Win32lib is a wrapper
From EuWiki
For better understanding of some of the pages, perhaps more pointedly Event_driven_programming, it is probably necessary to explain how Windows sees a program, how win32lib defines a program and what are the correspondences between the two models.
Win32lib only wraps the Windows API, providing high level routines to hide a large amount of tricky details C programmers deal with daily. This explains how the documentation is organised: by routine, rather than by task or theme. Win32lib is not a standalone GUI toolkit, like GTK or wxEuphoria.
Since some sections of this page deal with Windows basics , they may become common to several GUI libraries. As a consequence, making these sections into templates may be helpful .
Contents |
windows and controls
From the Windows API standpoint
The base objects Windows acts upon are windows. They occupy some rectangular portion of the screen, belong to some class specifying a number of defaults for any window of that class, and have styles, which define various elements of behaviour and appearance, some of which can be dynamically toggled.
Each window has a handle, a machine integer that uniquely identifies it. When processing a window handle in some Euphoria code, always store it as an atom, as it would not usually fit into an Euphoria integer. Handles of destroyed controls may be recycled.
Controls are just windows with a specific behaviour intended. A list, a button, is a 'window' of the appropriate class and having appropriate styles.
The only difference is that windows can be top level (stand their own) while a control must belong to (be the child of) some parent window (or control).
Each class has a default processing routine, which handles any message passed to any instance of that class, ie any window of that class. Because of the abovementioned difference, there are distinctions to be made about these routines, which would fall outside the scope of this paper.
Each window has its message loop, which polls a private message queue. When a message targets the control, any specific code is executed, and then, if no special action was taken, the message is passed to the default processing routine of the control.
Each control or window has an identifier. This identifier is often unique within an application, but needs not to be unique across applications. It is used in various messages, and tells the recipient what the control is doing (so some may have the same id if they have the same function). They are logical identifiers, while the handles are physical identifiers.
From the win32lib standpoint
win32lib knows about controls, some of which have no parent. A control belongs to a family defined at creation time. Each control is uniquely known by its id, a Euphoria integer. ids are recycled; as a consequence, you must be careful, when destroying a control, to never reference that control again, as the id might be used later to create a probably unrelated control. They have styles closely matching the native Windows ones.
Controls have event handlers, which tell what the control does in reaction to an event. When all handlers for the event have been called, and if no special action was taken, the default processing routine for the control is passed the message that triggered the event.
Do not assume anything at all about control ids, except that they are greater than 0. Because of the way the library recycles ids, controls created straight one after the other won't have increasing ids. The most likely pattern is a decreasing sequence of ids, with breakups as more space is allocated to hold control data. If many control destructions occur, this weak assumption doesn't even hold. In particular, you cannot infer anything about item positions from their ids. The library currently looks up destroyed control ids (most recent first), then available free space from the top down. If all this fails, more free space is allocated and the lowest new id is used. Calling setControlBlocks() with a large enough value will cause part of the controls you'll create next to have decreasing ids, depending on how many recyclable ids there are at the time you create the controls.
Bridges between the models
There are a variety of ways to get native control information and, in the other direction, to associate native data with win32lib concepts.
- getId(atom handle) returns 0 if the handle is unknown, else the win32lib id of the control.
- getIdFromDC(atom hDC) determines whether its argument is a device context handle and, if so, whether it belongs to a win32lib control. The id is returned on success, and 0 on failure.
- getHandle(integer id) does the conversion in the other direction. It always returns a valid handle, unless the control was destroyed.
- getHandles() returns the list of handles known from win32lib.
When explicitly creating a control, win32lib sets its control identifier to the win32lib identifier. However, this doesn't hold true in some special cases, and in particular for popup menus: see comment at line 13037 in win32lib.ew. The problem is that Windows menus just do not have identifiers, while menu items have one. getId() doesn't handle this special case currently.
Events and messages
From the Windows API standpoint
Windows knows about hardware events, like a key on the keyboard being pushed or some data packet pending on a serial port. It will translate any relevant event to one or more messages, which will be sent to one or more windows. A message always has three parts:
- An integer, the identifier, which says which sort of information is being passed. For instance, the value 260 is known as WM_SYSKEYDOWN; a message with this identifier informs of the target control of some system command (an Alt-something key sequence, a system menu item being clicked, etc.)
- An integer, historically 16-bit and called wParam, first parameter of the message;
- An integer, historically a 32-bit pointer and called lParam. It is the second parameter of the message, and often points to a data structure being passed to the control.
When a message is sent, the recipient must be known. The recipient usually has no knowledge of the sender but will know the meaning of the message and format and meaning of the parameters.
Messages are used for any communication between windows or between windows and Windows:
- The operating system may send messages to windows or controls, often to report a phusical event.
- Applications send messages to controls so as to pass data to them or retrieve data from them.
- Controls that belong to a parent window usually send it notifications, which take the form of a WM_COMMAND or WM_NOTIFY message whose lParam points to a structure containing a notification code and sometimes extra data as well.
Any application may send any message to any window. If the targeted recipient doesn't understand or expect the message, the processing routine of its class usually returns 0.
From the win32lib standpoint
Controls receive events, which are known by two elements:
- An integer, the event type, which belongs to a predefined set of constants in win32lib. For instance, the w32HMouse event is used to tell a control about something the mouse did;
- A sequence, the data, whose layout and contents depend on the event type and the control type.
Some events only notify program conditions, not hardware events. Thus, there is a w32HIdle event which is sent to controls when no message is being processed for that control. More on this in the event programming page.
