April 19, 2024, 10:07:58 PM

News:

IonicWind Snippit Manager 2.xx Released!  Install it on a memory stick and take it with you!  With or without IWBasic!


Programming 6 - A Simple Window from Scratch

Started by GWS, May 02, 2010, 07:09:05 AM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

GWS

Hi,

Programming 6. - A GUI Window

We'll leave the nitty-gritty programming stuff for a while, and take a look at something more interesting.

Console windows have their uses, but are not very attractive for the user. 

So we'll now create a 'graphical user interface' ?? Sounds like something a stuffy committee came up with.
In plain words - a Window.  In fact we'll create two Windows, because there are two different types - but we'll leave the discussion of the second type (A Direct X window) for the Programming 7 section.

Normally, you wouldn't start from a blank canvas - you would load an outline window template which you would keep
somewhere as a starting point for each Windows project,  I call mine 'winskel.cba'. and I save it in a work folder.

Since we haven't got a starter window, we'll just begin from a blank editor screen.

If you have anything open in Creative already, do a 'File - Close' to close it, and then a 'File - New - Source file' to start a new
program.

Phew ! .. it's like starting a new book .. just a scary blank page ..

A GUI Window.

Here we go then .. we'll put a comment line at the start of the program - always a good idea to identify what it's about.


' Creating a Window in Creative Basic


(Copy and paste the lines of code as we do them .. )

The comment shows up in green (default colour) to indicate a Comment.
You can have as many comments as you like, so don't stint on them - scatter them around all your programs. They provide the description of what the program is doing, which will be prove helpful later.

Now we need some Definition statements to set up our working variables.


def w:window
def wstyle:int
def a$,newline:string


We're going to set up a window, and each window needs an identifying name, which will be referred to many times in a program.
For this program we'll just call it 'w', and it's 'type' is of course 'window'.

Every window has a 'style' - which controls it's appearance.  We'll call our style 'wstyle', and this variable is an 'int'(eger) type.

Since as the programmer, I have some idea what I'm going to do - I know I shall be putting some text on screen, so I require a string variable. I choose to call it 'a$' - although you can use any name you like.  It's type is 'string'.

I also know I shall require more than one line of text, so I need a 'carriage return' character to begin a new line.  I've named this variable 'newline', and again it's of type 'string'.

When you copy and paste the definitions, note the blue highlighting of the 'keywords' , and the red highlighting of the variable types.
This coloured highlighting helps to read the code, and picks out any mis-spellings, which will not be coloured.

Next we set the style for the window (to provide in this example for closure and minimisation), and the newline character ..


wstyle = @MINBOX
newline = chr$(10)


Finally, we write the statement to create the window ..


window w,0,0,600,400,wstyle,0,"Creative Basic",messages


The window name is just 'w', and it is to be located at window co-ordinates x=0, y=0.

To explain this - a screen has a 'resolution' of 'n by m' pixels.  Typically 1024x768 or 1280x1024 pixels, although other settings might be available for your graphics card. Values of x=0, y=0 correspond to the pixel located at the top left of the screen - so the top left corner of the window will be located there. The 'x' values increase from left to right - 'y' values increase from the top of the window to the bottom . (In this example, from y = 0 to y = 400).

The two following values  - 600 and 400, specify the width and height of the window in pixels.

Then comes the window style, followed by a ' 0 ', which indicates that this window has no parent window - it is the main window of the program.

There are many styles which can be used to control the window's functionality - check the User's Guide.
We have chosen to have just a 'minimise' icon and the close window cross icon.

Next comes a string of text which will be displayed in the caption of the window.  You can put anything useful here.

Finally comes the name of the subroutine which will handle all the messages for the window.  In this example, I've used the subroutine name 'messages', although you can name it whatever you like. 

Now we need the program closedown statements ..


waituntil w = 0
END


The 'waituntil' statement will go to sleep, waiting until the window's integer reference number becomes equal to 0 - that is, the window is closed.  As long as the window exists, it's reference number within the Windows system will be a some large integer value.  Each window has it's own reference.  When the window closes, the value becomes '0'.

So once the window is closed, the 'waituntil' check is then satisfied, and the program drops through to the 'END' statement. This then closes all windows, dialogs and open files, and clears all variables before returning control to Windows.

