GUI /
Programming matters |
Hint |
Answer: |
How can I devide sets radio
buttons or toggle buttons into groups?, whatever
I add seems to stick to the rest...
|
In VB "frames"
are the fundament object to split groups of radiobuttons and toggle
buttons by putting them into it. XBasic has no direct frames
but instead you can group Radiobuttons by labels as their fundament
(or so called "parent grid"). Be sure that you
insert the radio/toggle/etc. buttons within the border margins of
the label else they will be seen as a kid of the windowgrid which
will group them with the rest of the buttons which are situated
there. As you may know, you can give a label a "Frame"
look so eventually, XBasic has got frames but you have to take two
steps to set them up instead of one. Download the GUI
window here |
How can I set a radiobutton
or box to a checked status before my program start? (sort of default
set options) |
If you want to have default
options set for the user this can be done by sending a #SetValue
message right to the kidnumber of the radiobutton / box you want
to check (or uncheck). Preselecting buttons before starting
you need to set this value in parameter v0 to $$TRUE using the kidnumber,
now to have them set before the windows even pop up you can either
do that in the InitWindows or CreateWindows, but you need to know
the kidnumber of the radiobox / button / togglebutton you want to
enable since you can only use direct numbers in the kid argument
as the kids of your windows are not defined in global constants.
(You can find the kidnumbers in the constants defined in your [windowfunction]Code())
Suppose we do it in the CreateWindows function: FUNCTION
CreateWindows()
' My window that contains buttons: Search
(@Search, #CreateWindow,
0, 0, 0, 0, $$WindowTypeSystemMenu, 0) XuiSendMessage
( Search, #SetCallback, Search, &SearchCode(), -1, -1, -1, 0)
XuiSendMessage (
Search, #Initialize, 0, 0, 0, 0, 0, 0) XuiSendMessage
( Search, #SetGridProperties, -1, 0, 0, 0, 0, 0)
'It contains 4 radioboxes, kid 5 is box 4
(kid 0 is the parent grid) XuiSendMessage
( Search, #SetValue, -1, 0, 0, 0, 5, @index ) XuiSendMessage
( Search, #DisplayWindow, 0, 0, 0, 0, 0, 0)
END FUNCTION
What if we want to set it somewhere else besides the CreateWindows()
function?
FUNCTION CreateWindows() Search
(@Search, #CreateWindow,
0, 0, 0, 0, $$WindowTypeSystemMenu, 0) XuiSendMessage
( Search, #SetCallback, Search, &SearchCode(), -1, -1, -1, 0)
XuiSendMessage (
Search, #Initialize, 0, 0, 0, 0, 0, 0) ' XuiSendMessage
( Search, #DisplayWindow, 0, 0, 0, 0, 0, 0) 'Don't display
yet XuiSendMessage
( Search, #SetGridProperties, -1, 0, 0, 0, 0, 0) 'Store the
gridnumber in a global variable #SearchWindowGrid
= Search END FUNCTION
FUNCTION InitWindows() XuiSendMessage
( #SearchWindowGrid, #SetValue, -1, 0, 0, 0, 5, @index ) XuiSendMessage
( #SearchWindowGrid, #DisplayWindow, 0, 0, 0, 0, 0, 0) AnyFunction()
END FUNCTION
FUNCTION AnyFunction() '
retrieve values from the radiobuttons FOR
X = 1 to 5 XuiSendMessage(
#SearchWindowGrid, #GetValue, @Value, 0, 0, 0, X, 0)
IF
Value THEN PRINT
"Option "; X; "is selected" ELSE
PRINT
"Option "; X; "is not selected" END
IF NEXT X
'Changing values
on-the-fly without using the mouse to select FOR
X = 1 to 5 XuiSendMessage(
#SearchWindowGrid, #SetValue, @Value, 0, 0, 0, X, 0) XuiSendMessage(
#SearchWindowGrid, #Redraw, 0, 0, 0, 0, X, 0) 'Never forget this
when live updating!) NEXT
X 'You should
now have all four radiobuttons enabled (while this should not be
possible) END FUNCTION |
How do you change colours
and fontsets of Drop-boxes and listboxes etc? I
can't get this done in the GUI Designer!
|
For each GUI design you
can set assets per object that you edit. The Appearance
editor does incorporate settings for sub-assets that belong to sub-kids
from eg. a menu object or a drop-list object (Click the "Kids"
menu in the appearance window) but in some cases settings don't
stick or don't get translated to the source-code function of your
design. These options you have to manually set yourself
AFTER you did a "ToFunction" translation. When
you examine create function() that has been generated by the GUI
designer, you will e.g. find your lisbox options being created like
this: XuiListButton
(@g, #Create, 52, 4, 208, 20, r0, grid) XuiSendMessage
( g, #SetCallback, grid, &FileDialog(), -1, -1, $LBDrives, grid)
XuiSendMessage (
g, #SetGridName, 0, 0, 0, 0, 0, @"LBDrives") XuiSendMessage
( g, #SetStyle, 0, 0, 0, 0, 0, 0) XuiSendMessage
( g, #SetColor, $$Blue, $$Black, $$Black, $$White, 0, 0) XuiSendMessage
( g, #SetColorExtra, $$LightRed, $$White, $$Black, $$White, 0, 0)
XuiSendMessage (
g, #SetAlign, $$AlignMiddleLeft, 0, -1, -1, 0, 0) XuiSendMessage
( g, #SetBorder, $$BorderFlat4, $$BorderFlat4, $$BorderNone, 0,
0, 0) XuiSendMessage
( g, #SetFont, 240, 400, 0, 0, 0, @"MS Sans Serif")
XuiSendMessage (
g, #SetTexture, $$TextureRaise1, 0, 0, 0, 1, 0) XuiSendMessage
( g, #SetGridName, 0, 0, 0, 0, 1, @"PressButton")
XuiSendMessage (
g, #SetGridName, 0, 0, 0, 0, 2, @"XuiList721")
Though, you would like to have the fonts set of the characters
within the list AND on the button set to MS Sans Serif, you notice
that in the above example only kid "0" is set to this
font, while Kid "0" is the button itself. It's
nice to know that these objects have more kids, for the XuiList
the kidnumber for the text on the button is "1", the kidnumber
for the text in the list is "2" By copying this
line another two times underneath the original:
XuiSendMessage
( g, #SetFont, 240, 400, 0, 0, 0, @"MS Sans Serif")
And changing the Kid numbers, you have set the fonts
for the other assets of the XuiList object. Your sourcecode
will now look like this: XuiListButton (@g, #Create, 52, 4, 208, 20, r0,
grid) XuiSendMessage
( g, #SetCallback, grid, &FileDialog(), -1, -1, $LBDrives, grid)
XuiSendMessage (
g, #SetGridName, 0, 0, 0, 0, 0, @"LBDrives") XuiSendMessage
( g, #SetStyle, 0, 0, 0, 0, 0, 0) XuiSendMessage
( g, #SetColor, $$Blue, $$Black, $$Black, $$White, 0, 0) XuiSendMessage
( g, #SetColorExtra, $$LightRed, $$White, $$Black, $$White, 0, 0)
XuiSendMessage (
g, #SetAlign, $$AlignMiddleLeft, 0, -1, -1, 0, 0) XuiSendMessage
( g, #SetBorder, $$BorderFlat4, $$BorderFlat4, $$BorderNone, 0,
0, 0) XuiSendMessage
( g, #SetFont, 240, 400, 0, 0, 0, @"MS Sans Serif")
XuiSendMessage (
g, #SetFont, 240, 400, 0, 0, 1, @"MS Sans Serif")
XuiSendMessage (
g, #SetFont, 240, 400, 0, 0, 2, @"MS Sans Serif")
XuiSendMessage (
g, #SetTexture, $$TextureRaise1, 0, 0, 0, 1, 0) XuiSendMessage
( g, #SetGridName, 0, 0, 0, 0, 1, @"PressButton")
XuiSendMessage (
g, #SetGridName, 0, 0, 0, 0, 2, @"XuiList721")
For every aspect, the same rules apply: To make changes to
the rest, copy the original and change the kidnumbers.
Maybe you even want to have different colours in each of the subkids,
then just adjust the colours.
|
Nice that
you can change the above assets within the [function]() but I want to do this in the InitWindows() or in
the [function]Code()
Before the asset-change:
After the asset change:
|
Okay, okay...
For this we need a trick-message called #GetEnclosedGrids.
The general tree structure of how we control xbasic (explained here) goes up to three levels
deep. If we want to change these matters there are a couple
of ways how you can do this. I choose for the way with
the best survey, download this
small window and then start Xbasic with a new "GUI
Program" Open up the toolkit and select menu "Window"
option "Load", load the window and select again menu "Window"
option "ToFunction"
Go to the "CreateWindows()" function where the following
should be listed: Listbox
(@Listbox, #CreateWindow,
0, 0, 0, 0, 0, 0) XuiSendMessage
( Listbox, #SetCallback, Listbox, &ListboxCode(), -1, -1, -1,
0) XuiSendMessage
( Listbox, #Initialize, 0, 0, 0, 0, 0, 0) XuiSendMessage
( Listbox, #DisplayWindow, 0, 0, 0, 0, 0, 0) XuiSendMessage
( Listbox, #SetGridProperties, -1, 0, 0, 0, 0, 0)
Add the following line underneath it:
#ListBoxGrid
= Listbox
You know why I did this? I made the gridnumber of the window
global this means that I can now make changes or read anything from
this window and it's kids from any place within the whole program.
If I have more windows I store the gridvalues in a multidimensional
array along with it's function address and it's active status.
There are tools to get this information when needed, but I
don't want to think about when and how to use these tools, I just
want to know for sure what it is even if I would drop my code for
a couple of months. Now getting back to the story, add
the following code to the "InitWindows()" function:
STATIC
text$[24]
FOR
x = 0 TO 24 text$[x]
= "Line " + STRING(x) NEXT
x
XuiSendMessage(#ListBoxGrid,
#SetTextArray, 0,0,0,0,1,@text$[])
You see that you can already change the contents of the list
by using this global variable. You do have to lookup the kid number
but at least you can maintain your windows from pretty anywhere.
Now when you run the code you would see the picture displayed
in the left box. By just adding a few elements you can
also change the look of this list; Go back to the "InitWindows()"
function and add the last piece of code under the "XuiSendMessage...":
XuiGetEnclosedGrids ( #ListBoxGrid, #GetEnclosedGrids,
0, 0, 0, 0, 0, @grid[] )
' Setting the font of the Button XuiSendMessage
( grid[0], #SetFont, 240, 400, 0, 0, 1, @"MS Sans Serif")
' Setting the font of the list XuiSendMessage
( grid[0], #SetFont, 240, 400, 0, 0, 3, @"MS Sans Serif")
' Setting the style of the list to 1 (small arrows
in scrollbars XuiSendMessage ( grid[0], #SetStyle, 1,
0, 0, 0, 3, 0)
' Setting the borders of the whole set: XuiSendMessage
( grid[0], #SetBorder, $$BorderLower1, $$BorderLower1, $$BorderNone,0,1
0) XuiSendMessage ( grid[0], #SetBorder, $$BorderRaise2, $$BorderLower1,
$$BorderNone,0,2,0) XuiSendMessage ( grid[0], #SetBorder, $$BorderRaise1,
$$BorderLower1, $$BorderNone,0,3,0)
' Redrawing the changed assets: XuiSendMessage
(grid[0], #Redraw, 0, 0, 0, 0, 1, 0) XuiSendMessage (grid[0],
#Redraw, 0, 0, 0, 0, 2, 0) XuiSendMessage (grid[0], #Redraw,
0, 0, 0, 0, 3, 0)
The #GetEnclosedGrids will place all the gridnumbers of
the kids into an array (counting from kid 1, not kid 0!);
This is important because you need to change sub-kid assets from
these kids and you can only do that by using the gridnumbers of
those kids. A listbox has 3 sub kids: The frame (kid
0) the textfield, (kid 1) the arrow-button (kid 2) and the
list (kid 3) You can change every aspect per sub-kid to
the possibilities of it's function, like the list can receive #SetStyle
messages, #RedrawText messages and so more. In the example
above we change the fontset and it's borders when done the listbox
should display like the picture on the left. The
Appearance window you notice in the GUI designer does unfortunately
not offer a possibility to change these options from there so you
have to make these adaptions manually. You can at least
quickly make some default window with some buttons, lists and set
some options so you can quickly copy the line you need without needing
to grab the documentation for finding how to set the font again.
BEWARE!: I
have to warn you that when using the XuiGetEnclosedGrids () statement
it gets only the first kid-branch underneath the parent-grid
So if you have two labels with two sets of radioboxes, your returned
kid[] array only contain two kid grid numbers: grid of label
number one and grid of label number two. To retrieve the
kidnumbers of the radioboxes you need to repeat the XuiGetEnclosedGrids
() statement but in this case you don't send the windowgrid as grid
number but the gridnumber from the label with radiobox set from
which you want the gridnumbers from. Another nessesary
thing to tell: When using Xui objects like filedialogues, the
GetEnclosedGrids does not see a XuiFile as "one" object,
the XuiFile covers the main grid with a couple of grid objects therefore,
GetEnclosedGrids returns also gridnumbers from the objects that
build the XuiFile Dialogue. If you truly want a distinct
object direct command, try the #GetKidArray message instead Download this example source to see a demonstration of how GetEnclosedGrids
work. How #GetKidArray works: setKid
= 0 'Select the parent grid of all
kids in this case the windowgrid XuiSendMessage
(grid, #GetKidArray, 0, 0, 0, 0, setKid, @KidArray[])
IF
UBOUND(KidArray[]) > -1 THEN
FOR
akid = 0 TO UBOUND(KidArray[]) 'Setting
all colors of all child kids to one set. XuiSendMessage
( KidArray[akid], #SetColor, back, draw, -1, -1, 0, 0 ) XuiSendMessage
( KidArray[akid], #SetColorExtra, -1, accent, lowText, highText,
0, 0 ) XuiSendMessage
( KidArray[akid], #SetImage, 0, 0, 0, 0, 0, 0) 'Removing
image IF placed NEXT
akid
ELSE
'grid has no kids, change the color-set of the
parent grid only. XuiSendMessage
( grid, #SetColor, back, draw, -1, -1, setKid, 0 ) XuiSendMessage
( grid, #SetColorExtra, -1, accent, lowText, highText, setKid, 0
) XuiSendMessage
( grid, #SetImage, 0, 0, 0, 0, setKid, 0) 'Removing
image IF placed END
IF |
The
XstGetNextField() and XstGetNextItem() are poorly explained in the
docs, what can I actually do with them? |
These functions are used
to tokenise (separating words) line-phrases, they give you the ability
to process words from a textfile (also comma delimited / separated).
If you want to make a word processor like an HTML viewer, such functions
can be very handy to use. Examples tell the most, click here to download some exclusive
examples done by Max Reason himself. |
I'm
not getting mouse messages send to my function, neither as #WindowMouseDown
neither as #MouseDown, the docs
describe it as #Window... messages are sent to the window and the
other are sent to the grids but I'm having troubles even getting
the messages from inside the window. I'm able to find out where
my pointer is by sending a XgrGetMouseInfo() message but I want
to respond on the available messages. How can
I get those mouse messages sent to my current window? |
I had to deal with this
problem myself too at the beginning. David Szafranski came
up with a solution that I overlooked. In his attempt to figure
out how to change eg. a mouse-cursor made it necessary to figure
out where the mousepointer was. For that a #MouseEnter event and
a #MouseExit event is necessary. These messages are not
sent to your functionCode() but to your function() (this is called
the window function). It's not nice to spread your processing
routines across two functions at least you don't really have survey
on all your code. You need to set the CEO function:
The XgrSetCEO() is used to have all messages sent to the function
you supply it's address from. If your functionCode() is
named HelloWorldCode() then you simply add this line in the InitWindows()
function: XgrSetCEO(&HelloWorldCode()) And
voila, all messages are sent to the HelloWorldCode(). Just enable
the "ReportWindow" and check out what messages it receives.
Notice that messages like #MouseDown and #MouseMove are not
sent but #WindowMouseDown and #WindowMouseMove are sent to the function.
|
Okay I set the CEO but
I have more windows than just one, I don't
want to manually add a line in each function to change the CEO constantly
and also trying the window to figure out what window it has to set
the CEO to, I just want to have the CEO automaticly set to the window
I select as soon as I click on it. |
This is possible but it's
tricky and it brings up one limitation. In a Gui Program
you have the loop where the messages are processed: DO
XgrProcessMessages (1) LOOP
Just change it to the following: DO CentralCEO
() XgrProcessMessages (1) LOOP Now
select from the PDE menu "View" option "new function"
and call it "CentralCEO"
Make it look like this:
' ' ' ###########################
' ##### CentralCEO () ##### ' ###########################
' FUNCTION CentralCEO () STATIC
CEOWindow
'Get the window number
that is currently selected XgrGetSelectedWindow(@window)
IF CEOWindow <> window
THEN 'Get
it's gridnumber XgrGetWindowGrid(window,
@wingrid)
'If
the gridnumber is one of our own application grids... IF
wingrid > 0 THEN 'Grab
it's gridtype name and strip off the first three letters XuiSendMessage
(wingrid, #GetGridTypeName, 0, 0, 0, 0, 0, @gname$) gname$
= UCASE$(LEFT$(gname$, 3))
'Check
if the UCASE(windowname) is starting with a "XUI", in
this case you stumble upon 'an
autonomous child-window which causes an application crash if you
send a '#GetCallback
message to this window! IF
(wingrid > 0) AND (gname$ <> "XUI") THEN
XuiSendMessage
( wingrid, #GetCallback,@callGrid, @callFunc, @v2, @v3, @r0, 0 )
XgrSetCEO(callFunc)
END
IF END
IF END IF
END FUNCTION Why is the gridtype
name checked for a "Xui" prefix? This has one important
reason: The toolkit objects like XuiPulldown menu's, listboxes
and droplists are a cluster or various options you can use.
Example: The menu-bar exists out of a XuiMenuBar and a
XuiPullDown. The XuiMenuBar will be a kid of your main
window but the XuiPullDown has it's own window. As long
as you select kids that are a direct object of your main window,
the name of your window should appear in the gridtypename "gname$"
No problem so far since the messages can be send to an existing
functionCode() However if you select the "pulldown list"
of your menubar you also select a new (frameless) window that has
no further kid structure causing you to mess up the ProcessMessages
routine and it will start to crash. Because these functions
are named "Xui..." they are easily filtered out of the
process so the CEO is only changed if a window is encountered that
has not the prefix "Xui" (or any case of XUI, xui, xUi,
xuI, etc). The only limitation is that you should not name
your application window with "Xui" as a prefix. If you
want to make a toolbox set with this prefix : fine but for your
main window focus inside your core application, don't use it. |
Okay
, all CEO messages seem to arrive, but now when I want to use the
messages on the kids but nothing seem to happen if I do a simple
XuiSendMessage(grid, #message, v0, v1, v2, v3, kid, r1)
No redraws, no changes of labels, it does repond on keyinput and
selections but no ordinary mousclicks, well it responds but does
not send the change to the kid. what is wrong? |
Setting the CEO to your
function means that you receive ALL messages, not only grid messages
but also the window messages. For grid-messages the gridnumber
is sent in the parameter "grid" but when a window message
is encountered, the windownumber will be supplied in the "grid"
parameter. So for each #Window[.....] message you should
your message selector GOSUB to a routine that converts the windownumber
into a grid number before you jump to any routines that do XuiSendMessages
to grid oriented treatment. The next example is a small extract
from the top of a functionCode() where you could change the window
number to a grid. ' $UpperKid
= 3 ' kid maximum ' ' XuiReportMessage
(grid, message, v0, v1, v2, v3, r0, r1) IF
(message == #Callback) THEN message = r1
XgrMessageNumberToName
(message, @messageName$) IF
LEFT$(messageName$, 6) == "Window" THEN XgrGetWindowGrid
(grid, @grid) END
IF
If you are not sure you will receive a windownumber yes/no, you
can always use the XgrGetWindow() function to get the window number
to be sure you convert a window number. |
XBasic
V2.0022 and higher does not support wheelmouse anymore like it did
earlier
What happened? |
XBasic still supports Wheelmouse,
as a matter of fact, Eddie Penninkhof even added Wheelmouse support
in the Beta release of the Linux version, so pretty soon you may
even expect cross compilable support for this kind of mouse-driver
devices. It just does not behave the way Max implemented
it, the problem was that Max's solution was oriented on the Native
window message that is broadcasted to XBasic when the wheel on that
mouse is scrolled. Windows NT 4.x/2000 and Win'98 support this
native message, Windows '95 however does NOT, so he was sort of
excluding Win'95 users from having the benefit of it. I can't Blame
Max since he runs Win'98 so there are minory differences between
Win95 and Win98 that pop up as soon as someone notices the difference
or is missing something, that's good since it keeps the effectiveness
of XBasic high and it's general behavior should be that way the
ordinary XBasic user would not be able to notice any difference
between XBasic on whatever platform unless one particular platform
lacks kernel support for an action that can be done on other platforms.
With that though, I added support for WM in win95 and translated
both the native message as the win95 proprietary message into a
general XBasic message. I Hope Eddie does the same in Linux.
Yet the support remains pretty simple for so far (no fancy
five button support etc.) If you want something visual
to play with, test the
following example (9k) in your PDE. |
How
do Unions work with complex types? |
This one is posted by Steven
Gunhouse:
################################### Just to answer Kenneth's
implied question - the purpose of a UNION is to either have the
same space hold several different kinds of data (which is the example
in the documentation) or to have the same data accessible by different
methods (which is what I did). If it holds different kinds of data,
then you'd need a separate flag to indicate what type is currently
stored there. In our case, since it is really the same data in either
format the flag is not required - at best it would only indicate
whether the data has been converted yet or not (in essence, an endian
flag). One of my previous languages was PowerBASIC
for DOS, version 3.0. They didn't have equivalents to the XBasic
GHIGH and GLOW or DHIGH and DLOW, so one example they had in the
manuals was using a UNION to access the high and low INTEGER (SSHORT
to us) of a LONG (SLONG in XBASIC). While the whole is slightly
larger here and the pieces a little smaller, it's the same concept.
Given that function arguments can include the ANY type,
I never did see much use in XBasic for a union as holding different
kinds of data ... though I suppose perhaps a parser of some sort
might. If you are reading multiple coefficients from
the file and they are stored together, Kenneth's example would be
better because it reads several at once, rather than one at a time.
But we don't know the precise format of your files, it could be
that there are some sort of tags stored with the values and thus
they couldn't be read in order. ###################################
The following cut-snippets are there to convert a Unix DEC
format to M$ IEEE and a DEC format binary is very adequate for using
a UNION type of figures since DEC format are just plain 8-byte words
that can be swapped easily.. TYPE
DECDBL UNION
UBYTE
.u[7] DOUBLE
.d END
UNION END
TYPE ...
...
DECDBL DECtoIEEE
UNO = OPEN
(MyDECFile$, $$RD) ...
FOR i =1 TO NCOEF
READ
[UNO], DECtoIEEE.d
SWAP
DECtoIEEE.u[0], DECtoIEEE.u[7] SWAP
DECtoIEEE.u[1], DECtoIEEE.u[6] SWAP
DECtoIEEE.u[2], DECtoIEEE.u[5] SWAP
DECtoIEEE.u[3], DECtoIEEE.u[4]
NUM[i]=DECtoIEEE.d
NEXT i |
Go to the FAQ |
to search more answers |
Mail
more questions |
to us for more answers |