The Cincom® ObjectStudio® GUI Files – Part 2: Fundamentals
We already discussed in the Cincom Smalltalk Digest some of these innovations that will make it into the upcoming release of ObjectStudio, like the MarqueeDialog and the ProgressBar. However, the focus of the project is to provide a new GUI library of Windows-native widgets using DLLCC instead of writing them in C.
A preview of the new library will be shown at the Smalltalk Industry Conference in Phoenix next month.
In Part 1 of the ObjectStudio GUI Files, we did a small introduction of the project, and in this month’s Digest, we’ll have a closer look at how the fundamentals are implemented.
WM_Messages is a namespace that contains an entry for each constant used in Windows. Once you have imported the namespace into your class, you can use the Windows constants like PGN_SCROLL, RB_SETTOOLTIPS, WM_GETFONT and many more just like you would in C.
Since every dialog and every control is essentially a window, we constructed a class hierarchy. UIView is the super-class for all of the new “User-Interface” classes. Each subclass from UIView will be able to implement its own Message Maps, Windows Procedure, Icon and Styles.
MessageMap is a shared variable on UIView, and it’s an array. The index is the value of the Windows Message, and the value is a symbol that represents the message that is being send to the Windows Procedure. An example of such a definition is:
^(Array new: 800)
at: WM_ACTIVATE put: #WM_ACTIVATE:msg:wParam:lParam:;
at: WM_ACTIVATEAPP put: #WM_ACTIVATEAPP:msg:wParam:lParam:;
at: WM_APPCOMMAND put: #WM_APPCOMMAND:msg:wParam:lParam:;
If behavior of a certain control is different from the one defined by UIView, then the message can be overwritten for that class. Each instance of UIView or any of its subclasses can have a localMessageMap. The Windows Procedure will first check the localMessageMap, and when it finds no reference to the Windows Message, it will search for it in the MessageMap.
Register the Class
We register the class UIView with the operating system to set the WndProc as the callback for all windows events to this class.
More information regarding the WNDCLASSEX structure and RegisterClassEx() API used can be obtained on the MSDN pages.
When our UIView or any of its subclasses receives a message from Windows, the Windows Procedure defined with the class registration or by subclassing the original Windows Procedure receives the parameters from Windows and performs the following steps.
First the localMessageMap is searched for a matching entry, then the global MessageMap. If we find the key, we retrieve the assigned method selector and forward the current parameters. If no reference is found, the default windows handler is used.
All method selectors must accept four parameters:
- The windows handle
- The message number
The content and meaning of wParam and lParam are defined by the message
wParam specifies if the window is activated or deactivated as well as the window state (minimized).
lParam specifies the window being activated or deactivated.
Creating a View
The UIView is created using the CreateWindowExW() API. The following arguments are supplied to the API:
- Extended style
- Class name
- Window name
- Window Style
- Parent window
Window Style and Extended Style
Each UIView class has a default wndStyle and wndExtStyle. These are defined with class methods.
^WS_BORDER | WS_VISIBLE | WS_CHILD
^WS_EX_LEFT | WS_EX_LTRREADING | WS_EX_RIGHTSCROLLBAR | WS_EX_WINDOWEDGE
The styles give information on how the Window has to look and behave and are different for each subclass. Each instance of a UIView class can overwrite the defaults by using the style and exStyle instance variables.
Want to know more details or see examples on how this all works? Join us at STIC’13 in Phoenix, June 9-12, 2013.