The GUI statement specifies that the program is a Graphical User Interface application and provides a ClassName for the program. The GUI statement must be placed at the beginning of the program code and cannot be placed inside any SUB, FUNCTION or within the BEGIN EVENTS ... END EVENTS loop. It must be placed at the file scope level, the same level at which your directives and global variables are declared.
Syntax 1:GUI ClassName AS STRING [,PIXELS, ICON, ResInt AS INTEGER] Parameters:
|
The following is a minimal BCX GUI program.
' -------BCX Code start-------------------- GUI "BCX_Template" SUB FORMLOAD GLOBAL Form1 AS HWND Form1 = BCX_FORM("BCX_TEMPLATE", 0, 0, 130, 110) BCX_SET_FORM_COLOR(Form1,QBCOLOR(4)) CENTER(Form1) SHOW(Form1) END SUB BEGIN EVENTS SELECT CASE CBMSG CASE WM_CLOSE DestroyWindow(Form1) EXIT FUNCTION END SELECT END EVENTS ' -------BCX Code end----------------------
As well as the GUI statement, a GUI program must have a SUB FORMLOAD ... END SUB procedure , which translates to a WinMain function, and also a BEGIN EVENTS ... END EVENTS procedure.
π In a BCX GUI program, all expressions and variable initializations must be inside a FUNCTION, SUB or the BEGIN EVENTS ... END EVENTS procedure.
π A GUI NOMAIN (see below) program must not use a SUB FORMLOAD ... END SUB procedure, but instead, GUI NOMAIN requires that the programmer provide a WinMain equivalent and the other basic functions to register a ClassName and provide a message pump.
In a GUI program, code that is responsible for monitoring and responding to messages and commands like mouse clicks, button presses, radio controls and so on, is placed in the BEGIN EVENTS ... END EVENTS block.
It is important to remember that this block is a callback routine which can be called several times before any specific task contained in the block is completed. For this reason, it is best that any variables which must be declared in the BEGIN EVENTS ... END EVENTS block, should be declared as STATIC. When DIM or LOCAL are used, BCX emits code to automatically clear the variable to zero and so if a callback occurs before a task is completed the DIM or LOCAL variables will be cleared to zero and the task will fail.
Syntax:BEGIN EVENTS [ProcedureName] ' Messages and Commands END EVENTS [MAIN] Parameters:
|
The BEGIN EVENTS section, which does not use a procedure name, of this BCX code,
GUI "BCX_STATUS" DIM Form1 AS CONTROL DIM Stat1 AS CONTROL DIM MainMenu AS HMENU DIM HelpMenu AS HMENU SUB FORMLOAD Form1 = BCX_FORM("Simple Status Sample") MainMenu = CreateMenu() Insertmenu(MainMenu, 0, MF_POPUP, HelpMenu, "&Help") SetMenu(Form1, MainMenu) Stat1 = BCX_STATUS("Ready",Form1) CENTER(Form1) SHOW(Form1) END SUB BEGIN EVENTS SELECT CASE CBMSG CASE WM_LBUTTONDOWN SetWindowText(Stat1,"left mouse button down :-(") CASE WM_LBUTTONUP SetWindowText(Stat1,"LEFT MOUSE BUTTON UP :-)") CASE WM_MOUSEMOVE ' horizontal position of cursor, X Position = LOWORD(lParam) ' vertical position of cursor, Y Position = HIWORD(lParam) SetWindowText(Stat1, STR$(LOWORD(lParam)) & " " & STR$(HIWORD(lParam))) END SELECT END EVENTS
translates to this C code.
LRESULT CALLBACK WndProc (HWND hWnd,UINT Msg,WPARAM wParam,LPARAM lParam)
{
if(Msg==WM_LBUTTONDOWN )
{
SetWindowText(Stat1,"left mouse button down :-(");
goto L1000;
}
if(Msg==WM_LBUTTONUP )
{
SetWindowText(Stat1,"LEFT MOUSE BUTTON UP :-)");
goto L1000;
}
if(Msg==WM_MOUSEMOVE )
{
SetWindowText(Stat1,join(3,str(LOWORD(lParam))," ",str(HIWORD(lParam))));
}
L1000:; // SelectState[PusherSelectState].CaseFlag 3
if(Msg==WM_DESTROY)
{
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hWnd,Msg,wParam,lParam); // endevents
}
The GUI NOMAIN statement specifies that a WinMain function will not be automatically emitted. NOMAIN requires, at least, that the programmer provide a WinMain equivalent, register a ClassName and provide a message pump. The GUI NOMAIN statement is similar to the $NOMAIN directive used in console mode programs. The GUI NOMAIN statement must be placed at the start of the program and cannot be placed inside any SUB, FUNCTION, or within the BEGIN EVENTS ... END EVENTS loop. It must be placed at the file scope level, the same level at which the directives and global variables are declared.
Syntax:GUI NOMAIN [,PIXELS, ICON, ResInt AS INTEGER] Parameters:
|
In a BCX GUI NOMAIN program, all expressions must be inside a FUNCTION, SUB or the BEGIN EVENTS ... END EVENTS procedure.
The BEGIN EVENTS section, which uses a procedure name and the MAIN statement appended to END EVENTS, of this BCX code
GUI NOMAIN FUNCTION WINMAIN () GLOBAL Form1 AS HWND GLOBAL Stat1 AS HWND Form1 = BCX_WND("MAINFORM", Form1Proc, "Simple BCX_WND Sample") Stat1 = BCX_STATUS("Ready",Form1) SHOW(Form1) FUNCTION = BCX_MSGPUMP() END FUNCTION BEGIN EVENTS Form1Proc SELECT CASE CBMSG CASE WM_LBUTTONDOWN SetWindowText(Stat1,"left mouse button down :-(") CASE WM_LBUTTONUP SetWindowText(Stat1,"LEFT MOUSE BUTTON UP :-)") CASE WM_MOUSEMOVE ' horizontal position of cursor, X Position = LOWORD(lParam) ' vertical position of cursor, Y Position = HIWORD(lParam) SetWindowText(Stat1, STR$(LOWORD(lParam)) & " " & STR$(HIWORD(lParam))) END SELECT END EVENTS MAIN
translates to
LRESULT CALLBACK Form1Proc (HWND hWnd,UINT Msg,WPARAM wParam,LPARAM lParam)
{
if(Msg==WM_LBUTTONDOWN )
{
SetWindowText(Stat1,"left mouse button down :-(");
goto L1000;
}
if(Msg==WM_LBUTTONUP )
{
SetWindowText(Stat1,"LEFT MOUSE BUTTON UP :-)");
goto L1000;
}
if(Msg==WM_MOUSEMOVE )
{
SetWindowText(Stat1,join(3,str(LOWORD(lParam))," ",str(HIWORD(lParam))));
}
L1000:; // SelectState[PusherSelectState].CaseFlag 3
if(Msg==WM_DESTROY)
{
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hWnd,Msg,wParam,lParam); // endevents
}
The BEGIN EVENTS Form2Proc section, which does use a procedure name but with no MAIN statement appended to END EVENTS, of this BCX code,
GUI NOMAIN FUNCTION WINMAIN () GLOBAL Form1 AS HWND GLOBAL Stat1 AS HWND Form1 = BCX_WND("FORM1", Form1Proc, "Form1 Simple BCX_WND Sample") Stat1 = BCX_STATUS("Ready",Form1) SHOW(Form1) GLOBAL Form2 AS HWND GLOBAL Stat2 AS HWND Form2 = BCX_WND("FORMTWO", Form2Proc, "Form2 Simple BCX_WND Sample") Stat2 = BCX_STATUS("Ready",Form2) SHOW(Form2) FUNCTION = BCX_MSGPUMP() END FUNCTION BEGIN EVENTS Form1Proc SELECT CASE CBMSG CASE WM_LBUTTONDOWN SetWindowText(Stat1,"left mouse button down :-(") CASE WM_LBUTTONUP SetWindowText(Stat1,"LEFT MOUSE BUTTON UP :-)") CASE WM_MOUSEMOVE ' horizontal position of cursor, X Position = LOWORD(lParam) ' vertical position of cursor, Y Position = HIWORD(lParam) SetWindowText(Stat1, STR$(LOWORD(lParam)) & " " & STR$(HIWORD(lParam))) END SELECT END EVENTS MAIN BEGIN EVENTS Form2Proc SELECT CASE CBMSG CASE WM_LBUTTONDOWN SetWindowText(Stat2,"left mouse button down :-(") CASE WM_LBUTTONUP SetWindowText(Stat2,"LEFT MOUSE BUTTON UP :-)") CASE WM_MOUSEMOVE ' horizontal position of cursor, X Position = LOWORD(lParam) ' vertical position of cursor, Y Position = HIWORD(lParam) SetWindowText(Stat2, STR$(LOWORD(lParam)) & " " & STR$(HIWORD(lParam))) END SELECT END EVENTS
translates to
LRESULT CALLBACK Form2Proc (HWND hWnd,UINT Msg,WPARAM wParam,LPARAM lParam)
{
if(Msg==WM_LBUTTONDOWN )
{
SetWindowText(Stat2,"left mouse button down :-(");
goto L1001;
}
if(Msg==WM_LBUTTONUP )
{
SetWindowText(Stat2,"LEFT MOUSE BUTTON UP :-)");
goto L1001;
}
if(Msg==WM_MOUSEMOVE )
{
SetWindowText(Stat2,join(3,str(LOWORD(lParam))," ",str(HIWORD(lParam))));
}
L1001:; // SelectState[PusherSelectState].CaseFlag 3
return DefWindowProc(hWnd,Msg,wParam,lParam); // endevents
}
This WM_DESTROY handler,
if(Msg==WM_DESTROY)
{
PostQuitMessage(0);
}
is automatically generated by the BEGIN EVENTS ... END EVENTS statements when the ProcedureName is not specified and, as well, when a ProcedureName is specified and the MAIN statement is appended to the END EVENTS statement.
Therefore, in these instances, it is redundant to include
CASE WM_DESTROY PostQuitMessage(0)
in the BCX code of the events loop.
BCX_FORM creates a window.
Syntax:HndlWnd = BCX_FORM([Caption AS STRING] _ [, Xpos AS INTEGER] _ [, Ypos AS INTEGER] _ [, Width AS INTEGER] _ [, Height AS INTEGER] _ [, WinStyle AS INTEGER] _ [, ExWinStyle AS INTEGER]) Return Value:
Parameters:
|
π When using BCX_FORM without
GUI Classname$
a ClassName must be provided by using
BCX_CLASSNAME$ = "SomeClassName"
prior to initialization of BCX_FORM.
Form1 = BCX_FORM()
Form1 = BCX_FORM("My Form")
Form1 = BCX_FORM("My Form", 0, 0, 310, 250)
Form1 = BCX_FORM("My Form", 0, 0, 100, 100, WS_CAPTION | WS_SYSMENU)
In Examples 1, 2 and 3 the default style used is
WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS
The default window Style for a BCX_FORM control also can be changed by using the MODSTYLE function.
When a BCX GUI program is translated, a WNDCLASSEX structure named BCX_WNDCLASS is created and declared GLOBAL. It is initialized to the default values by the internal BCX translator BCX_INITGUI( ) procedure and then registered using the internal BCX translator BCX_REGWND procedure. BCX_REGWND checks to see if a window class of the name being registered has already been used and if so does not register it again. It allows 256 different (non case sensitive) window classes to be registered. It also sets the BCX_GUI_INIT system variable to TRUE, indicating that the procedure has been run and it will exit without doing anything next time it is called.
BCX_REGWND registers a window class.
Syntax:BCX_REGWND(ClassName AS STRING, ProcedureName) Parameters:
|
If ClassName exists and ProcedureName is NULL then ClassName will be removed from the list of windows classes registered in BCX and the class will be unregistered with an UnregisterClass WinAPI call.
When a BCX GUI program is translated, an HINSTANCE named BCX_HINSTANCE is created and declared GLOBAL. It is initialized to the value of the HINSTANCE of WinMain. From that point on, it is free to be referenced.
π BCX_HINSTANCE should be considered a read-only HINSTANCE. Changing its value at runtime is not advisable.
The controls are designed to scale with the font and the userβs display settings. For example, the user may be on a high-DPI system, or simply may prefer that the text be larger (so that, yβknow, they can see it), and dialog boxes will scale to accommodate those changes.
π Important: Although BCX_SCALEX and BCX_SCALEY are accessible from the code, they are intended to be read-only. Modifying their values after initialization may lead to unpredictable GUI behavior.
Syntax:NumberX = BCX_SCALEX NumberY = BCX_SCALEY Return:
Parameters:
|
BCX_SCALEX and BCX_SCALEY are not intended for pixel-perfect layout.
The default values for BCX_SCALEX and BCX_SCALEY are derived using the Win32 API function MapDialogRect(), which converts dialog units into pixels based on the system font metrics. Since MapDialogRect() always assumes that the system font is being used in the control, the resulting pixel-based scaling factors may be inaccurate if other fonts are used in the GUI.
If the application uses a font other than the system default, or mixes fonts across different controls, the control dimensions may need to be adjusted manually. In these cases, BCX_SCALEX and BCX_SCALEY can be read to guide the adjustments.
BCX_MSGPUMP creates a message loop to retrieve messages from the message queue of the non-MDI gui programs, and dispatch them to the destination window procedures.
Syntax:BCX_MSGPUMP(HndlAccel AS HACCEL) Parameters:
|
GUI NOMAIN, ICON, 123 GLOBAL FooBloo AS HACCEL FUNCTION WINMAIN GLOBAL Form1 AS HWND BCX_SETMETRIC("DialogUnits") BCX_REGWND("MAINFORM", form1Proc) Form1 = BCX_FORM("BCX_TEMPLATE", 0, 0, 110, 110) BCX_SET_FORM_COLOR(Form1,QBCOLOR(31)) CENTER(Form1) SHOW(Form1) FUNCTION = BCX_MSGPUMP(FooBloo) END FUNCTION BEGIN EVENTS form1Proc SELECT CASE CBMSG CASE WM_GETDLGCODE FUNCTION=DLGC_WANTALLKEYS CASE WM_KEYDOWN SELECT CASE wParam CASE VK_HOME MSGBOX "VK_HOME" CASE VK_END MSGBOX "VK_END" CASE VK_NEXT MSGBOX "VK_NEXT" CASE VK_PRIOR MSGBOX "VK_PRIOR" CASE VK_DOWN MSGBOX "VK_DOWN" CASE VK_UP MSGBOX "VK_UP" CASE VK_LEFT MSGBOX "VK_LEFT" CASE VK_RIGHT MSGBOX "VK_RIGHT" CASE VK_RETURN MSGBOX "VK_RETURN" END SELECT CASE WM_CLOSE DestroyWindow(Form1) END SELECT END EVENTS MAIN
BCX_MDI_MSGPUMP creates a message loop to retrieve messages, from the message queue of a MDI gui program, and dispatch them to the destination window procedures.
Syntax:BCX_MDI_MSGPUMP(HndlAccel AS HACCEL) Parameters:
|
BCX_SETMETRIC specifies the units for locating and sizing forms and controls. The case insensitive argument can be either "PIXELS" or "DLGUNITS".
Syntax:BCX_SETMETRIC(Metric AS STRING) Parameters:
|
The following procedures are used to replace members of the WNDCLASSEX structure. For more information, visit the Microsoft WNDCLASSEX structure webpage.
BCX_SETBKGRDBRUSH sets the background brush.
Syntax:BCX_SETBKGRDBRUSH(HndlWnd AS HWND, Brush AS HBRUSH) Parameters:
|
BCX_SETCLASSSTYLE sets the class style.
Syntax:BCX_SETCLASSSTYLE(HndlWnd AS HWND, Style AS LONG) Parameters:
|
BCX_SETICON sets the Icon.
Syntax:BCX_SETICON(HndlWnd AS HWND, Icon AS INTEGER) Parameters:
|
BCX_SETICONSM sets the small icon.
Syntax:BCX_SETICONSM(HndlWnd AS HWND, smIcon AS INTEGER) Parameters:
|
BCX_SETCURSOR sets the cursor.
Syntax:BCX_SETCURSOR(HndlWnd AS HWND, CursorName AS STRING) Parameters:
|
Primarily intended for parent forms and dialogs, BCX_SETCLIENTSIZE sets the bounding rectangle based on the desired size of the client area. One way to understand what this means is to think about a painting. The canvas size determines the frame size and not the other way around.
Syntax:BCX_SETCLIENTSIZE(HndlWnd AS HWND, _ iWidth AS INTEGER, _ iHeight AS INTEGER _ [, ScaleWidth AS SINGLE] [, ScaleHeight AS SINGLE]) Parameters:
|
$BCXVERSION "8.0.4" GUI "BCX_SETCLIENTSIZE" CONST MAXX = 256 CONST MAXY = 256 SUB FORMLOAD GLOBAL Form1 AS HWND Form1 = BCX_FORM("BCX_SETCLIENTSIZE") BCX_SETCLIENTSIZE( Form1, MAXX, MAXY) BCX_SET_FORM_COLOR(Form1, QBCOLOR(0)) MODSTYLE(Form1, 0, WS_MAXIMIZEBOX|WS_MINIMIZEBOX, FALSE) CENTER Form1 SHOW Form1 CALL Drawit END SUB BEGIN EVENTS SELECT CASE CBMSG CASE WM_QUIT, WM_CLOSE, WM_DESTROY END END SELECT END EVENTS SUB Drawit FOR INT i = 0 TO 360 STEP 45 ' draw 8 spokes BCX_POLAR_LINE(Form1, 128, 128, 100, i, QBCOLOR(9)) NEXT BCX_PENSIZE = 4 ' fat pixels please FOR INT i = 0 TO 360 STEP 10 ' draw a ring of colored pixels BCX_POLAR_PSET(Form1, 128, 128, 120, i, QBCOLOR(RND2(9, 14))) NEXT END SUB
π iWidth and iHeight are always assumed to be PIXELS. BCX can scale PIXELS to dialog units if BCX_SCALEX and BCX_SCALEY or appropriate values are used for the optional ScaleWidth and ScaleHeight arguments. However, that will work only if the BCX GUI statement is used without the PIXELS qualifier. For example:
$BCXVERSION "8.0.4" GUI "BCX_SETCLIENTSIZE_DLU" CONST MAXX = 256 CONST MAXY = 256 SUB FORMLOAD GLOBAL Form1 AS HWND Form1 = BCX_FORM("BCX_SETCLIENTSIZE_DLU") BCX_SETCLIENTSIZE( Form1, MAXX, MAXY, BCX_SCALEX, BCX_SCALEY) BCX_SET_FORM_COLOR(Form1, QBCOLOR(0)) MODSTYLE(Form1, 0, WS_MAXIMIZEBOX|WS_MINIMIZEBOX, FALSE) CENTER Form1 SHOW Form1 CALL Drawit END SUB BEGIN EVENTS SELECT CASE CBMSG CASE WM_QUIT, WM_CLOSE, WM_DESTROY END END SELECT END EVENTS SUB Drawit FOR INT i = 0 TO 360 STEP 45 ' draw 8 spokes BCX_POLAR_LINE(Form1, 128, 128, 100, i, QBCOLOR(9)) NEXT BCX_PENSIZE = 4 ' fat pixels please FOR INT i = 0 TO 360 STEP 10 ' draw a ring of colored pixels BCX_POLAR_PSET(Form1, 128, 128, 120, i, QBCOLOR(RND2(9, 14))) NEXT END SUB
The BCX_GET_WINDOW_HEIGHT function returns an integer containing the height of the client area of a windows form.
Syntax:RetVal = BCX_GET_WINDOW_HEIGHT(HndlWnd AS HWND) Return Value:
Parameters:
|
The BCX_GET_WINDOW_WIDTH function returns an integer containing the width of the client area of a windows form.
Syntax:RetVal = BCX_GET_WINDOW_WIDTH(HndlWnd AS HWND) Return Value:
Parameters:
|
Mainly intended to easily resize child control windows, BCX_RESIZE also can be used to resize parent windows and dialogs.
Syntax:BCX_RESIZE(HndlWnd AS HWND, iWidth, iHeight) Parameters: |