An alternative method of controlling the closedown of a program, is to use a separate integer variable (usually called 'run'), which is set initially to '1' for the program to run, and then set to '0' to close the program. See the first example program in Programming 2.

That's the window part of the program complete.  Now we just have to deal with the messages.

Messages.

As soon as a window is opened, messages start to flow, and will be seen by the message handling subroutine .  There are very many such messages which are sent, whenever events relating to the window occur.  Many of these will just pass through and be ignored.

Others we need to intercept and process , as the user interacts with the program and it's controls.

So we begin with the subroutine name statement, and the closing statement of the routine 'RETURN'.


SUB messages

RETURN


Messages relating to a window have identifiers.  The system variable @CLASS contains the message ID, and this variable can be checked for any of the messages types you wish to handle.

So we choose a selection of key messages we wish to respond to for this program.


select @CLASS
    case @IDCLOSEWINDOW
        closewindow w
    case @IDCONTROL
        if @controlID = 2 then closewindow w
endselect


We haven't covered this type of instruction yet, but it's easy to follow.

The 'select' command choses between a number of options for it's control variable ('@class' in this case), and executes the statements which are associated with a particular option.

For instance, if the @CLASS system variable message becomes equal to the @IDCLOSEWINDOW value, then the 'closewindow w' statement will be executed.  Of course, this will only be true if the user closes the window.

When the window is closed, the window variable becomes '0', and the 'waituntil w = 0' statement executes and closes the program.

If you haven't already copied the instructions into the editor , here is the program as it stands so far ..


' Creating a window in Creative Basic
def w:window
def wstyle,image1,image2:int
def a$,newline:string

wstyle = @MINBOX
newline = chr$(10)
' open a window ..
window w,0,0,600,400,wstyle,0,"Creative Basic",messages

waituntil w = 0
END

SUB messages
select @CLASS
case @IDCLOSEWINDOW
closewindow w
endselect
RETURN


You can run this program now, and you should find an uninspiring window at the top left of your screen.
This can be closed by clicking the close-window cross icon at the top right of the window.

Obviously some improvements are needed.  So we'll investigate some easy additions to the program.

Two very simple improvements are to centre the window on the screen, and to give it a bit of colour.
So if you place the folloiwng two statements just after the 'window ....' statement, we can do that.


setwindowcolor w, rgb(0,40,80)
centerwindow w


Run the program now, and we see a more civilised window.

Colours.

The 'setwindowcolor' command, sets the background colour of the window, using the RGB(r,g,b) function.

Colours are set by choosing values for the red, green, and blue components of colours.

These values range from 0 (no colour), to 255 (full colour).

So RGB(0,0,0) is black, RGB(255,255,255) is white.

A full red is obtained by RGB(255,0,0) - a full blue by RGB(0,0,255) .. and so on.
If all the values are equal, you get a shade of gray between black and white.

Take Control.

Now we'll take a look at a couple of controls to show how easy they are to set up in Creative Basic.

First we'll place a Text Box in the window in which we can display some text.
The statement which does this is ..

control w,"T,,(600-300)/2,30,300,200,@cteditcenter,1"


The 'w' specifies which window the control is in.

The 'T' shows it to be a Text Box, into which any text can be written or read.

Next come two ,,'s reserving a place in which any initial text could be placed. We will leave the box blank.

Then comes the placement of the control - it's 'x' and 'y' co-ordinates for the top left of the control.

Since our text box is to be 300 pixels wide, and 200 pixels high, to centre the control in the 600 pixel wide window, we use (600 - 300)/2 as the 'x' position - thus leaving equal space on each side.

The vertical position is chosen to be 30 pixels down.

Then come the actual width and height values 300x200 pixels.

Then come any control flags which  specify how the control will behave.  In this case, we want to centre any text in the Text Box, so we use the @cteditcenter flag.

Finally comes the control unique identifier.  This can be any integer value, but since this is the first control for window 'w', we use '1' as it's ID.

We could have used 10 or 100, or any value as long as we remember what we have chosen.

To make the control look nice, we can then set it's foreground (text) and background colours ..


setcontrolcolor w,1,rgb(55,255,160),rgb(0,50,70)


and to highlight the Text Box, we can place a Rectangle around it ..


