Introduction to PM Programming - Mar 1994: Difference between revisions
mNo edit summary |
m Removed extraneous paragraph tags which were displayed literally; minor typo. ~~~~ |
||
Line 5: | Line 5: | ||
<h3>Introduction</h3> | <h3>Introduction</h3> | ||
The purpose of this column is to provide the readers out there who are not | |||
familiar with PM application development the information necessary to | familiar with PM application development the information necessary to | ||
satisfy their | satisfy their curiosity, educate themselves, and give them an advantage | ||
over the documentation supplied by IBM. Of course, much of this stuff | over the documentation supplied by IBM. Of course, much of this stuff | ||
could probably be found in one of the many books out there, but the problem | could probably be found in one of the many books out there, but the problem | ||
Line 13: | Line 13: | ||
after you read the book the first time through. | after you read the book the first time through. | ||
I will gladly entertain feedback from the readers about what was "glossed | |||
over" or what was detailed well, what tangential topics need to be covered | over" or what was detailed well, what tangential topics need to be covered | ||
and what superfluous crap should have been removed. This feedback is | and what superfluous crap should have been removed. This feedback is | ||
essential in guaranteeing that you get what you pay for. :) | essential in guaranteeing that you get what you pay for. :) | ||
It should be said that you must not depend solely on this column to teach | |||
you how to develop PM applications; instead, this should be viewed as a | you how to develop PM applications; instead, this should be viewed as a | ||
supplement to your other information storehouses (books, the network | supplement to your other information storehouses (books, the network | ||
Line 28: | Line 28: | ||
<h3>Last Month</h3> | <h3>Last Month</h3> | ||
Last month, we finished dissecting the (initial) HELLO program that was | |||
introduced in volume 2, issue 1. This month we will starts to look at a | introduced in volume 2, issue 1. This month we will starts to look at a | ||
significantly changed version of HELLO in order to set the direction of | significantly changed version of HELLO in order to set the direction of | ||
Line 35: | Line 35: | ||
useful. Other than that, it didn't do anything useful. :) | useful. Other than that, it didn't do anything useful. :) | ||
Up to this point, we have introduced and continued discussion on two areas | |||
of PM application development - messages and functions. Now we are going | of PM application development - messages and functions. Now we are going | ||
to add two more - dialog box implementation and resource files. | to add two more - dialog box implementation and resource files. | ||
Line 41: | Line 41: | ||
<h3>Dialog Boxes</h3> | <h3>Dialog Boxes</h3> | ||
In most programs, it is necessary to gather (even frequently) data from the | |||
user. This may be as simple as getting a filename, or it may be as complex | user. This may be as simple as getting a filename, or it may be as complex | ||
as (gulp) filling out an online tax form. In any case, what is the method | as (gulp) filling out an online tax form. In any case, what is the method | ||
Line 50: | Line 50: | ||
discussed when this column began. | discussed when this column began. | ||
Every one has seen a dialog box or two; whether it is when your word | |||
processor prompts you for a file name to load, or when your spreadsheet | processor prompts you for a file name to load, or when your spreadsheet | ||
program asks you to select a printer, you cannot escape these facts of | program asks you to select a printer, you cannot escape these facts of | ||
Line 56: | Line 56: | ||
another. | another. | ||
There are two components to dialog box implementation - screen layout and | |||
code. We will begin to look at each in this issue, and will continue in | code. We will begin to look at each in this issue, and will continue in | ||
more detail in future issues as we also look at the various controls. | more detail in future issues as we also look at the various controls. | ||
Line 62: | Line 62: | ||
<h3>Multilingual</h3> | <h3>Multilingual</h3> | ||
Okay, so you are a Pascal hacker from DOS trying to learn C under OS/2. To | |||
make it worse, you have to also learn PM, according to your boss. But if | make it worse, you have to also learn PM, according to your boss. But if | ||
that weren't enough, now you can tack on another language to learn, another | that weren't enough, now you can tack on another language to learn, another | ||
Line 68: | Line 68: | ||
language in which dialog boxes (among other things) are designed. | language in which dialog boxes (among other things) are designed. | ||
Simply put, a dialog box is a collection of child windows. Each window is | |||
defined separately, with a specific order. At the next level, there are | defined separately, with a specific order. At the next level, there are | ||
groups of windows, beginning with the first one having a special style - | groups of windows, beginning with the first one having a special style - | ||
Line 76: | Line 76: | ||
keyword. | keyword. | ||
A sample dialog definition follows: | |||
<pre><small> | <pre><small> | ||
Line 113: | Line 113: | ||
</small></pre> | </small></pre> | ||
As you can see, there are many more details regarding these definitions; | |||
fortunately, you don't have to know them. There is a utility called | fortunately, you don't have to know them. There is a utility called | ||
DLGEDIT which allows you to design, on the screen, your dialog boxes and | DLGEDIT which allows you to design, on the screen, your dialog boxes and | ||
Line 124: | Line 124: | ||
<h3>Resource Files</h3> | <h3>Resource Files</h3> | ||
A resource file - with the extension .RC - contains the definition of the | |||
various resources used by the application and each of these resources can | various resources used by the application and each of these resources can | ||
be loaded or accessed via a Win*() function specific to that resource type. | be loaded or accessed via a Win*() function specific to that resource type. | ||
Line 131: | Line 131: | ||
constants that are needed by both the resource file and the application. | constants that are needed by both the resource file and the application. | ||
For dialogs, Microsoft decided that the Dialog Box Editor shouldn't have to | |||
deal with parsing the entire resource file, so it added dialog definition | deal with parsing the entire resource file, so it added dialog definition | ||
files (.DLG) to the fold. Integrating the two can get unwieldy - at the | files (.DLG) to the fold. Integrating the two can get unwieldy - at the | ||
Line 138: | Line 138: | ||
<pre><small>RCINCLUDE MYDLGS.DLG</small></pre> | <pre><small>RCINCLUDE MYDLGS.DLG</small></pre> | ||
...but at the beginning of the dialog file, you must somehow also include | |||
the #define statements for each dialog, so there is a different statement: | the #define statements for each dialog, so there is a different statement: | ||
<pre><small>DLGINCLUDE 1 MYDLGS.H</small></pre> | <pre><small>DLGINCLUDE 1 MYDLGS.H</small></pre> | ||
Whoa! Why the number on the DLGINCLUDE statement but not the RCINCLUDE | |||
statement? The answer is that Microsoft thought that different dialogs | statement? The answer is that Microsoft thought that different dialogs | ||
would have different sets of constants, so the number is the identifier of | would have different sets of constants, so the number is the identifier of | ||
Line 149: | Line 149: | ||
different dialog box definitions). | different dialog box definitions). | ||
If the reasoning seems flawed to you, that is because it is. My personal | |||
taste is to append the .RC file with the contents of the .DLG file. | taste is to append the .RC file with the contents of the .DLG file. | ||
Preference is the key word here. Since the dialog editor reads the binary | Preference is the key word here. Since the dialog editor reads the binary | ||
Line 156: | Line 156: | ||
<h3>Dialog Code</h3> | <h3>Dialog Code</h3> | ||
In addition to a dialog screen definition, there is code to be written. | |||
Since a dialog is much like a "main window", you can imagine that the code | Since a dialog is much like a "main window", you can imagine that the code | ||
is some form of a window procedure and this is correct. It is called a | is some form of a window procedure and this is correct. It is called a | ||
Line 174: | Line 174: | ||
<h4>WM_INITDLG </h4> | <h4>WM_INITDLG </h4> | ||
This message occurs when a dialog box is being created. | |||
<pre><small> | <pre><small> | ||
Line 201: | Line 201: | ||
later issues. | later issues. | ||
Dialog boxes come in two flavors, and the type determines the function used | |||
to display the dialog box. | to display the dialog box. | ||
Modal dialog boxes are those that require interaction by the user before | |||
the application or system can continue. An "Open file" dialog is an | the application or system can continue. An "Open file" dialog is an | ||
example of this. | example of this. | ||
Modeless dialog boxes are those that do not require input for the | |||
application to continue. A toolpad is an example of this. | application to continue. A toolpad is an example of this. | ||
For the former, WinDlgBox() is used to display and process the dialog. The | |||
latter uses WinLoadDlg(). Both functions take the same parameters. | latter uses WinLoadDlg(). Both functions take the same parameters. | ||
Line 262: | Line 262: | ||
<h3>Dismissal versus Destruction</h3> | <h3>Dismissal versus Destruction</h3> | ||
When a dialog is dismissed, it is by default not destroyed until the | |||
application exits. This is for performance reasons; since a large | application exits. This is for performance reasons; since a large | ||
percentage of dialogs are reused by an application many times, this reduces | percentage of dialogs are reused by an application many times, this reduces | ||
Line 268: | Line 268: | ||
actually displayed. | actually displayed. | ||
The ramifications are that if you allocate resources in the dialog | |||
procedure, you cannot wait until the WM_DESTROY message to free them, or | procedure, you cannot wait until the WM_DESTROY message to free them, or | ||
else you are asking for trouble. When do you do it? I have yet to find a | else you are asking for trouble. When do you do it? I have yet to find a | ||
Line 275: | Line 275: | ||
<h3>Summary</h3> | <h3>Summary</h3> | ||
This month, we began to look at dialog boxes and resource files. These are | |||
collectively large topics, so we will continue next month with these. In | collectively large topics, so we will continue next month with these. In | ||
the meantime, a sample application has been provided as hello.zip; this is | the meantime, a sample application has been provided as hello.zip; this is | ||
Line 281: | Line 281: | ||
in previous issues. | in previous issues. | ||
Further down the road, we will begin looking at each of the individual | |||
controls, what their purpose is, and how they are used (primarily from the | controls, what their purpose is, and how they are used (primarily from the | ||
context of a dialog box). Stay tuned! | context of a dialog box). Stay tuned! | ||
[[Category: PM Articles]] | [[Category: PM Articles]] |
Revision as of 07:12, 8 February 2016
Introduction to PM Programming
Written by Larry Salomon Jr.
Introduction
The purpose of this column is to provide the readers out there who are not familiar with PM application development the information necessary to satisfy their curiosity, educate themselves, and give them an advantage over the documentation supplied by IBM. Of course, much of this stuff could probably be found in one of the many books out there, but the problem with books in general is that they don't answer the questions you have after you read the book the first time through.
I will gladly entertain feedback from the readers about what was "glossed over" or what was detailed well, what tangential topics need to be covered and what superfluous crap should have been removed. This feedback is essential in guaranteeing that you get what you pay for. :)
It should be said that you must not depend solely on this column to teach you how to develop PM applications; instead, this should be viewed as a supplement to your other information storehouses (books, the network conferences, etc.). Because this column must take a general approach, there will be some topics that you would like to see discussed that really do not belong here. Specific questions can be directed to the Scratch Patch, where an attempt to answer them will be made.
Last Month
Last month, we finished dissecting the (initial) HELLO program that was introduced in volume 2, issue 1. This month we will starts to look at a significantly changed version of HELLO in order to set the direction of this column for the next few issues. To recap, though, HELLO's purpose was simply to demonstrate the minimum number of calls required to do anything useful. Other than that, it didn't do anything useful. :)
Up to this point, we have introduced and continued discussion on two areas of PM application development - messages and functions. Now we are going to add two more - dialog box implementation and resource files.
Dialog Boxes
In most programs, it is necessary to gather (even frequently) data from the user. This may be as simple as getting a filename, or it may be as complex as (gulp) filling out an online tax form. In any case, what is the method by which input is obtained? CUA defines the mechanism to be a dialog box. What is a dialog box, you ask? To be precise, it is a window whose sole purpose is to receive data from the user in order for the application to continue. Because it is a window, it has the window characteristics discussed when this column began.
Every one has seen a dialog box or two; whether it is when your word processor prompts you for a file name to load, or when your spreadsheet program asks you to select a printer, you cannot escape these facts of (GUI) life. However, using them is one thing - implementing them is quite another.
There are two components to dialog box implementation - screen layout and code. We will begin to look at each in this issue, and will continue in more detail in future issues as we also look at the various controls.
Multilingual
Okay, so you are a Pascal hacker from DOS trying to learn C under OS/2. To make it worse, you have to also learn PM, according to your boss. But if that weren't enough, now you can tack on another language to learn, another skill to master. It is called the resource language, and it is the language in which dialog boxes (among other things) are designed.
Simply put, a dialog box is a collection of child windows. Each window is defined separately, with a specific order. At the next level, there are groups of windows, beginning with the first one having a special style - WS_GROUP - and ending just prior to the beginning of the next group or with the end of the dialog box definition. Finally, a dialog definition begins with a DIALOG keyword, followed by a BEGIN keyword, and ends with an END keyword.
A sample dialog definition follows:
<small> DLGTEMPLATE DLG_GRAPHTYPE LOADONCALL MOVEABLE DISCARDABLE BEGIN DIALOG "Create graph", DLG_GRAPHTYPE, 64, 23, 195, 170, NOT FS_DLGBORDER | WS_VISIBLE, FCF_SYSMENU | FCF_TITLEBAR | FCF_SIZEBORDER BEGIN GROUPBOX "Graph type", -1, 10, 105, 170, 60 LTEXT "Field(s) to graph", -1, 10, 90, 100, 8 CONTROL "", DGT_UB_BARGRAPH, 15, 110, 50, 45, WC_BUTTON, BS_USERBUTTON | WS_GROUP | WS_TABSTOP | WS_VISIBLE CONTROL "", DGT_UB_LINEGRAPH, 70, 110, 50, 45, WC_BUTTON, BS_USERBUTTON | WS_GROUP | WS_TABSTOP | WS_VISIBLE CONTROL "", DGT_UB_SCATTERGRAPH, 125, 111, 50, 45, WC_BUTTON, BS_USERBUTTON | WS_GROUP | WS_TABSTOP | WS_VISIBLE LISTBOX DGT_LB_HEADERLIST, 10, 30, 175, 60, LS_HORZSCROLL | LS_EXTENDEDSEL | WS_GROUP LISTBOX DGT_LB_FULLIST, 10, 30, 175, 60, LS_HORZSCROLL | LS_EXTENDEDSEL | WS_GROUP | NOT WS_VISIBLE DEFPUSHBUTTON "~Graph", DGT_PB_GRAPH, 10, 10, 40, 13, WS_GROUP PUSHBUTTON "~Settings...", DGT_PB_SETTINGS, 55, 10, 40, 13 PUSHBUTTON "Cancel", DLG_PB_CANCEL, 100, 10, 40, 13 PUSHBUTTON "Help", DLG_PB_HELP, 145, 10, 40, 13 END END </small>
As you can see, there are many more details regarding these definitions; fortunately, you don't have to know them. There is a utility called DLGEDIT which allows you to design, on the screen, your dialog boxes and save the result. We won't describe how to use this utility; see the accompanying documentation for this. What is the result? The human-readable source is saved with the extension .DLG and the binary form is saved with the extension .RES. In order to explain more, we need to broaden the scope of our discussion to...
Resource Files
A resource file - with the extension .RC - contains the definition of the various resources used by the application and each of these resources can be loaded or accessed via a Win*() function specific to that resource type. The resource language also includes C-style preprocessor commands to allow the inclusion of C header files containing #define statements for various constants that are needed by both the resource file and the application.
For dialogs, Microsoft decided that the Dialog Box Editor shouldn't have to deal with parsing the entire resource file, so it added dialog definition files (.DLG) to the fold. Integrating the two can get unwieldy - at the end of the .RC file, you indicate the dialog file to include:
<small>RCINCLUDE MYDLGS.DLG</small>
...but at the beginning of the dialog file, you must somehow also include the #define statements for each dialog, so there is a different statement:
<small>DLGINCLUDE 1 MYDLGS.H</small>
Whoa! Why the number on the DLGINCLUDE statement but not the RCINCLUDE statement? The answer is that Microsoft thought that different dialogs would have different sets of constants, so the number is the identifier of the dialog (meaning you can have different #include files refer to different dialog box definitions).
If the reasoning seems flawed to you, that is because it is. My personal taste is to append the .RC file with the contents of the .DLG file. Preference is the key word here. Since the dialog editor reads the binary file (.RES), it doesn't matter how we manipulate the human-readable source.
Dialog Code
In addition to a dialog screen definition, there is code to be written. Since a dialog is much like a "main window", you can imagine that the code is some form of a window procedure and this is correct. It is called a dialog procedure and differs from a window procedure in the following ways:
- The dialog procedure never receives a WM_CREATE message. Instead, it gets a WM_INITDLG message.
- The default dialog procedure is not WinDefWindowProc(); it is instead WinDefDlgProc() and takes the same parameters.
- A dialog is not explicitly destroyed by the application (usually). Instead, it is dismissed via the WinDismissDlg() function.
WM_INITDLG
This message occurs when a dialog box is being created.
<small> Parameters param1 hwndFocus (HWND) The handle of the window to receive the input focus when initialization is completed. param2 pvData (PVOID) Points to the application data specified as the last parameter on the call to WinDlgBox() or WinLoadDlg(). Returns reply bFocusChanged (BOOL) Focus change indicator: FALSE Give the input focus to the window in param1 TRUE The input focus was assigned by the application to another window, so do not give the input focus to any window. </small>
We will examine in detail how dialog procedures are written and used in later issues.
Dialog boxes come in two flavors, and the type determines the function used to display the dialog box.
Modal dialog boxes are those that require interaction by the user before the application or system can continue. An "Open file" dialog is an example of this.
Modeless dialog boxes are those that do not require input for the application to continue. A toolpad is an example of this.
For the former, WinDlgBox() is used to display and process the dialog. The latter uses WinLoadDlg(). Both functions take the same parameters.
<small> ULONG WinDlgBox(HWND hwndParent, HWND hwndOwner, PFNWP pfnDlgProc, HMODULE hmModule, ULONG ulDlgId, PVOID pvData); </small>
hwndParent | The parent window of the dialog box |
hwndOwner | The desired owner window of the dialog. This is rarely the true owner of the dialog (see below). For calls to WinDlgBox(), the true owner is disabled until the dialog is dismissed. |
pfnDlgProc | Specifies the dialog procedure |
hmModule | Handle to the DLL where the dialog definition resides |
ulDlgId | ID of the dialog to be displayed |
pvData | Application data, passed to the dialog procedure via the WM_INITDLG message |
The true owner of a dialog is calculated by the system in the following manner - each successive parent window of hwndOwner is queried until one is found whose immediate parent is hwndParent. If found, this becomes the true owner, otherwise hwndOwner becomes the true owner.
Dismissal versus Destruction
When a dialog is dismissed, it is by default not destroyed until the application exits. This is for performance reasons; since a large percentage of dialogs are reused by an application many times, this reduces the time between the call to WinDlgBox() and the time the dialog is actually displayed.
The ramifications are that if you allocate resources in the dialog procedure, you cannot wait until the WM_DESTROY message to free them, or else you are asking for trouble. When do you do it? I have yet to find a good answer to that question...
Summary
This month, we began to look at dialog boxes and resource files. These are collectively large topics, so we will continue next month with these. In the meantime, a sample application has been provided as hello.zip; this is an enhancement of the previous Hello world application that was discussed in previous issues.
Further down the road, we will begin looking at each of the individual controls, what their purpose is, and how they are used (primarily from the context of a dialog box). Stay tuned!