The current ObjectStudio GUI project is bringing considerable innovations to the environment.

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

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.

UIView

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.

Message Map

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:;
   …
   yourself

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.

Windows Procedure

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:

  1. The windows handle
  2. The message number
  3. wParam
  4. lParam

The content and meaning of wParam and lParam are defined by the message

e.g. WM_ACTIVATE

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:

  1. Extended style
  2. Class name
  3. Window name
  4. Window Style
  5. X
  6. Y
  7. Width
  8. Height
  9. Parent window
  10. Menu
  11. hInstance
  12. lpParam

Window Style and Extended Style

Each UIView class has a default wndStyle and wndExtStyle. These are defined with class methods.

wndStyle
   ^WS_BORDER | WS_VISIBLE | WS_CHILD
wndExStyle
   ^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.

Advertisements