FAQ OCXs & Forms

OCX & Form related questions  (under construction)

What is OCX?

What is a form?

GFA-BASIC 32 forms are the windows that are the basic of a program. From prior GFA-BASIC versions we know the OpenW, ParentW, ChildW, and Dialog windows that were handled using the well known  MENU() array values. GFA-BASIC 32 took a new way and replaced this by the Visual Basic compatible 'form' concept. Now, OpenW/ParentW/ChildW #n are forms as well. Their form name is Win_n, where n stands for the window number, for instance Win_1. A dialog is a form also. Their object name is Dlg_n, where n is a value between 0 and 31.
 
A form can be created in code using
 
Form frm1 
Do : Sleep : Loop Until Me Is Nothing
 
Sleep is used to obtain messages and dispatch them to the window procedures of the windows of the application. Me is a GFA_BASIC variable of type Form that contains the current active form. If the form is closed the object is set to Nothing. This marks the end of the program.
A form can also be created in the Form-editor. To use such a form use
 
Loadform frm1 

How do I respond to OCX messages?

The VB way, e.g. using Sub events. A sub event's name is always constructed by a contraction of the OCX/Form name followed by an underscore, folowed by the event name. For instance, an OpenW #31 form has an event sub to prevent the closing of the window. The Cancel? parameter is ByRef and is False when the sub is entered. Setting Cancel? to True prevents the window from closing.

Sub Win_31_Close(Cancel?) 
 Cancel? = True
 

How many event subs are there?

Again, most event subs conform to VB. However, GFA-BASIC offer many more event subs, especially for Forms.

What are the properties, events, and methods of a form?

Since GB32 tries to be VB compatible, it provides almost the same properties, methods, and events as VB. There are two distinct differences though. First, GB does not the provide OLExxx facility that VB does. Secondly, GB32 has a lot more properties, events and methods than VB. The properties and methods for a form can be selected from an autocomplete popup box. The required parameters and their types are displayed in the statusbar. Most of them speak for them selves.
 

What is the difference between _Message and _MessageProc?

The definitions:
 
Sub frm_Message(hWnd%, Mess%, wParam%, lParam%)
Sub frm_MessageProc(hWnd%, Mess%, wParam%, lParam%, _
                      Retval%, ValidRet?)

Two strange, badly documented event subs are provided for Forms: the _Message and _MessageProc event. Although they sound much alike, they are quite different. The first thing to note is that the subs are invoked from different places. _Message is invoked as part of the Sleep (GetEvent/PeekEvent) statement and _MessageProc is called from inside the window procedure of the form. _Message is called only for a handful of messages, but _MessageProc is called for all messages.
 
_MessageProc event sub
With the _MessageProc sub you can actually filter or influence the behavior of the GB32 window procedure for the Form window class. The _MessageProc is called before GB32 handles the message itself (more or less). The sub obtains six message parameters. The first four are the same as defined for a Windows API window procedure. Every message, whether it is obtained from the message queue (the posted messages) or by a direct call from any other source (SendMessage), is handled in the window procedure. The hWnd parameter is the window to which the message is sent (we already know the objects name: frm and we could obtain the window handle from the object, that would have lowered the number of parameters by one). The Msg parameter is the message number—which is usually a constant such as WM_ACTIVATEAPP or WM_PAINT. The wParam and lParam parameters differ for each message, as does the return value; you must look up the specific message to see what they mean. Often, wParam or the return value is ignored, but not always.
 
The _MessageProc has two additional parameters (ByRef) that allow you to return a value. For instance, when you want GB not to handle a certain message you can set the ValidRet? variable to True and provide a return value by setting RetVal%. What value RetVal must have is defined in the Windows API SDK. It often says something like: "If you handle this message return zero (or..)".
 
Now let us look at an example. Suppose you want to store the window coordinates of OpenW #1 in the register so the application can use these value to open at the same place. In GB you must then handle the sub events _ReSize and _Moved to store the coordinates. As an alternative you could use _MessageProc and handle the WM_EXITSIZEMOVE message.
 
Sub Win_1_MessageProc(hWnd%, Mess%, wParam%, lParam%, Retval%, ValidRet?) 
 Local Int x, y, w, h 
 Switch Mess 
 Case WM_EXITSIZEMOVE 
 GetWinRect hwnd, x, y, w, h 
 SaveSetting "MyComp", "ThisApp", "Position", Mkl$(x, y, w, h)
 ValiRet? = True : RetVal = 0 
 EndSwitch 
EndSub
 
_MessageProc actually _is_ the subclass proc for the GB OpenW, Form and Dialog windows. Subclassing is built-in feature of GFA-BASIC 32. The OCX Form is perfectly suited to write custom controls.
 
_Message event sub
_Message is different: you cannot filter messages and return values, you can only respond, to WM_SIZE, or WM_PAINT for instance. Why these? Because these are posted messages, messages that are retrieved from the message queue. Most posted messages have a accompanying sub event. A WM_SIZE message results in calling the _ReSize event sub.
You can use the _Message sub to handle many messages that are otherwise handled in the event subs. All you need to know is which messages are posted. These are all input messages like key and mouse messages, window management messages like moved, sized and wm_paint. You must then, just as in _MessageProc, create a Switch/Case structure to respond to the message. The main disadvantage is that you must interpret the wParam and lParam yourself...
 
The order in which the sub events are called
You can easily test in which order the sub events are called. For posted messages, those that are retrieved from the message queue using Sleep, the _Message() event is called before any other sub. Then the message is dispatched to the window procedure and the _MessageProc is called. And at last, the event sub is invoked. For a WM_SIZE message the sequence is:
 
Win_1_Message()
Win_1_MessageProc()
Win_1_ReSize