rect w,149,29,302,202,rgb(0,150,150)


So now, we'll put some text in the box.


a$ = string$(2,newline) + "A Simple" + newline + "Creative Window"
setfont w,"Arial", 20, 700, @SFITALIC, 1
setcontroltext w,1,a$


First we set up the text we wish to display.  Note the string$() function used to include two 'newline' characters. which space the text verrtically.  Then come the two strings of characters we wish to display.

The desired font, size, weight(boldness) and format of the text are dealt with using the 'setfont' statement.

Font size is on a points basis, where 72 point is 1 inch high, 36 point is 0.5 inch high, and so on.

The 'weight' value ranges from 0 to 1000, with 700 being standard for bold text and 400 for normal text.

The flags can be @SFITALIC, @SFUNDERLINE, or @SFSTRIKEOUT for italicized, underlined, and strikeout fonts.

If a control ID is entered as the last value of a setfont statement, the font is applied to just that control - otherwise it will be applied to any subsequent text.

Finally, we'll place a Button in the window with which we can close the program.


control w,"B,Exit,(600-70)/2,310,70,30,0,2"


This statement follows the same pattern as the Text Box.  We specify 'B' to indicate a button control.

Then comes the text which will appear on the button - 'Exit'.

The button 'x' position is centred using (600 - 70)/2, and the 'y' position is chosen as 310 pixels down the window.

The width and height of the button are chosen as 70x30 pixels.

There are several possible flags which can be applied to a button - in this case we just use the default setting '0'.
(We could for instance have specified a button with a 'flat' appearance by using the flag @ctlbtnflat)

If you run the program now, the button will be there - but if you click it, nothing happens.

The reason is that although when you click the button, a message will be sent to Windows, we have not yet placed any message handling statement in our 'messages' subroutine to respond to the 'button clicked' message.

So we now place the following statements in the messages subroutine (after the 'closewindow statement' ..


case @IDCONTROL
    if @controlID = 2 then closewindow w


These statements deal with the case when @CLASS indicates that this is a message from a control, in it's @IDCONTROL value.

In other words, a user event has occurred relating to one of the window's controls.  But which one .. ?

The @CONTROLID variable will indicate which control has been activated.

In our example control ID '2' is the Exit button.

When this message occurs, we simply close window 'w' - and the program exits, since the window's identifier becomes '0', and the main 'waituntil w = 0' statement executes to close the program.

If you run the program now, it's looking pretty good, and the Exit button is functional.

In fact it might be useful to save the program in a separate folder containing useful bits and pieces of code.  You could name this one something like 'winskel.cba' as a starting skeleton for any future windows program.  Then all you need do is add additional controls, or delete things you don't need, and you've got a good start to your next project.

We're almost done - but just to make the window look a bit more artistic, we'll place a couple of images on the screen.

You will find many programs will require some artistic resources, which will need a bit of preparation using some program like good old Windows Paint, or some other graphics program.

I've attached a couple of .jpg images to the .zip of this program's complete source code.  Just create a folder to hold the program and unzip the code and images into it.

To load the images, we use the loadimage() function like this :


image1 = loadimage(getstartpath + "silverbirch1.jpg",@IMGSCALABLE)
image2 = loadimage(getstartpath + "silverbirch2.jpg",@IMGSCALABLE)


The images are loaded and theri ID's stored in two integer variables 'image1' and 'image2'.

'getstartpath' specifies that the images can be found in the same folder the program is started from.

Then follows the image file names, and the image type flag - in this case @IMGSCALABLE.
(See the User Guide for the various flags that may apply).

All we need to do then, is to display the images at some chosen locations on screen, using the ShowImage command.


SHOWIMAGE w, image1, @IMGSCALABLE,28,80,85,125}
SHOWIMAGE w, image2, @IMGSCALABLE,485,80,82,125}


These commands apply to window 'w', and will display the named images.
The type of images are the same as that used when loading them.
The first two numbers are the 'x','y' co-ordinates to position the images, and the last two numbers specify the size they are to be scaled to for display.

There we are then - a rather smart window with some pretty pictures - what more could we ask ?
Well, in fact there are lots more things we could do, but we'll leave those discussions 'til later.

End of Programming 6
______________________________________________
























Tomorrow may be too late ..