Because the procedures and functions do not form part of your program the size of its file is reduced, and if a bug is found in one of the functions it can be corrected by updating the library file without having to modify each of the programs in which it is used.
You can build up your own library of such files, but BBC BASIC for Windows is supplied with the following modules:
The library should be loaded from your program using the command:
INSTALL @lib$+"ARRAYLIB"
The functions contained are:
In BBC BASIC for Windows version 3.00a and later several of these operations are incorporated within the interpreter. Using the built-in operations will be considerably faster than using the library routines; see the Array arithmetic section for details. The library routines which are not supported as built-in operations are PROC_transpose, PROC_invert and FN_det.When executed this program will print:DIM N(3) N() = 1, 2, 3, 4 PROC_add(N(), 5) PRINT N(0),N(1),N(2),N(3)
6 7 8 9
When executed this program will print:DIM N(3) N() = 1, 2, 3, 4 PROC_mul(N(), 2) PRINT N(0),N(1),N(2),N(3)
2 4 6 8
When executed this program will print:DIM N(3), S(3) N() = 1, 2, 3, 4 S() = 5, 6, 7, 8 PROC_sum(N(), S()) PRINT N(0),N(1),N(2),N(3)
6 8 10 12
When executed this program will print:DIM N(0,2), S(2,1), D(0,1) N() = 1, 2, 3 S() = 4, 5, 6, 7, 8, 9 PROC_dot(N(), S(), D()) PRINT D(0,0) D(0,1)
40 46
When executed this program will print:DIM N(1,2), T(2,1) N() = 1, 2, 3, 4, 5, 6 PROC_transpose(N(), T()) PRINT T(0,0) T(0,1) PRINT T(1,0) T(1,1) PRINT T(2,0) T(2,1)
1 4
2 5
3 6
When executed this program will print:DIM M(2,2) M() = 2,0,6,8,1,-4,0,5,7 PROC_invert(M()) PRINT M(0,0) M(0,1) M(0,2) PRINT M(1,0) M(1,1) M(1,2) PRINT M(2,0) M(2,1) M(2,2)
0.09184 0.10204 -0.02041 -0.19048 0.04762 0.19048 0.13605 -0.03401 0.00680
When executed this program will print:DIM M(2,2) M() = 2,0,6,8,1,-4,0,5,7 PRINT FN_mod(M())
13.96424
When executed this program will print:DIM M(2,2) M() = 2,0,6,8,1,-4,0,5,7 PRINT FN_det(M())
294
The library should be loaded from your program using the command:
INSTALL @lib$+"WINLIB"
The functions contained are:
The following program segment creates a status bar containing the string "Press F1 for Help":
hstat% = FN_createstatusbar("Press F1 for help")
Note that BASIC's output window is not automatically made
smaller to accommodate the status bar. You should use the
VDU 24 and/or VDU 28 commands
to reduce the size of the graphics and/or text windows to suit.
If you want the status bar to resize itself automatically when the size of the main window changes (e.g. as the result of the user dragging a corner) you should forward the size-change message as follows:
You should remove the status bar by calling PROC_removestatusbar before your program exits or returns to immediate mode. It is good practice to trap errors (using ON ERROR ) and to remove the status bar if an unexpected error occurs.ON MOVE SYS "PostMessage",hstat%,@msg%,@wparam%,@lparam% : RETURN
Once you have created a basic status bar, you can use Windows™ API functions to divide it into a number of parts and write different text in each part. The following program segment illustrates how to split the status bar into three parts; hstat% is the value returned from the FN_createstatusbar function.
The first DATA statement determines the width of each part, by specifying the position of its right-hand edge (in pixels). The second DATA statement determines the text which will appear in each part; the CHR$9 character causes the text to be displayed centrally.nparts% = 3 DIM edges%(nparts%-1) FOR N% = 0 TO nparts%-1 READ edges%(N%) NEXT N% SYS "SendMessage", hstat%, 1028, nparts%, ^edges%(0) FOR N% = 0 TO nparts%-1 READ text$ SYS "SendMessage", hstat%, 1025, N%, CHR$9+text$ NEXT N% DATA 440, 540, 640 DATA Part 1, Part 2, Part 3
The following program segment creates a toolbar containing three buttons: a cut button, a copy button and a paste button:
The button% array contains the button types and the buttid% array contains the button identifiers (which are used to identify the buttons, and to determine which button has been clicked). If the button identifier is zero this signifies a separator rather than a button.nbutts% = 3 DIM button%(nbutts%-1), buttid%(nbutts%-1) button%() = 0, 1, 2 buttid%() = 100, 101, 102 htool% = FN_createtoolbar(nbutts%,button%(),buttid%())
In version 1.7 and later of the WINLIB library you can specify a negative identifier value. This creates an auto toggle button which alternates between the 'pressed' and 'unpressed' states when you click on it. In this case the actual identifier value allocated to the button is minus the value specified in the buttid% array.
The available button types are as follows:
Note that BASIC's output window is not automatically made smaller to accommodate the toolbar. You should use the VDU 24 and/or VDU 28 commands to reduce the size of the graphics and/or text windows to suit.
Value Button 0 Cut 1 Copy 2 Paste 3 Undo 4 Redo 5 Delete 6 New 7 Open 8 Save 9 Find 10 Print Preview 11 Help 12 Find 13 Replace 14 15 no image
If you want the toolbar to resize itself automatically when the size of the main window changes (e.g. as the result of the user dragging a corner) you should forward the size-change message as follows:
You should remove the toolbar by calling PROC_removetoolbar before your program exits or returns to immediate mode. It is good practice to trap errors (using ON ERROR ) and to remove the toolbar if an unexpected error occurs.ON MOVE SYS "PostMessage",htool%,@msg%,@wparam%,@lparam% : RETURN
Once you have created a toolbar, clicking on the buttons will cause messages to be sent to your program which can be detected with ON SYS, in exactly the same way as a selection from a menu bar. The @wparam% value will be the button identifier you chose. Alternatively you can automate the process and avoid the need to use ON SYS in your code by allocating the identifier using FN_setproc in WINLIB5.
You can use Windows™ API functions to determine the appearance of the buttons. The following program segment illustrates how to cause a button to be disabled (greyed out); htool% is the value returned from the FN_createtoolbar function:
Some of the possible button states are:state% = 0 SYS "SendMessage", htool%, 1041, buttid%, state%
You can discover the current state of a button as follows:
0 Disabled 4 Enabled 6 Pressed 8 Hidden
In the case of an auto toggle button which has been toggled to the 'pressed' state, the returned value is one greater than those shown. So 5 signifies that it has been toggled to the 'pressed' state and 7 that it is also being pressed by the user.SYS "SendMessage", htool%, 1042, buttid%, 0 TO state%
The function returns TRUE if the button image was successfully changed, and FALSE otherwise (most likely because the specified file could not be read or has an invalid format). You can customise as many buttons as you like by calling this function multiple times with different values of buttid%; alternatively you can customise multiple buttons from a single bitmap file using the FN_custombuttons function to be found in the WINLIB3 library.
The following program segment illustrates how to customise a button image:
When initially creating the toolbar set the button 'type' of any custom buttons to 15 (no image). Also ensure that the background colour of your bitmap file is R=192, G=192, B=192 (&C0C0C0). These measures will ensure that your custom images are displayed correctly.ok% = FN_custombutton(htool%, "\pictures\bmp\owl.bmp", 102)
Four parameters must be supplied: the handle of the toolbar (as returned from FN_createtoolbar), the number of buttons for which you want to provide tips, an array of strings containing the tips to be displayed and an integer array of identifier values for the appropriate buttons.
The following program segment illustrates how to add tooltips to the toolbar created in the earlier example:
The buttid% array may often be the same as that passed to FN_createtoolbar.nbutts% = 3 DIM buttip$(nbutts%-1), buttid%(nbutts%-1) buttip$() = "Cut", "Copy", "Paste" buttid%() = 100, 101, 102 PROC_addtooltips(htool%,nbutts%,buttip$(),buttid%())
The library should be loaded from your program using the command:
The functions contained are:INSTALL @lib$+"WINLIB2"
The supplied example program DLGEDIT.BBC can simplify the creation of dialogue boxes by providing a 'visual' editor and generating some of the required BBC BASIC code automatically.
The string title$ specifies the title of the dialogue box, which is displayed in its title bar. The values x% and y% specify the initial position of the dialogue box, with respect to the top left corner of your program's window. The values cx% and cy% specify the width and height, respectively, of the dialogue box.dlg% = FN_newdialog(title$,x%,y%,cx%,cy%,font%,size%)
The value font% specifies the size, in points, of all the text strings in the dialogue box, and it also determines the size of the units used to specify the position and size of the box. Therefore, if you change the size of the text all the other dimensions of the dialogue box are scaled to suit. A common value to use is 8.
The value size% specifies the number of bytes of memory to allocate for the dialogue box template. As a rule of thumb this can be set to approximately the number of individual items within the dialogue box multiplied by 50; if the value is too small you will receive the error message No room for dialogue template when the items are created. There is no harm, apart from wasted memory, in making it too big.
The returned value (dlg% in this case) identifies the dialogue box, and must be stored for use in the subsequent procedures.
Normally a dialogue box has a title bar. This can be eliminated by adding an extra line after the call to FN_newdialog as follows:
dlg% = FN_newdialog("",x%,y%,cx%,cy%,font%,size%)
dlg%!16 AND= &FF7FFFFF
Note, however, that if you do this the user won't be able to move the dialogue box,
so you may need to set its position more carefully.
All dialogue boxes should have at least one pushbutton, labelled OK, which enables the user to confirm that his input is complete:
The value dlg% identifies the dialogue box, and is the value returned from FN_newdialog. The string text$ specifies the text to appear inside the button (e.g. "OK"), the values x% and y% specify the position of the button within the dialogue box and the values cx% and cy% specify the size of the button (in dialogue box units).PROC_pushbutton(dlg%,text$,id%,x%,y%,cx%,cy%,style%)
The value id% is a unique identifier of the pushbutton; all the items within a particular dialogue box must have different values. You can choose any value (within reason) but the values 1 and 2 are reserved for the OK and Cancel buttons respectively so should only be used for that purpose.
The value style% can be zero, but other values allow you to modify the appearance or behaviour of the pushbutton. Setting it to 1 causes the pushbutton to be the default button: it is displayed with a thicker border and pressing the Enter key has the same effect as pressing that button. There should only be one button in each dialogue box with this style; typically you would use it for the OK button. Setting style% to &20000 causes the button to be the first item in a new group; this affects navigation of the dialogue box using the cursor keys. Setting style% to &80 indicates that the button will display a bitmap image (see Initialising the contents of a dialogue box); in this case text$ should be empty. The values can be combined.
The value dlg% identifies the dialogue box, and is the value returned from FN_newdialog. The string text$ specifies the text to appear alongside the check box, the values x% and y% specify the position of the check box within the dialogue box and the values cx% and cy% specify the size of the check box and its associated text (in dialogue box units). The value id% is a unique identifier for the check box.PROC_checkbox(dlg%,text$,id%,x%,y%,cx%,cy%,style%)
The value style% can be zero, but other values allow you to modify the appearance or behaviour of the check box. Setting it to &20 causes the associated text to appear to the left of the check box rather than to the right. Setting it to &20000 causes the check box to be the first item in a new group; this affects navigation of the dialogue box using the cursor keys. The values can be combined.
The value dlg% identifies the dialogue box, and is the value returned from FN_newdialog. The string text$ specifies the text to appear alongside the radio button, the values x% and y% specify the position of the radio button within the dialogue box and the values cx% and cy% specify the size of the radio button and its associated text (in dialogue box units). The value id% is a unique identifier for the radio button.PROC_radiobutton(dlg%,text$,id%,x%,y%,cx%,cy%,style%)
The value style% can be zero, but other values allow you to modify the appearance or behaviour of the radio button. Setting it to &20 causes the associated text to appear to the left of the radio button rather than to the right. Setting it to &20000 causes the radio button to be the first item in a new group; this has special significance for radio buttons, since only one radio button in a group can be checked at any one time. The values can be combined.
The value dlg% identifies the dialogue box, and is the value returned from FN_newdialog. The string text$ specifies the text to appear in the top edge of the group box, the values x% and y% specify the position of the group box within the dialogue box and the values cx% and cy% specify the size of the group box (in dialogue box units). The value id% is a unique identifier for the group box.PROC_groupbox(dlg%,text$,id%,x%,y%,cx%,cy%,style%)
The value style% may be zero, but will often have the value &20000 signifying that the group box is the first item in a new group.
The value dlg% identifies the dialogue box, and is the value returned from FN_newdialog. The string text$ specifies the initial text (if any) to appear in the edit box, the values x% and y% specify the position of the edit box within the dialogue box and the values cx% and cy% specify the size of the edit box (in dialogue box units). The value id% is a unique identifier for the edit box.PROC_editbox(dlg%,text$,id%,x%,y%,cx%,cy%,style%)
The value style% can be zero, but other values allow you to modify the appearance or behaviour of the edit box. Setting it to &80 causes the contents of the edit box to scroll horizontally, if necessary. Setting it to &2000 causes the edit box to accept only numeric input. Setting it to &20000 causes the edit box to be the first item in a new group. Setting it to &1004 (along with an appropriate vertical size) creates a multi-line edit box. The values can be combined.
The value dlg% identifies the dialogue box, and is the value returned from FN_newdialog. The string text$ specifies the required text (if any), the values x% and y% specify the position of the rectangle within the dialogue box and the values cx% and cy% specify the size of the rectangle (in dialogue box units). The value id% is a unique identifier for the static item.PROC_static(dlg%,text$,id%,x%,y%,cx%,cy%,style%)
The value style% may be zero, but other values allow you to modify the appearance of the static item. By default text is left-justified within the rectangle but setting style% to 1 causes the text to be centred within the rectangle and setting it to 2 causes the text to be right-justified within the rectangle. Setting style% to &E indicates that the item will contain a bitmap image to be loaded later (see Initialising the contents of a dialogue box); in this case text$ should be empty.
The value dlg% identifies the dialogue box, and is the value returned from FN_newdialog. The text string is unused and should be set to an empty string, the values x% and y% specify the position of the list box within the dialogue box and the values cx% and cy% specify the size of the list box (in dialogue box units). The value id% is a unique identifier for the list box.PROC_listbox(dlg%,"",id%,x%,y%,cx%,cy%,style%)
The value style% can be zero, but other values allow you to modify the appearance or behaviour of the list box. For example setting it to &20000 causes the list box to be the first item in a new group. To disable automatic sorting of the listbox contents subtract 2 from the style% value you would otherwise have used (e.g. use –2 instead of zero or &1FFFE instead of &20000). Adding &100000 to style% results in the list box having a horizontal scroll bar if there are too many items to fit in the box at once.
The items to be displayed in the list box must be written as a separate exercise once the dialogue box has been displayed. See Initialising the contents of a dialogue box for details. If the height of the list box is insufficient for the number of items to be displayed, a scroll bar is automatically generated.
The value dlg% identifies the dialogue box, and is the value returned from FN_newdialog. The text string is unused and should be set to an empty string, the values x% and y% specify the position of the combo box within the dialogue box and the values cx% and cy% specify the size of the combo box (in dialogue box units). The value id% is a unique identifier for the combo box.PROC_combobox(dlg%,"",id%,x%,y%,cx%,cy%,style%)
The value style% can be zero, but other values allow you to modify the appearance or behaviour of the combo box. Setting it to 3 creates a drop down list, where the list of items from which the selection can be made is only displayed when the user clicks on the arrow button (note particularly that in this case cy% is the dropped down height of the box). Setting it to &100 causes the items in the list to be sorted into alphabetical order. Setting it to &20000 causes the combo box to be the first item in a new group. The values can be combined.
The items to be displayed in the combo box list must be written as a separate exercise once the dialogue box has been displayed. See Initialising the contents of a dialogue box for details. In the case of a drop-down list the height of the combo box should be made sufficient for the list when it is displayed.
The value dlg% identifies the dialogue box, and is the value returned from FN_newdialog. The values x% and y% specify the position of the item within the dialogue box and the values cx% and cy% specify the size of the item (in dialogue box units). The values of text$, style% and class% depend on the type of item. The value id% is a unique identifier for the item.PROC_dlgitem(dlg%,text$,id%,x%,y%,cx%,cy%,style%,class%)
This allows you to embed in your dialogue box standard Windows™ controls for which dedicated procedures are not provided. Examples of such controls are up-down controls and trackbars:PROC_dlgctrl(dlg%,text$,id%,x%,y%,cx%,cy%,style%,class$)
This item must immediately follow a numeric edit box in which the value controlled by the up and down arrows appears. The up-down control automatically positions itself at the right-hand end of the edit box (the position values are unused and are set to 0,0).PROC_dlgctrl(dlg%,"",id%,0,0,cx%,cy%,&50000096,"msctls_updown32")
To set the range of the up-down control (which must be done after the PROC_showdialog):
SYS "SendDlgItemMessage", !dlg%, id%, &465, 0, (min% << 16) + max%
The above example creates a horizontal trackbar with no tick-marks. To alter the style of the trackbar add one or more of the following values to the &50000000:PROC_dlgctrl(dlg%,"",id%,x%,y%,cx%,cy%,&50000000,"msctls_trackbar32")
To set the range of the trackbar (which must be done after the PROC_showdialog):
Style Effect 0 Horizontal trackbar with no tick marks 1 Show tick marks 2 Vertical trackbar 4 Tick marks to top or left (default is bottom or right)
To set the current position of the trackbar:SYS "SendDlgItemMessage", !dlg%, id%, 1030, 1, (max% << 16) + min%
To read the current position of the trackbar:SYS "SendDlgItemMessage", !dlg%, id%, 1029, 1, position%
SYS "SendDlgItemMessage", !dlg%, id%, 1024, 0, 0 TO position%
The value dlg% identifies the dialogue box, and is the value returned from FN_newdialog. Once the dialogue box has been displayed, you can send messages to it to affect its contents, and request information about its current contents.PROC_showdialog(dlg%)
To change the text associated with a dialogue box item (which may for example be the contents of an edit box or a label for a check box) you can use the SetDlgItemText API call:
The value !dlg% (note the exclamation mark) is the handle of the dialogue box, which is contained in memory at the address returned from FN_newdialog. The value id% is the identifier for the item in question and text$ is the new text string to be associated with the item.SYS "SetDlgItemText", !dlg%, id%, text$
If the item is an edit box used for numeric entry, the value displayed in the box can be set with SetDlgItemInt:
The value !dlg% is the handle of the dialogue box, id% is the identifier for the item in question, value% is the new value to display and signed% determines whether the value should be interpreted as signed (1) or unsigned (0).SYS "SetDlgItemInt", !dlg%, id%, value%, signed%
If the value is controlled by an up-down control you can set the allowed range as follows:
where id% is the identifier for the up-down control, min% is the lowest value permitted and max% is the highest value permitted.SYS "SendDlgItemMessage", !dlg%, id%, &465, 0, (min% << 16) + max%
To load a bitmap image into a static item or a pushbutton you should use the following program segment. In the case of a pushbutton change &172 to &F7 in the second line:
The value bmpfile$ is the name of a Windows™ bitmap file containing the image, cx% and cy% are the dimensions of the image in pixels, !dlg% is the handle of the dialogue box and id% is the identifier for the static item or pushbutton in question. Once you have finished with the dialogue box (but not before) delete the bitmap handle as follows:SYS "LoadImage", 0, bmpfile$, 0, cx%, cy%, 16 TO hbitmap% SYS "SendDlgItemMessage", !dlg%, id%, &172, 0, hbitmap%
SYS "DeleteObject", hbitmap%
To enter the list of strings into a list box you should do the following:
where the value id% is the identifier for the list box. The list box will (by default) sort the strings into alphabetical order, so the order in which they are sent is not important. To disable sorting subtract 2 from the style% value you would otherwise have used (see PROC_listbox).SYS "SendDlgItemMessage", !dlg%, id%, &180, 0, "Listbox item 0" SYS "SendDlgItemMessage", !dlg%, id%, &180, 0, "Listbox item 1" SYS "SendDlgItemMessage", !dlg%, id%, &180, 0, "Listbox item 2" etc.
To empty a list box of its contents do:
SYS "SendDlgItemMessage", !dlg%, id%, &184, 0, 0
To enter the list of strings into a combo box you should do the following:
where the value id% is the identifier for the combo box. In this case the items are not sorted (by default), so they must be sent in the order in which they should appear. The initial selection from the list should be made as follows:SYS "SendDlgItemMessage", !dlg%, id%, &143, 0, "Combobox item 0" SYS "SendDlgItemMessage", !dlg%, id%, &143, 0, "Combobox item 1" SYS "SendDlgItemMessage", !dlg%, id%, &143, 0, "Combobox item 2" etc.
The value index% determines which of the items is initially selected (starting at 0).SYS "SendDlgItemMessage", !dlg%, id%, &14E, index%, 0
To empty a combo box of its contents do:
SYS "SendDlgItemMessage", !dlg%, id%, &14B, 0, 0
To initialise the state of a set of radio buttons, you can use the CheckRadioButton API call:
Here first% is the identifier of the first radio button in the group, last% is the identifier of the last radio button in the group and id% is the identifier of the button you want to be checked.SYS "CheckRadioButton", !dlg%, first%, last%, id%
To initialise the state of a check box, you can use the CheckDlgButton API call:
Here id% is the identifier of the button you want to affect and state% is the state you wish it to have: 0 signifies unchecked and 1 signifies checked.SYS "CheckDlgButton", !dlg%, id%, state%
To disable an item you can use the EnableWindow API call:
Here id% is the identifier of the button you want to affect. To re-enable the item change the zero to a one:SYS "GetDlgItem", !dlg%, id% TO h% SYS "EnableWindow", h%, 0
Note that, as with initialisation, these routines must be executed after the call to PROC_showdialog.SYS "GetDlgItem", !dlg%, id% TO h% SYS "EnableWindow", h%, 1
To read the text associated with a dialogue box item (which may for example be the contents of an edit box or the current selection of a combo box) you can use the GetDlgItemText API call:
The parameter dlg% is the value returned from FN_newdialog and the parameter id% is the identifier for the item in question. The maximum length of the string is 255 characters.DEF FNgetdlgtext(dlg%, id%) LOCAL text% DIM text% LOCAL 255 SYS "GetDlgItemText", !dlg%, id%, text%, 255 = $$text%
In the case of a multi-line edit box the maximum length should be set to an appropriate value (up to a maximum of 65535 bytes). To save the returned data to a file you can do the following:
The data returned from a multi-line edit box consists of lines of text separated by CRLF (CHR$13+CHR$10) sequences. If you want to process the data you can split it into individual lines as follows:DEF PROCsavetofile(dlg%,id%,filename$) LOCAL text%, Len% DIM text% LOCAL 65535 SYS "GetDlgItemText", !dlg%, id%, text%, 65535 TO Len% OSCLI "SAVE """+filename$+""" "+STR$~text%+"+"+STR$~Len% ENDPROC
If the item is an edit box used for numeric entry, the current value can be read with GetDlgItemInt:P% = text% REPEAT A$ = $P% : REM. get line of text from memory PRINT A$ : REM. print the text (for example) P% += LEN(A$)+2 : REM. advance pointer to next line UNTIL P% >= (text%+Len%)
The value !dlg% is the handle of the dialogue box, id% is the identifier for the item in question and signed% determines whether a negative value should be accepted (1) or not (0).SYS "GetDlgItemInt", !dlg%, id%, 0, signed% TO value%
To determine which item (if any) is selected in a list box you can do the following:
where the value id% is the identifier for the list box. The returned value sel% gives the index (starting at 0) of the currently selected item. If no item is selected, –1 is returned. Note that if the listbox contents have been sorted, which is the default behaviour, knowing the index alone is of little value. However you can use it to discover the selected text as follows:SYS "SendDlgItemMessage", !dlg%, id%, &188, 0, 0 TO sel%
To determine which item is selected in a combo box do the following:DEF FNgetlistboxtext(dlg%, id%, sel%) LOCAL text% DIM text% LOCAL 255 SYS "SendDlgItemMessage", !dlg%, id%, &189, sel%, text% = $$text%
To discover the current state of a check box or radio button, you can use the IsDlgButtonChecked API call:SYS "SendDlgItemMessage", !dlg%, id%, &147, 0, 0 TO sel%
where the value id% is the identifier for the check box or radio button. The value state% is set to 0 if the button is not checked and to 1 if it is checked.SYS "IsDlgButtonChecked", !dlg%, id% TO state%
The following code segment can be used to wait for the OK or Cancel button to be clicked, and then take appropriate action:
Since clicking the close button of a dialogue box (or floating toolbar) always produces the same ID code (2) you cannot directly tell from ON SYS which dialogue box or toolbar was closed. If your program has more than one open at the same time this could be a problem. You can determine which are still open (and therefore, by a process of elimination, which was closed) by examining the window handles (!dlg% in the above example). If the handle is non-zero the window is still open, and if it is zero it has been closed.click% = 0 ON SYS click% = @wparam% AND &FFFF : RETURN REPEAT pause% = INKEY(1) : UNTIL click% = 1 OR click% = 2 OR !dlg% = 0 ON SYS OFF IF click% = 1 THEN PRINT "OK pressed" REM. process contents of dialogue box here ELSE PRINT "Cancel pressed" ENDIF PROC_closedialog(dlg%)
The dialogue box template remains in memory, so you can display it again at any time by calling PROC_showdialog.PROC_closedialog(dlg%)
The dialogue box should also be removed whenever your program returns to immediate mode (for example if an error occurs or the END statement is executed) or when your program's window is closed by the user. This can be achieved by executing the following statements immediately after the call to PROC_showdialog:
Because the dialogue box uses space on the heap, it is essential that you remove it before executing a CLEAR, CHAIN or RUN statement. Failure to do so is very likely to crash BBC BASIC for Windows.ON CLOSE PROC_closedialog(dlg%):QUIT ON ERROR PROC_closedialog(dlg%):PRINT'REPORT$:END
INSTALL @lib$+"WINLIB3"
The functions contained are:
Normally the floating toolbar has a title bar. This can be eliminated by adding an extra line after the call to FN_createfloatingtoolbar as follows:
Note, however, that if you do this the user won't be able to move the toolbar, so you may need to set its position more carefully.ftb% = FN_createfloatingtoolbar(nbutts%,button%(),buttid%(),50,50,"") ftb%!16 AND= &FF7FFFFF
See FN_createtoolbar for more details. If you want to send messages to the toolbar (for example to control the appearance of the buttons) you can do so using the means described under FN_createtoolbar, but note that the value returned from FN_createfloatingtoolbar is a pointer to the toolbar handle not the handle itself. For example, to cause a button to be disabled (greyed out):nbutts% = 3 DIM button%(nbutts%-1), buttid%(nbutts%-1) button%() = 0, 1, 2 buttid%() = 100, 101, 102 ftb% = FN_createfloatingtoolbar(nbutts%,button%(),buttid%(),50,50,"Floating") PROC_showfloatingtoolbar(ftb%)
Note that you can only send messages to a floating toolbar after it has been displayed with PROC_showfloatingtoolbar.SYS "SendMessage", !ftb%, 1041, buttid%, 0
Because FN_createfloatingtoolbar reserves space on the heap, it is essential that you remove the toolbar before executing a CLEAR, CHAIN or RUN statement. Failure to do so is very likely to crash BBC BASIC for Windows.PROC_removefloatingtoolbar(ftb%)
The function returns TRUE if the button images were successfully changed, and FALSE otherwise (most likely because the specified file could not be read or has an invalid format). You can customise as many buttons as you like by providing a bitmap with suitable dimensions.
Note that when used with a floating tool bar the value returned from FN_createfloatingtoolbar is a pointer to the toolbar handle not the handle itself. So to customise all the buttons in a floating toolbar:
When initially creating the toolbar set the button 'type' of any custom buttons to 15 (no image). Also ensure that the background colour of your bitmaps is R=192, G=192, B=192 (&C0C0C0). These measures will ensure that your custom images are displayed correctly.ok% = FN_custombuttons(!ftb%, "birds.bmp", nbutts%, buttid%())
The values can be combined.
Style Effect 0 Horizontal trackbar with no tick marks 1 Show tick marks 2 Vertical trackbar 4 Tick marks to top or left (default is bottom or right)
To create and display a horizontal trackbar with tick marks, suitable for selecting a value between zero and ten:
tb% = FN_createtrackbar(@hwnd%, 100, 200, 20, 300, 1) PROC_showtrackbar(tb%, 10)
Normally the trackbar is moved by the user, but if you want your program to move it to a specific position you can do that as follows:trackpos% = FN_trackbarpos(tb%)
(note the exclamation mark in !tb%).SYS "SendMessage", !tb%, 1029, 1, trackpos%
Because FN_createtrackbar reserves space on the heap, it is essential that you remove the trackbar before executing a CLEAR, CHAIN or RUN statement. Failure to do so is very likely to crash BBC BASIC for Windows.PROC_removetrackbar(tb%)
The values may be combined.
Style Effect 1 Progress 'blocks' are contiguous 4 The progress bar is vertical
To create and display a progress bar, suitable for showing a value between zero and ten:
pb% = FN_createprogressbar(@hwnd%, 100, 200, 20, 300, 0) PROC_showprogressbar(pb%, 10)
You can also set the progress bar to an absolute value as follows:PROC_stepprogressbar(pb%, 1)
SYS "SendMessage", !pb%, 1026, progress%, 0
Because FN_createprogressbar reserves space on the heap, it is essential that you remove the progress bar before executing a CLEAR, CHAIN or RUN statement. Failure to do so is very likely to crash BBC BASIC for Windows.PROC_removeprogressbar(pb%)
INSTALL @lib$+"WINLIB4"
The functions contained are:
Property sheets and wizards are very similar, both effectively consisting of multiple dialogue box pages within a single window (only one page being displayed at a given time). They differ principally in the way the individual pages are selected: in a property sheet the pages can be selected in any order (each has a tab which can be clicked by the user), whereas in a wizard the pages must be selected sequentially by means of Next and Back buttons.Because property sheets and wizards are like multiple dialogue boxes, this is exactly how they are created in BBC BASIC for Windows. Each page must be created using the FN_newdialog function in the WINLIB2 library. However, unlike conventional dialogue boxes, you should not include OK, Apply or Cancel buttons in the individual pages.
Instead of displaying the individual dialogue boxes with PROC_showdialog they are grouped together as a property sheet or wizard using FN_newpropsheet and displayed using PROC_showpropsheet.
The following program segment creates a property sheet containing three dialogue box pages:
pages% = 3
DIM page%(pages%-1)
page%(0) = FN_newdialog("First page", 32, 32, 288, 128, 8, 650)
REM create the contents of the first page here
page%(1) = FN_newdialog("Second page", 32, 32, 288, 128, 8, 1100)
REM create the contents of the second page here
page%(2) = FN_newdialog("Third page", 32, 32, 288, 128, 8, 1100)
REM create the contents of the third page here
psh% = FN_newpropsheet("Property sheet",pages%,0,0,page%())
Following each FN_newdialog call the contents of
the relevant page are created using the procedures provided in
WINLIB2, e.g.
PROC_static, PROC_editbox etc.
If a wizard rather than a property sheet is wanted, the last line would be:
psh% = FN_newpropsheet("Property sheet",pages%,0,&20,page%())
The following program segment displays the property sheet or wizard created above:
DIM hdlg%(pages%-1) PROC_showpropsheet(psh%,hdlg%())
The methods for doing this are identical to those listed in Initialising the contents of a dialogue box except that whenever the dialogue box handle is needed you must supply an element from the hdlg%() array returned from PROC_showpropsheet rather than the value pointed to by FN_newdialog. For example, to change the text associated with an item in the first page of the property sheet or wizard:
You should normally ensure that the item identifier id% is unique rather than being used in two or more different pages. If the specified item is not in the page corresponding to the specified dialogue box handle, the call will fail.SYS "SetDlgItemText", hdlg%(0), id%, text$
The following code segment can be used to wait for the OK, Finish or Cancel button to be clicked, and then take appropriate action:
click% = 0 ON SYS click% = @wparam% AND &FFFF : RETURN REPEAT pause% = INKEY(1) : UNTIL click% = 1 OR click% = 2 ON SYS OFF IF click% = 1 THEN PRINT "OK or Finish pressed" REM process contents of property sheet here ELSE PRINT "Cancel pressed" ENDIF PROC_closepropsheet(psh%)
You can do this by monitoring the current page handle, which can be determined by means of an API call. For example, the loop for monitoring which buttons are pressed can be modified to check also for page changes as follows:
ON SYS click% = @wparam% AND &FFFF : RETURN
oldhdlg% = 0
REPEAT
click% = 0
REPEAT pause% = INKEY(1)
SYS "SendMessage", !psh%, &476, 0, 0 TO hdlg%
UNTIL click%<>0 OR hdlg%<>oldhdlg%
IF hdlg%<>oldhdlg% THEN
oldhdlg% = hdlg%
CASE hdlg% OF
WHEN hdlg%(0): SYS "SendMessage", !psh%, &470, 0, 2 : REM Next only
WHEN hdlg%(1): SYS "SendMessage", !psh%, &470, 0, 3 : REM Back and Next
WHEN hdlg%(2): SYS "SendMessage", !psh%, &470, 0, 5 : REM Back and Finish
ENDCASE
ENDIF
CASE click% OF
WHEN 1: PRINT "Finish pressed"
REM Process contents of wizard here
WHEN 2: PRINT "Cancel pressed"
ENDCASE
UNTIL hdlg% = 0
PROC_closepropsheet(psh%)
The above example is for a wizard with three pages. According to which page is
currently displayed the Back, Next and Finish buttons
are displayed appropriately.
The methods for doing this are identical to those listed in Reading the contents of a dialogue box except that whenever the dialogue box handle is needed you must supply an element from the hdlg%() array returned from PROC_showpropsheet rather than the value pointed to by FN_newdialog. For example, to read the text associated with an item in the second page of the property sheet or wizard:
DIM text% 255 SYS "GetDlgItemText", hdlg%(1), id%, text%, 255 content$ = $$text%
The property sheet templates remain in memory, so you can display it again at any time by calling PROC_showpropsheet.PROC_closepropsheet(psh%)
The property sheet or wizard should also be removed whenever your program returns to immediate mode (for example if an error occurs or the END statement is executed) or when your program's window is closed by the user. This can be achieved by executing the following statements immediately after the call to PROC_showpropsheet:
Because the property sheet uses space on the heap, it is essential that you remove it before executing a CLEAR, CHAIN or RUN statement. Failure to do so is very likely to crash BBC BASIC for Windows.ON CLOSE PROC_closepropsheet(psh%):QUIT ON ERROR PROC_closepropsheet(psh%):PRINT'REPORT$:END
The WINLIB5 library contains a set of procedures and functions for incorporating push buttons, edit boxes etc. in your program without the need to create a dialogue box to contain them. The library should be loaded from your program using the command:
INSTALL @lib$+"WINLIB5"
The functions contained are:
The value id% is a unique identifier of the pushbutton, and can be any constant you choose (within reason) or a value returned from FN_setproc. The value style% can be zero, but other values allow you to modify the appearance or behaviour of the button, for example the value &100 causes the text to be left-justified rather than centered, 3 creates a checkbox and 9 creates a radiobutton.
Clicking on the button causes an ON SYS event in the same way as a menu selection, with @wparam% equal to the value of id%.
The function returns the window handle of the button, which is needed when removing the button with PROC_closewindow.
The value id% is a unique identifier of the combo box, and can be any constant you choose (within reason) or a value returned from FN_setproc. The value style% can be zero, but other values allow you to modify the appearance or behaviour of the box, for example the value 3 creates a drop down list combo box. The function returns the window handle of the box.
To enter a list of strings into a combo box do:
where hbox% is the value returned from FN_combobox. An initial (default) selection can be made as follows:SYS "SendMessage", hbox%, &143, 0, "Combo box item 0" SYS "SendMessage", hbox%, &143, 0, "Combo box item 1" etc.
To determine which item is selected in a combo box do:SYS "SendMessage", hbox%, &14E, index%, 0
SYS "SendMessage", hbox%, &147, 0, 0 TO sel%
The value id% is a unique identifier of the edit box, and can be any constant you choose (within reason) or a value returned from FN_setproc. The value style% can be zero, but other values allow you to modify the appearance or behaviour of the box, for example the value &80 allows the contents of the box to scroll horizontally. The function returns the window handle of the box.
To read the contents of an edit box do:
where the parameter hbox% is the value returned from FN_editbox.DEF FNgettext(hbox%) LOCAL text% DIM text% LOCAL 65535 SYS "GetWindowText", hbox%, text%, 65535 = $$text%
The value id% is a unique identifier of the list box, and can be any constant you choose (within reason) or a value returned from FN_setproc. The value style% can be zero, but other values allow you to modify the appearance or behaviour of the box, for example the value 2 causes the contents of the box to be sorted. The function returns the window handle of the box.
To enter a list of strings into a list box do:
where hbox% is the value returned by FN_listbox. To determine which item is selected do:SYS "SendMessage", hbox%, &180, 0, "List box item 0" SYS "SendMessage", hbox%, &180, 0, "List box item 1" etc.
The value sel% gives the index (starting at 0) of the currently selected item or –1 if no item is selected.SYS "SendMessage", hbox%, &188, 0, 0 TO sel%
The value id% is a unique identifier of the static box, and can be any constant you choose (within reason) or a value returned from FN_setproc. The value style% can be zero, but other values allow you to modify the appearance or behaviour of the box, for example the value &E indicates that the box will contain a bitmap image. The function returns the window handle of the box.
To load a bitmap image into a static box do:
The value bmpfile$ is the name of a Windows™ bitmap file containing the image, cx% and cy% are the dimensions of the image in pixels and hbox% is the value returned from FN_staticbox. Once you have finished with the box (but not before) delete the bitmap handle:SYS "LoadImage", 0, bmpfile$, 0, cx%, cy%, 16 TO hbitmap% SYS "SendMessage", hbox%, &172, 0, hbitmap%
SYS "DeleteObject", hbitmap%
To create a menu, in which selecting Open causes PROCopen to be executed and selecting Exit causes PROCexit to be executed:
To create buttons in a dialogue box, where clicking on Button 1 causes PROCbutton1 to be executed and clicking on Button 2 causes PROCbutton2 to be executed:SYS "CreatePopupMenu" TO hfile% SYS "AppendMenu", hfile%, 0, FN_setproc(PROCopen), "&Open" SYS "AppendMenu", hfile%, 0, FN_setproc(PROCexit), "E&xit"
INSTALL @lib$+"WINLIB2"
dlg% = FN_newdialog("Button test", 200, 100, 100, 100, 8, 1000)
PROC_pushbutton(dlg%,"Button 1",FN_setproc(PROCbutton1),20,10,64,16,0)
PROC_pushbutton(dlg%,"Button 2",FN_setproc(PROCbutton2),20,32,64,16,0)
To create buttons on your main window, where clicking on Button 3 causes PROCbutton3
to be executed and clicking on Button 4 causes PROCbutton4 to be executed:
hbutt3% = FN_button("Button 3",300,20,100,24,FN_setproc(PROCbutton3),0)
hbutt4% = FN_button("Button 4",300,90,100,24,FN_setproc(PROCbutton4),0)
If you need to know the values of @wparam% and/or @lparam% (unlikely in the case
of menu selections or button presses, but possible with other controls) you can arrange for them to be
passed to your procedure by adding a pair of parentheses when you call FN_setproc, as follows:
hedit% = FN_editbox("",300,20,100,24,FN_setproc(PROCeditbox()),0)
You must then define your procedure to receive two parameters:
where W% and L% receive the values of @wparam% and @lparam% respectively.DEF PROCeditbox(W%, L%)
The library should be loaded from your program using the command:
INSTALL @lib$+"SPRITELIB"
The functions contained are:
The returned value is TRUE if the sprite system was initialised successfully and FALSE if not. The function will fail if the supplied parameter is zero, or if there is insufficient memory.IF FN_initsprites(2) = 0 STOP
The file must be an Icon-format file (usually having the extension .ICO) generated using a suitable icon editor. BBC BASIC for Windows is supplied with a simple icon editor (ICONEDIT.BBC) which will suffice if no other editor is available. Under normal circumstances you should specify the same dimensions in the FN_createsprite call as were used when the icon was created, however if you do not do so the sprite will be scaled to the specified size (with some attendant loss of quality).
The returned value is non-zero if the sprite was created successfully, and zero otherwise. The most likely reason for the function to fail is if the file does not exist or is not a suitable icon-format file.ok% = FN_createsprite(0, "bbcmicro.ico", 64, 64)
The sprite is not displayed until PROC_movesprite is executed.
Sprites are unaffected by the current graphics window (if any) and always display in front of any other graphics or text. Sprites have a predefined priority order such that, if they overlap, a higher-numbered sprite always appears in front of a lower-numbered sprite.PROC_movesprite(0, 200, 200, 1)
Because the sprite routines use space on the heap, it is essential that you call PROC_exitsprites before executing a CLEAR, CHAIN or RUN statement. Failure to do so is very likely to crash BBC BASIC for Windows.PROC_exitsprites
BBC BASIC also lacks the UPPER$ (or UCASE$) and LOWER$ (or LCASE$) functions provided in some dialects of BASIC to convert strings to uppercase (capitals) or lowercase characters respectively.
The FNUSING library provides replacements for these operations. It should be loaded from your program using the command:
Alternatively, since the functions are quite short, you might prefer to incorporate them in your own program (use the Insert command from the File menu).INSTALL @lib$+"FNUSING"
The functions contained are:
A significant difference from the conventional PRINT USING statement is that each format string can only refer to one numeric value, so you must call FNusing for each value you want to output.PRINT FNusing(fmt1$,val1) FNusing(fmt2$,val2) .....
The format string is a string literal or variable containing special formatting characters, as follows:
| # | The hash character is used to represent a digit position. Digit positions are always
filled: if the number has fewer digits than positions specified it is right-justified
(preceded by spaces) in the field. A decimal point may be inserted at any position in the field
and numbers are rounded as necessary. For example:
PRINT FNusing("##.##",.78)
0.78
PRINT FNusing("###.##",987.654)
987.65
|
| + | A plus sign at the beginning or end of the format field causes the sign of the number
(plus or minus) to be printed before or after the number. For example:
PRINT FNusing("+###.##",2.4)
+2.40
PRINT FNusing("##.##+",55.678)
55.68+
PRINT FNusing("##.##+",-3)
3.00-
|
| – | A minus sign at the end of the format field causes negative numbers to be printed
with a trailing minus sign. For example:
PRINT FNusing("##.##-",-68.95)
68.95-
PRINT FNusing("###.##-",-7)
7.00-
|
| ** | A double asterisk at the beginning of the format field causes leading spaces in the
field to be filled with asterisks. The ** also specifies two more digit positions. For example:
PRINT FNusing("**#.#",12.39)
*12.4
PRINT FNusing("**##.##",-0.9)
**-0.90
|
| $$ | A double dollar (or pound) sign at the beginning of the format field causes a dollar (or
pound) sign to be printed to the immediate left of the formatted number. The $$ also
specifies two more digit positions, one of which is the currency symbol. For example:
PRINT FNusing("$$###.##",45.67)
$45.67
PRINT FNusing("££###.##",123.45)
£123.45
|
| **$ | A **$ (or **£) at the beginning of the format field combines the effects of the previous two
formats. Leading spaces are filled with asterisks, and a dollar (or pound) sign is printed
before the number. **$ specifies three more digit positions, one of which is the currency
symbol. For example:
PRINT FNusing("**$##.##",2.34)
***$2.34
|
| , | A comma to the left of the decimal point in the format string causes a comma to be
printed between every third digit before the decimal point. For example:
PRINT FNusing("#,###.##",1234.5)
1,234.50
PRINT FNusing("##,###,###",1E6)
1,000,000
|
| ^^^^ | Four carets may be placed after the digit characters to specify exponential format.
The four carets allow space for "E-xx" to be printed. For example:
PRINT FNusing("##.##^^^^",234.56)
2.35E2
PRINT FNusing("##.##^^^^",1E-30)
1.00E-30
|
PRINT FNusing("Price ££#.## including VAT",29.99)
Price £29.99 including VAT
If the number cannot be represented in the format supplied, question marks are printed:
PRINT FNusing("##.##",123)
?????
PRINT FNlower("The Quick Brown Fox")
the quick brown fox
PRINT FNupper("The Quick Brown Fox")
THE QUICK BROWN FOX
The library should be loaded from your program using the command:
INSTALL @lib$+"MDILIB"
The functions contained are:
See the section on adding popup and sub-menus for more details. PROC_initmdi must be called just once at the start of your program; once it has been called no output to the screen is possible until you have created one or more child windows (if necessary you can still display information using a message box).SYS "CreatePopupMenu" TO hwindow% SYS "CreateMenu" TO hmenu% SYS "AppendMenu", hmenu%, 16, hwindow%, "&Window" SYS "SetMenu", @hwnd%, hmenu% SYS "DrawMenuBar", @hwnd% PROC_initmdi(hwindow%)
The child window is created with a default size and position, but your program can change that subsequently if necessary. It can be minimised, maximised, re-sized and moved by the user in the usual way, except that the child window is constrained to remain within the confines of your program's main window. You can create as many child windows as you like (within reason!).
FN_createmdichild returns the window handle of the child window it has created:
hwnd1% = FN_createmdichild("Hello world")
hwnd2% = FN_createmdichild("Rectangles")
hwnd3% = FN_createmdichild("Circles")
Once you have created a child window you can send output to it in the same way as you would to BASIC's
normal output window, however you must first select the appropriate window by changing the values
of @hwnd% and @memhdc%. The easiest way of doing that (and of ensuring they are
restored to their original values afterwards) is to pass them as parameters of a procedure. So for
example a procedure for writing text to a child window might be:
To write a text string to a particular window you would call this procedure as follows:DEF PROCwritetext(A$, @hwnd%, @memhdc%) PRINT A$ ENDPROC
PROCwritetext("Some text", hwnd1%, FN_hdc(hwnd1%))
(see below for a description of FN_hdc)
As it stands this will work fine when writing text to just one window, but if you write text to two or more windows concurrently you will find that all the windows share the same text output position, so sending a 'newline' to one window will affect the subsequent position of text written to another window. One way to provide each child window with its own 'private' text position is to pass the X and Y coordinates to the procedure:
which you would call as follows:DEF PROCwritetext(A$, @hwnd%, @memhdc%, RETURN @vdu%!48, RETURN @vdu%!52) PRINT A$ ENDPROC
PROCwritetext("Text for window 1", hwnd1%, FN_hdc(hwnd1%), xpos1%, ypos1%)
PROCwritetext("Text for window 2", hwnd2%, FN_hdc(hwnd2%), xpos2%, ypos2%)
Since they are passed by reference the variables
containing the text coordinates for each window are automatically updated.
All the other text and graphics parameters (colour, plotting mode, window positions etc.)
are similarly shared between the child windows, so you may need to set the parameters
appropriate to that window before performing any output.
Note that (in BBC BASIC for Windows) MDI child windows do not display the text cursor (caret). User input, when required, should normally be done via a dialogue box.
You cannot prevent the user closing a child window (there is no direct equivalent to ON CLOSE) but you can detect that he has closed it using the IsWindow API call:
SYS "IsWindow", hwnd1% TO res% IF res% = 0 THEN REM child window has been closed REM take appropriate action if necessary ENDIF
INSTALL @lib$+"DATELIB"
The functions contained are:
The parameters supplied are the day of the month (1-31), the month number (1-12) and the year number (1-9999). Note that the functions in the DATELIB library will behave consistently for any date in that range (for example, converting from DMY to MJD and back will return the original values) but should not normally be used for dates prior to the introduction of the Gregorian calendar (in the UK on Thursday 14th September 1752, MJD –38779). For earlier dates the day, month and year values may not be correct, and since use of the old Julian calendar persisted in some countries until as late as 1927 care should be taken when using this function.
For example:
d Day of month as digits with no leading zero. dd Day of month as digits with leading zero for single-digit days. ddd Day of week as a three-letter abbreviation. dddd Day of week as its full name. M Month as digits with no leading zero. MM Month as digits with leading zero for single-digit months. MMM Month as a three-letter abbreviation. MMMM Month as its full name. y Year as last two digits, but with no leading zero. yy Year as last two digits, but with leading zero for years less than 10. yyyy Year represented by full four digits.
will return a string of the form "Sun 22 Feb 2004".date$ = FN_date$(mjd%, "ddd dd MMM yyyy")
The FN_readdate function attempts to make sense of the date string however it is formatted, so long as the elements are in the specified order. For example it will accept "22/2/2004", "22 Feb 04", "22-02-04" etc. If it cannot make sense of the string it will return the value &80000000.
INSTALL @lib$+"D3DLIB"
The functions contained are:
The value hw% is the handle of the window which is to contain the 3D graphics. It can be set to @hwnd% if the graphics are to be displayed in BBC BASIC's main output window or to the handle of a child window (for example as returned from FN_staticbox) if you want them to appear in a separate frame. Note that you cannot mix Direct3D graphics and normal BBC BASIC output (text or graphics) in the same window.
The value cull% specifies the culling mode, which determines whether surfaces behave as single sided or double sided. Possible values are 1 (none), 2 (clockwise) or 3 (counterclockwise). If in doubt, set to 1.
The value light% determines whether Direct3D's lighting engine is enabled. Set to 1 to enable lighting or to 0 to disable lighting. When lighting is disabled all objects appear normally as if uniformly illuminated. When lighting is enabled it is necessary for all objects to include surface normals in the vertex description.
The value pdev% is the pointer returned from FN_initd3d. The value file$ is the name of a file containing vertex data.
The values num%, fmt% and size% are outputs from FN_load3d and are set to the number of vertices, the vertex format and the size in bytes of each vertex respectively.
The file format is as follows:
Number of vertices (4 bytes, LSB first) Vertex format (2 bytes, LSB first) Vertex size in bytes (2 bytes, LSB first) Data for each vertex (see below)
To obtain the vertex format code add together the codes for the items included. To obtain the vertex size add together the sizes of the items included. The XYZ position and surface normal items each consist of three 4-byte floating point numbers (see FN_f4). The diffuse colour and specular colour items each consist of 4-byte colour values (&FFrrggbb). The texture coordinates consist of a pair of 4-byte floating point numbers. The simplest vertex description consists of an XYZ position and a diffuse colour (format &042; size 16 bytes). See FN_f4 for an example of creating a file in this format. Refer to Microsoft documentation for more details.
Code Size Data Comments &002 12 XYZ position Always required &010 12 Surface normal When lighting used &040 4 Diffuse colour When neither texture nor material specified &080 4 Specular colour For shiny objects &100 8 UV texture coordinates When texture specified
The value pdev% is the pointer returned from FN_initd3d. The value file$ is the name of the image file.
The image will be padded to a size of 2^n pixels in both horizontal and vertical directions.
The value pobj% is the pointer returned from FN_initd3d, FN_load3d or FN_loadtexture.
F% = OPENOUT"TRIANGLE.B3D" PROC4(3):REM 3 vertices PROC4(&100042):REM vertex size &10 and format &42 PROC4(FN_f4(-1.0)):PROC4(FN_f4(-1.0)):PROC4(FN_f4(1.0)):PROC4(&FF0000FF) PROC4(FN_f4(1.0)):PROC4(FN_f4(-1.0)):PROC4(FN_f4(1.0)):PROC4(&FF00FF00) PROC4(FN_f4(0.0)):PROC4(FN_f4(1.0)):PROC4(FN_f4(0.0)):PROC4(&FFFF0000) CLOSE #F% DEF PROC4(A%):BPUT#F%,A%:BPUT#F%,A%>>8:BPUT#F%,A%>>16:BPUT#F%,A%>>24:ENDPROC
Notes:
pdev% The value returned from FN_initd3d. bcol% The background colour (&FFrrggbb). nlight% The number of lights. Set to zero if lighting is not used. light%() An array of pointers to D3DLIGHT8 structures (see note 1). nobj% The number of objects (i.e. vertex buffers). mat%() An array of pointers to D3DMATERIAL8 structures (see note 2). tex%() An array of texture pointers (e.g. returned from FN_loadtexture). vbuf%() An array of vertex buffer pointers (e.g. returned from FN_load3d). vnum%() An array of vertex counts (e.g. returned from FN_load3d). vfmt%() An array of vertex format codes (e.g. returned from FN_load3d). vsize%() An array of vertex sizes (e.g. returned from FN_load3d). yaw() An array of yaw angles (rotations about the Y-axis). pitch() An array of pitch angles (rotations about the X-axis). roll() An array of roll angles (rotations about the Z-axis). X() An array of translations along the X-axis. Y() An array of translations along the Y-axis. Z() An array of translations along the Z-axis. eye() An array eye(0), eye(1), eye(2) holding the XYZ coordinates of the eye or camera. look() An array look(0), look(1), look(2) holding the XYZ coordinates of a point on the eyeline. fov The vertical field-of-view in radians (equivalent to the camera's zoom). ar The aspect ratio of the 3D graphics window (width/height). zn The distance from the camera to the near plane (objects nearer than this are invisible). zf The distance from the camera to the far plane (objects further away than this are invisible).
DIM light%(0) 103 light%(0)!0 = 3 : REM directional light light%(0)!4 = FN_f4(1) : REM red component light%(0)!8 = FN_f4(1) : REM green component light%(0)!12 = FN_f4(0) : REM blue component light%(0)!64 = FN_f4(0) : REM. X component of direction light%(0)!68 = FN_f4(0) : REM. Y component of direction light%(0)!72 = FN_f4(1) : REM. Z component of direction
DIM mat%(0) 67 mat%(0)!0 = FN_f4(1) : REM red component of colour mat%(0)!4 = FN_f4(1) : REM green component of colour mat%(0)!8 = FN_f4(1) : REM blue component of colour
Alternatively, since the procedures are quite short, you might prefer to incorporate them in your own program (use the Insert command from the File menu).INSTALL @lib$+"ELLIPSE"
The ellipse is drawn in the current graphics foreground colour and mode, as specified by GCOL.
It contains the single function FN_sortinit.INSTALL @lib$+"SORTLIB"
where dir% determines the sorting direction (0 = ascending, 1 = descending) and smode% determines how strings are sorted (0 = normal, 1 = ignore case).sort% = FN_sortinit(dir%,smode%)
To sort the contents of an entire array do the following:
To sort only part of an array set C% to the number of elements you want to sort and specify the first element to be sorted:C% = DIM(array(),1)+1 : CALL sort%, array(0)
To sort multiple arrays according to the contents of a key array do the following:C% = howmany% : CALL sort%, array(first%)
There can be any number of dependent arrays of any type. If the primary key array contains two or more identical elements, the remaining array(s) will be used as secondary keys, in the order specified.C% = size% : CALL sort%, keyarray(0), array2$(0), array3%(0)...
To sort a two-dimensional array, where the contents of the first row are used as a key for the other rows, do the following:
DIM array(2,999) C% = 1000 : CALL sort%, array(0,0), array(1,0), array(2,0)
The library should be loaded from your program using the command:
INSTALL @lib$+"SOCKLIB"
The functions contained are:
If the listening socket is created successfully the socket number is returned. If the call fails a negative number is returned (see the code of SOCKLIB.BBC for details). You can call FN_socketerror to discover more about the error.
If the connection is made successfully the socket number is returned. If the call fails a negative number is returned (see the code of SOCKLIB.BBC for details). You can call FN_socketerror to discover more about the error.
Note that it is possible for FN_writesocket to return a value less than the total length of the data. This indicates that only some of the data has been sent, and you should make further calls (adjusting the values of buffer% and size% accordingly) until all the data has been sent.
FN_readsocket does not wait for data to be received. If no data has been received since the last call, it returns zero.
The error code numbers can be found in the Microsoft™ file WINERROR.H.
The GDIPLIB library contains a set of procedures and functions for drawing antialiased graphics. It relies upon the presence of the Microsoft GDI+ graphics subsystem, which is installed as standard only with Windows XP (or later). However it is available for earlier versions of Windows (98 onwards) in the form of a redistributable file which can be downloaded from Microsoft's site (search for GDIPLUS.DLL).
The library should be loaded from your program using the command:
INSTALL @lib$+"GDIPLIB"
The functions contained are: