CHAPTER 7
THE WINDOWS OPERATING SYSTEM.
INTRODUCTION:
This chapter introduces the reader to a kind of general overview of the Windows operating system, before introducing the basic design of the code of an actual Windows program, which is given after the chapter on Data Structures.
I suggest that this chapter may be simply read through, rather than studied too closely, since the intention is to prepare the reader to be receptive to an understanding of the topics that will be considered in greater detail later on.
There are two main features of the Windows operating system that the programmer has to deal with, and this chapter therefore introduces these two most important topics in the context of the overall design concept of the system as a whole.
It might initially be supposed that the Windows operating system might be a very complex topic, necessitating many difficult chapters in order to gain an understanding of it. This might indeed be the case for a programmer working on the internal design of the operating system code, but it is by no means the case for a programmer, who intends only to design programs that merely make use of the operating
system. Indeed, only Microsoft programmers are permitted access to the system code itself.
There are only two main features of the Windows operating system generally, that an applications programmer needs to become acquainted with, and they are: Windows messages, and the Windows API (or Application Programming Interface), which is a list of operating system functions or procedures.
Several important supplementary programming topics need to be understood in order to make use of these two main features, and these are: functions, or procedures, data structures, the stack, equates, and Windows handles. Armed with an understanding of basic programming, along with these topics, a programmer can proceed to create working Windows programs, and will be able to understand the implementation of various features of a Windows program, like creating Windows, menus, using files, printing to the screen, and so on.
Firstly, I attempt to explain how, and why, the two main features, that is, messages and the Windows API, were designed as the two forms of interaction of a program with the operating system.
AN OVERVIEW OF THE WINDOWS OPERATING SYSTEM:
To understand the peculiarities associated with the Windows operating system, it is, perhaps, most instructive to begin with an understanding of the peculiar problems the operating system has to deal with.
Suppose you have two applications open on the desktop at the same time, such as a word processor and a graphics editor. You can easily switch the focus of attention from one to the other and back again, and work in one and then in the other. While you are working in one, the other is dormant in the background. Both of these programs, can be seen to be resting against the backdrop of the desktop belonging to the operating system itself. In a like manner, the internal codes of the two programs are also stored in memory (RAM) against a backdrop, as it were, of the operating system code itself, also stored in RAM.
A major problem that the operating system has to deal with here is how to manage the two programs, such that either can be active, while the other is only dormant, and not completely shut down.
A second problem is that the codes of the two applications, and that of the operating system itself, were created independently of one another, and
represent separate blocks of code, designed by different programmers, none of whom knew the internal working of the other's codes.
We can thus see immediately that an interface, or method of communication, has to be designed to allow all these separately designed blocks of code to interact together. This means that there have to be specified forms of input to and output from one code to the other, which the separately designed codes can recognise and make use of. A Windows programmer thus designs his code to receive particular kinds of input from and provide particular kinds of output to the operating system.
To understand the design of input to a program from the operating system, we must examine the concept of a Windows 'message'.
Then, to understand how to provide output from a program to the operating system, and thence to the hardware, like the screen, we must examine the use of the Windows API functions.
These are the two principal topics that enable the programmer to understand how to write programs to work with the Windows operating system.
THE CONCEPT OF A WINDOWS MESSAGE:
It might have been possible for a program to provide a set of entry points to its code, to correspond to every possible kind of input, so that the operating system could activate the program at the appropriate entry point. However, the Windows operating system was not designed in that way. Indeed, it was designed to avoid any rigid, immediate link between an input from the hardware, like the mouse, or keyboard, and the program response. Such an immediate link would make it difficult to solve the problem of managing multiple programs open at the same time.
Instead, the operating system was designed to communicate input to a program by means of a 'messaging' system, involving 'messages' all sent to one of only two program entry points.
Such a messaging system is simpler to design, and is certainly more flexible than having multiple program entry points for each kind of input. The ability to store messages also avoids the necessity for immediate activation of a program in response to any particular input. The messaging system, in fact, enables the operating system to separate user inputs from program activation, so that Windows can
collect messages sent to different windows, in a queue, and organise program activation independently.
If a user, for example, uses the mouse to drag a window across the screen, it may pass over other windows on the screen, which means the user action is sending input to two or more windows at the same time. That is, the window underneath the dragging operation has to repaint its client area when the dragged window exposes it again to view., even though it remains dormant in the background.
The messaging system has the flexibility that allows the operating system to organise the separate activations of the different windows, as well as the system desktop, which is also affected by the same user action. Windows thus provides each program with a 'message queue', which allows numbers of messages to be assigned to a program independently of the time and sequence of the program's response. The messaging system is thus a method designed to solve the problem of managing, at the same time, the operating system itself, together with all the programs that may be open on the desktop at the same time.
A PROGRAM'S RESPONSE TO MESSAGES:
The concept of a message is distinct from the concept of a response to a message, and the message relationship of a program with the operating system is not the same as the response relationship.
When a program code is actually implementing its response to a particular message, Windows hands the operating system over to the program, since this is the only way in which the program can communicate with the hardware.
In this situation the program is communicating with Windows, rather than Windows communicating with the program, and this not done via a messaging system, as before, but by the program accessing the operating system via multiple entry points, which are a set of possible procedure or function calls, which are referred to as the Windows API, or Application Programming Interface, as mentioned already. That is, the set of multiple entry points is referred to as the 'interface' between the program and the operating system.
The reason that a messaging system is not needed for program output is that the program needs only a one-to-one, immediate access to the operating system and hardware, and does not have to manage multiple, independent programs. Even though the messaging system is more flexible, it is also more indirect, and therefore less warranted in the case of an activity that is single and direct. A messaging system must end in a direct activity in any case, since it only selects an appropriate activity, and is not actually such an activity in itself. Where, however, a
program does have more than one window of its own open at the same time, and wants to work with all of them, it can use the Windows messaging system to send messages to the different windows.
The fact that a message, placed by Windows in a program's message queue, is not implemented immediately, leads to the necessity that a program should notify the operating system when it picks up and wants to implement its response to a particular message taken from its message queue.
This is done by the program sending the message back to Windows, so that the operating system can make a record of what the message is and then send it back to the program, again, for immediate implementation. For immediate implementation, the operating system sends the message to the program's second entry point, and not to the message queue entry point and, at the same time, makes the operating system available to the program for immediate use.
The reason that the program has a second entry point is thus that all messages sent to the second entry point are for immediate implementation only, whereas those sent to the first entry point, associated with the message queue, are not.
The following sections give a more detailed overview of Windows messages and the API but, first, we must consider the nature of a programming device known as an 'equate'.
MESSAGES AND EQUATES:
I introduce equates here in the absence of a decision as to where else might be the more appropriate place to introduce the concept. I have chosen to introduce it here, in preparation for the discussion of Windows messages, on the basis that every Windows message is in the form of an equate. Every Windows message is identified simply as a number, but inserting Windows message numbers, as such, into a Windows program code would make it very difficult and laborious for a programmer to reread the code at a later time, and remember all the messages to which the different numbers refer. An equate, therefore, is a programming device designed to circumvent this problem, in which a number can be replaced with an entire word, as a name. This then allows Windows messages to be given recognisable names which the assembler will translate into the corresponding numbers when the program is compiled.
The programmer can thus easily recognise the messages, inserted into the code, by their names. The particular Windows message number 200h, for example, is given the name WM_MOUSEMOVE, and it is clearly much easier for a programmer to recognise the name, and what it signifies, than to have to recognise the number 200h each time. The
name WM_MOUSEMOVE is thus defined as the number 200h by means of the equ (equate) instruction, as follows:
WM_MOUSEMOVE equ 200h
Every name in the code that is to be used as an equate must be defined in this manner, somewhere in the code or data section of the program. Windows message names and numbers were defined by Microsoft Windows programmers, but the definitions must be included in the code so that the assembler can translate them. You could give your own names to Windows message numbers, if there were any point in doing so, since it is the numbers, and not the names, that are used in the actual machine code. A programmer can also create equates of his own as desired, for his own code, which can be very useful to specify offset and flag numbers, as will be explained elsewhere.
I like to define a program's own equates in a special include file called EQUATES.inc. Windows equates, however, are normally defined within the Windows.inc include file.
WINDOWS MESSAGES OVERVIEW:
THE MESSAGE QUEUE:
It has been mentioned already that Windows communicates with a program via two program entry points, and that a program's first entry point is used merely to assign messages to a program, via a queue, independently of the time, and possibly of the order, of their implementation.
The message queue itself exists within the operating system, and not within the program's own code.
The program's first entry point code thus calls an API function, which activates the message queue, which exists within the API function's code. When the operating system is ready to activate the
window, it returns the instruction pointer from within the API function code to the program's code, with the message as part of the data returned by the API function.
The program then sends the message back to Windows to notify Windows that it has picked up the message for immediate implementation. It is also possible for a program, when implementing its response to one message, to examine the message queue to see what other messages are listed there, and remove messages, if it wants to do so. A program can thus have a degree of control over the message queue itself.
WINDOWS MESSAGES:
As mentioned previously, the messages sent through the message queue are simply binary numbers but are most conveniently expressed in the form of equates having names that indicate immediately to the programmer what a particular message means.
The Windows documentation has a list of equates for the messages sent to a program's main message loop, and it is thus advisable for the programmer, who will want to refer to such documentation, to keep and use the same system of message equate names within his own program.
The messages to the main message loop are all given equate names beginning with WM_, such as WM_CHAR etc. This helps to distinguish them from sets of supplementary messages and other equate name sets used by the system. You can think of WM_ as standing for 'WINDOWS MESSAGE_'.
A program opened on the desktop has a whole series of such messages sent to it from the system from the first moment the user opens it. All such messages are picked up from the queue and returned to the program's second entry point. I used a simple debug code (we shall consider debugging later on) to intercept all messages coming through a program's second entry point and save them to a file. As a matter of interest and instruction, the following is a list of the messages obtained from such a debug file by simply opening an empty program window on the screen and then closing it again, without carrying out any other programming activity. The message numbers are listed on the right, and the equate names on the left:
Equate Name Message Number
The program is opened, and starts here
WM_GETMINMAXINFO 36
WM_NCCREATE 129
WM_NCCALCSIZE 131
WM_CREATE 1
WM_SHOWWINDOW 24
WM_WINDOWPOSCHANGING 70
WM_WINDOWPOSCHANGING 70
WM_ACTIVATEAPP 28
WM_NCACTIVATE 134
WM_GETICON 127
WM_GETICON 127
WM_GETICON 127
WM_ACTIVATE 6
WM_SETFOCUS 7
WM_NCPAINT 133
WM_ERASEBKGND 20
WM_WINDOWPOSCHANGED 71
WM_NCCALCSIZE 131
WM_NCPAINT 133
WM_ERASEBKGND 20
WM_SIZE 5
WM_MOVE 3
WM_GETICON 127
WM_GETICON 127
WM_GETICON 127
WM_PAINT 15
WM_NCHITTEST 132
WM_ERASEBKGND 32
WM_NCMOUSEMOVE 160
WM_NCHITTEST 132
|
there follows here a whole series, one after another, of trios of the messages, WM_ERASEBKGND, WM_NCMOUSEMOVE, WM_NCHITTEST in response to movements of the mouse outside the client area of the window.
|
WM_NCHITTEST 132
WM_ERASEBKGND 32
|
The close box in the top right corner of the window was clicked here
WM_NCLBUTTONDOWN 161
WM_CAPTURECHANGED 533
WM_SYSCOMMAND 274
WM_CLOSE 16
WM_WINDOWPOSCHANGING 70
WM_WINDOWPOSCHANGED 71
WM_NCACTIVATE 134
WM_ACTIVATE 6
WM_ACTIVATEAPP 28
WM_KILLFOCUS 8
WM_DESTROY 2
WM_NCDESTROY 130
I suppose that, if you are new to Windows programming, you might be aghast at the prospect of having to deal with all these messages in order to merely put a window on the screen. In fact, you needn't worry. Any Windows message the program code doesn't want to respond to is simply sent back to Windows for the system to deal with, or discard.
There are only five of the above messages that might normally be useful to a program - WM_PAINT, WM_CREATE, WM_ERASEBKGND, WM_CLOSE, and WM_DESTROY. All the others will usually simply be returned to windows. A program code does not even have to identify them, since it makes a list of messages it wants to intercept, and sends back any message not on the list, without identifying it. The above list, however, is useful to give the reader an insight into the level of messaging activity that is going on between a program and the operating system.
The list, however, does provide numerous opportunities for a program's code to intercept, and add its own response to, any of the above messages, if a programmer finds a need to do so.
It is worth noting, in the above list, that some messages have the form WM_NC… All such messages always have to do with the 'non_client' area of a window. The 'client' area of a window is the area where the normal program activity occurs, and where its data, like text or images, is displayed. The non-client area consists of the window frame and title bar. The non-client area is managed by Windows, but Windows nevertheless sends non-client messages to the program, allowing the program to intercept and abort them or modify their results. A programmer, however, should already have had some experience with Windows programming before attempting to interfere with the non-client area of a window.
There are, in addition, at least one or two useful pieces of information that can be extracted from above message list. Note, for example, how early in the series of messages the window creation message, WM_CREATE, is sent to the window being opened. It is sent before the message, WM_SHOWWINDOW, which indicates that the window is being prepared to be shown on the screen, and long before the first WM_PAINT message is sent to the window, which is to tell the program to paint the window client area. This means you can intercept the WM_CREATE message and use this opportunity to initialise values of variables etc. in your program, if this is desirable, before the window appears on the screen.
The first WM_PAINT message is sent just after the window has been displayed on the screen, so you can intercept this and use it to initialise painting of the client area of your program if that is what you need to do. You can also use the initial WM_PAINT message response to send a WM_USER message to your own program, which can be used to initialise variables, initially create fonts and bitmaps, or whatever, after the window has been displayed on the screen, but before any messages from the user have been sent from the keyboard or mouse. This will be discussed further in a later chapter.
THE MOST IMPORTANT WINDOWS MESSAGES FOR A PROGRAMMER:
It is not necessary to enter into a further discussion of the above list, which, as I said, I provide for interest and to give the reader a feel for the level of messaging activity going on between the system and a program window open on the screen. Instead, I will introduce the Windows messages that are normally sent by user activity in the client area of the window from the mouse or keyboard, or from popup menus.
WM_MOUSEMOVE
WM_LBUTTONDOWN
WM_LBUTTONUP
WM_LBUTTONDBLCLK
WM_RBUTTONDOWN
WM_RBUTTONUP
WM_RBUTTONDBLCLK
These are the messages sent by the mouse from the client area of the screen. They are for a two button mouse. A modern, three button mouse would also have messages like WM_MBUTTONDOWN (middle button down), but you can easily extrapolate the use of these from the two button messages. The message names are really self-explanatory, and the program code in response to them depends on what you want the response of your program to be to any particular mouse message. If a WM_MOUSEMOVE message, for example, were to be sent, in the context of a word processor program, you could use it to highlight the text over which the mouse is moving, i.e., as long as the user is holding down the mouse left button.
Depending on what you want your program to do, it may not be necessary to intercept all of the mouse messages, in which case you need to intercept only those messages you need to respond to.
Windows messages also contain associated parameters in addition to the message number itself, which can give useful additional information, which I describe in the next section on the anatomy of a Windows message.
The WM_MOUSEMOVE message, has for example, a parameter that shows whether the mouse left button is in the up or down position.
WM_KEYDOWN
WM_CHAR
These two messages are used to intercept keyboard input. The first is sent by non-character keys, like arrow keys, etc., while the second is sent by character keys, like 'a', 'b', etc. There are other messages associated with keyboard input, like alt+(some key), which activate menus and menu items.
WM_ERASEBKGND
WM_CREATE
WM_PAINT
WM_CLOSE
WM_DESTROY
These are the most important and useful general window messages for the programmer to be able to intercept. The first isconnected with the repainting of the window if another window has been moved across it. The second inaugurates the initial creation of a window. The third is sent when the window is ready for general painting of a the client area, and the final two are sent at the closing and 'destruction' of a window, when the user exits the program.
WM_COMMAND
This is the message sent to a window from menu items and dialogue boxes, and its precise nature of the is further identified by extra parameters, as will be explained further on.
WM_HSCROLL
WM_VSCROLL
These are the messages sent from horizontal and vertical scrollbars. The first is for a horizontal, and the second for a vertical scrollbar.
WM_USER
This is a custom message a programmer can send to the program from within his code. The programmer can specify the extra message parameters, and thus use the message to help organise code activation.
The actual use of these messages will be described in their proper context further on.
THE 'ANATOMY' OF A WINDOWS MESSAGE:
It has been indicated already that a windows message has extra parameters associated with it, containing extra, useful information. The WM_COMMAND message, for example, will have additional parameters to identify which item on a menu or which dialog box sent the message. The WM_MOUSEMOVE message extra parameters will indicate the current position of the mouse cursor and will also contain mouse button information.
A Windows message thus has what might be called an anatomy, which has a standard form, with standard names for its parts These involve the message number itself, contained in a dword parameter, MESSAGE, with two extra dword sized parameters associated with it, as follows:
MESSAGE, wparam, lparam
When a message is sent to a program's message queue, or sent back to the second entry point, it is always sent in the form of the above three parameters, which together constitute a complete Windows message.
The parameters themselves are also given an anatomy, in that they each can be split up into two word sized sub-parameters. These are distinguished
from one another by the standard names wparam_hiword and wparam_loword, and lparam_hiword and lparam_loword. This means that sometimes wparam or lparam can have two distinct word sized parameters in the hiword and loword of the overall dword. However, this is not always the case, and the parameters can also be given single dword values, depending on the particular message. Thus, to take account of all these alternatives, the full anatomy of a Windows message has the form:
MESSAGE
WPARAM
WPARAM_HIWORD
WPARAM_LOWORD
LPARAM
LPARAM_HIWORD
LPARAM_LOWORD
Since the hiwords and lowords are extracted by a program's code, the initial anatomy of a message, as sent to the program by Windows, as mentioned above, has the simpler form:
MESSAGE
WPARAM
LPARAM
WINDOWS API FUNCTIONS OVERVIEW:
PROGRAM AND OPERATING SYSTEM ENTRY POINTS, OR FUNCTIONS:
The interaction of a program's code with the Windows operating system is established by two methods: the Windows messaging system, as described above, and Windows API function calls. Windows API functions will be dealt with in this section.
We have already seen that, while the Windows operating system communicates with a program via a messaging system, sent to only two program entry points, a program, on the other hand, communicates or interfaces with the operating system via multiple operating system entry points, and these are referred to collectively, in their entirety as the Windows API, or Application Programming Interface.
A programmer has no idea of the internal code of the Windows operating system, and is not permitted access to it by Microsoft. However, as we have seen in chapter 1, segments of program code can be encapsulated in the form of procedures, also called functions, or subroutines, and given a name which allows them to be 'called' via a call instruction. Thus, you can write code to call a procedure by name without actually knowing what the code is inside the procedure, and this is the basis on which a program is enabled to interact with the operating system code.
A procedure name is an entry point to the procedure code and thus the multiple entry points provided by
the system consist of a list of procedure names that can be called by a program's code. Likewise, the two entry points a program provides to the operating system are also entry points to procedure codes, that can be called by Windows.
This means that the Windows operating system documentation can let you know one of its internal procedure names, and what the result of the procedure will be if you call it, even though you are not allowed to know the code inside the procedure. There is an entire documented list of Windows system code procedure names, and what they do, and these are referred to, individually, as Windows API Functions.
An important question in using procedures, when you don't know their internal code, is: how do you send, or pass, input values to the procedure, and get results back from it, if necessary? The procedure code called AddLengths, as illustrated in chapter 1, uses the values in the memory addresses LengthA and LengthB, and gets a result in eax. Such memory address names are assigned by to the program memory, but a programmer has no way of knowing how such memory addresses are assigned within procedures belonging to the system code itself. Hence the problem of assigning input values to a Windows API function or, as it is called, 'passing parameters' to the API function.
PASSING VALUES, OR PARAMETERS, TO A WINDOWS FUNCTION:
We have already become acquainted with the stack, an important section of RAM, which has the advantage of being accessible to both the program code and the operating system code, because it is not accessed by the normal method of specifying memory addresses, but via its own special registers, the stack pointer, esp, and base pointer, ebp
As we have seen, the stack is accessed by the use of the special code instructions 'push' and 'pop', which can be used by either the program code, or the operating system code. The stack thus provides a very easy way to send input values or, as it is usually described, 'pass parameters', to a Windows API function, or from Windows to a program function.
This is the method specified by Windows for programmers to use. A program's code will push a series of values onto the stack, using the push instruction, before calling an API function, and the operating system will then retrieve them from the stack again for use in the internal code of the function or procedure. The documentation associated with the Windows API functions lists the parameters to be passed to any particular function and describes what
they are for and this enables the programmer to understand what the values should be.
An API function, however, does not return a value to the program by using the stack, but always returns the value in register eax. This creates a problem if the API function has to return more than one value, since eax can return only one value at a time. This problem is solved by passing a memory block address to the API function as one of its parameters, in which case the API function will place as many return values as necessary in the memory block. This arrangement will, of course, be described in detail in the documentation for the particular API function.
A very important consideration to be aware of, from the point of view of your own code, is the effect that calling an API function has on the values of the CPU registers, as follows: for some reason, the values of registers ebx,esi, and edi are not changed by a call to an API function, and remain the same before and after the call, but the value of any of the other registers cannot be assumed to remain unchanged.
WINDOWS HANDLES:
Since hardware, such as the video monitor, or printer, RAM, etc., is always in the control of the operating system, a program has to negotiate with such hardware only via the Windows API functions.
Any particular item, communicated to the hardware, such as a window on the video screen, or a bitmap, or a font, is described by a particular set of parameters, which are stored by the operating system, whether such parameters are created by the system, or passed to it by the program, or are a mixture of both.
In order that the object, described by such a list of parameters, can be referred to again by a program, or the operating system, as often as desired, and operated on by calls to API functions, it is given an identification number by Windows. This identification number is associated with the particular list of parameters, for the particular object, and is referred to as a 'handle', and thus becomes 'the handle' of the particular object. Thereafter the object, and its list of parameters, can be identified by this identification number. Thus, a window drawn on the screen has its handle, a bitmap also has its handle, a font, has its
own handle, and an opened file also has its own handle.
Windows gives such an identification number as the return value from a call to an API function that sets up the object and its list of parameters. A program must store this number in memory in order to refer to the object again as required.
It is not necessary for a program to have direct access to the list of parameters that a handle represents, as they are for direct internal use by the system, and the program thus refers to the list only by its identification number. Thus, an API function called to create a bitmap returns a handle to the bitmap, which the program can store in a suitably named memory location. When the bitmap, or other object, is no longer needed, the program can call an API function to tell the system to destroy the object and discard the set of parameters that defines it, which frees the memory resources that were used to store the parameters, after which the handle is no longer valid.
HOW TO OBTAIN HANDLES:
The handle of an object is returned in register eax, which is the usual way Windows API functions return values after they are called. Thus, you might get and save a bitmap handle, for example, or a file handle, as follows:
api CreateBitmap,(bitmap parameters here)
mov [BITMAP.Handle],eax
Or
api CreateFile, (file creation parameters here)
mov [FILE.Handle],eax
You will similarly get and save handles when you create fonts, dynamically ask the system to assign a block of memory, create coloured brushes to paint on the screen, or whatever.
HOW TO DESTROY HANDLES:
Since a handle refers to a set of parameters that describe one or another kind of object, these parameters are stored by the operating system, and thus take up space within the operating system memory. It clearly would not do if such memory allocations became cumulative, and progressively consumed more and more system memory, with every application, or program, that was opened, and remained so, even after each was closed. The system therefore provides a means of destroying or deleting Windows handles when they are no longer needed, thus freeing up system memory resources.
However, instead of having only one API function to destroy all handles, there are several different functions to destroy handles of different kinds of objects, as follows:
api CloseHandle
destroys the handle of an open file
api DestroyWindow
destroys a window, and its handle 
api DeleteObject
destroys a graphics object handle, like a bitmap, font, palette, etc.
api DeleteDC and api ReleaseDC
both destroy device context handles.
The actual use of each of these API functions will be described in the relevant context, but this overview illustrates the fact that, despite the different function names, they all achieve essentially the same kind of result.
Part I: Part I Introduction
Chapter 1: Binary numbers, code, and procedures
Chapter 3: Assembly Language
Chapter 4: Assembly Language Code example
Chapter 5: Macros and HLA
Chapter 6: HLA code example
Chapter 7: The Windows operating system
Chapter 8: Data Structures
Chapter 9: How to Create a Windows Program
Chapter 10: How to Create an Exe File
Chapter 11: Structured Programming and OOP
Part II: Part II Introduction
Chapter 12: Debugging a Windows Program Code
Chapter 13: Painting the Window Client Area
Chapter 14: Creating Window Menus
Chapter 15: How to Create Toolbars
Chapter 16: How to Create Popup Menus
Chapter 17: About the Windows Clipboard
Chapter 18: How to Create Bitmaps
Chapter 19: Icons and the Ico Format
Chapter 20: Common Dialog Boxes
Chapter 21: Working with Files
Chapter 22: Scrollbars and Scrolling
Chapter 23: How to Send Data to the Printer
Chapter 24: Miscellaneous Topics
© Alen, August 2013
alen@alenspage.net
Material on this page may be reproduced
for personal use only.