Jump to content

Introduction to PM Programming - Apr 1994: Difference between revisions

From EDM2
mNo edit summary
Lewisr (talk | contribs)
m Removed extraneous paragraph tags which were displayed literally; needs more formatting work. ~~~~
Line 3: Line 3:
<h2>Introduction</h2>
<h2>Introduction</h2>


<p>The purpose of this column is to provide the readers out there who are not
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 curiousity, educate themselves, and give them an advantage
satisfy their curiousity, educate themselves, and give them an advantage
Line 11: Line 11:
after you read the book the first time through.
after you read the book the first time through.


<p>I will gladly entertain feedback from the readers about what was "glossed
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.  :)


<p>It should be said that you must not depend solely on this column to teach
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 24: Line 24:
Patch, where an attempt to answer them will be made.
Patch, where an attempt to answer them will be made.


<p>
 
<h2>Last Month</h2>
<h2>Last Month</h2>


<p>Last month, we began looking at dialog boxes and their components.  This
Last month, we began looking at dialog boxes and their components.  This
month, we'll continue by delving into the source code to HELLO which was
month, we'll continue by delving into the source code to HELLO which was
presented last month.  We'll examine the messages in our dialog procedure,
presented last month.  We'll examine the messages in our dialog procedure,
and will begin looking at how controls are used within dialogs.
and will begin looking at how controls are used within dialogs.


<p>
 
<h3>nameDlgProc()</h3>
<h3>nameDlgProc()</h3>


<p>Below is the dialog procedure from HELLO.C condensed a bit:
Below is the dialog procedure from HELLO.C condensed a bit:
<pre>
<pre>
MRESULT EXPENTRY nameDlgProc(HWND hwndWnd,
MRESULT EXPENTRY nameDlgProc(HWND hwndWnd,
Line 63: Line 63:
other two.
other two.


<p><h4>WM_COMMAND</h4>
<h4>WM_COMMAND</h4>


This message occurs when a command is to be performed, or when a key
This message occurs when a command is to be performed, or when a key
combination is translated to a WM_COMMAND accelerator message.
combination is translated to a WM_COMMAND accelerator message.


<p><h4>Parameters</h4>
<h4>Parameters</h4>
<blockquote>
<blockquote>
<b>param1</b>
<b>param1</b>
Line 87: Line 87:
Pointer indicator
Pointer indicator


<p><b>TRUE</b>  The message is the result of a pointer action.<br>
<b>TRUE</b>  The message is the result of a pointer action.<br>
<b>FALSE</b>  The message is the result of a keyboard action.
<b>FALSE</b>  The message is the result of a keyboard action.


</blockquote></blockquote></blockquote>
</blockquote></blockquote></blockquote>


<p><h4>Returns</h4>
<h4>Returns</h4>
<blockquote>
<blockquote>
<b>reply</b>
<b>reply</b>
Line 101: Line 101:
</blockquote></blockquote></blockquote>
</blockquote></blockquote></blockquote>


<p><h4>WM_CONTROL</h4>
<h4>WM_CONTROL</h4>


This message occurs when a control has a significant event to report to its
This message occurs when a control has a significant event to report to its
Line 107: Line 107:




<p><h4>Parameters</h4>
<h4>Parameters</h4>
<blockquote>
<blockquote>
<b>param1</b>
<b>param1</b>
Line 121: Line 121:
</blockquote></blockquote>
</blockquote></blockquote>


<p>
 
<b>param2</b>
<b>param2</b>


Line 130: Line 130:
</blockquote></blockquote></blockquote>
</blockquote></blockquote></blockquote>


<p>
 
<h4>Returns</h4>
<h4>Returns</h4>
<blockquote>
<blockquote>
Line 140: Line 140:
</blockquote></blockquote></blockquote>
</blockquote></blockquote></blockquote>


<p>
 
Okay, "big deal," you say.  Just add two more entries to your list of
Okay, "big deal," you say.  Just add two more entries to your list of
messages that you now know about?  Well, these messages are a bit more
messages that you now know about?  Well, these messages are a bit more
important than that...
important than that...


<p>
 
<h4>The WM_COMMAND Message</h4>
<h4>The WM_COMMAND Message</h4>


Line 152: Line 152:
Among other things...
Among other things...


<p><ul>
<ul>
<li>menu items send this message when they are selected
<li>menu items send this message when they are selected
<li>pushbuttons send this message when they are selected
<li>pushbuttons send this message when they are selected
Line 160: Line 160:
</ul>
</ul>


<p>It doesn't look like much, but as you travel the PM developer's journey,
It doesn't look like much, but as you travel the PM developer's journey,
you'll find that this message is frequently sent.  It becomes your central
you'll find that this message is frequently sent.  It becomes your central
interface to the user, since most actions are requested by the user through
interface to the user, since most actions are requested by the user through
menus on client windows and through pushbuttons on dialogs.
menus on client windows and through pushbuttons on dialogs.


<p>Let's take a look at how this message is treated in HELLO.C.
Let's take a look at how this message is treated in HELLO.C.


<pre>
<pre>
Line 184: Line 184:
feel ashamed if you don't understand the constants DID_OK and DID_CANCEL.
feel ashamed if you don't understand the constants DID_OK and DID_CANCEL.


<p><b>DID_OK</b>  Sent whenever the user presses Enter
<b>DID_OK</b>  Sent whenever the user presses Enter
<br><b>DID_CANCEL</b>  Sent whenever the user presses Escape
<br><b>DID_CANCEL</b>  Sent whenever the user presses Escape


<p>It is imperative that you understand that these messages are not sent by
It is imperative that you understand that these messages are not sent by
pushbuttons.  Thus, even though your dialog might not have pushbuttons, it
pushbuttons.  Thus, even though your dialog might not have pushbuttons, it
is possible to receive these messages.  (If you don't believe me, comment
is possible to receive these messages.  (If you don't believe me, comment
out the DEFPUSHBUTTON and PUSHBUTTON lines in HELLO.RC, recompile and try.)
out the DEFPUSHBUTTON and PUSHBUTTON lines in HELLO.RC, recompile and try.)


<p><h3>Dismissal Revisited</h3>
<h3>Dismissal Revisited</h3>


<p>When reading last month's column, I realized that I was talking about the
When reading last month's column, I realized that I was talking about the
dismissal of dialogs like we were all old pro's at it; if we were, I
dismissal of dialogs like we were all old pro's at it; if we were, I
thought, this column wouldn't have a reason for existance.
thought, this column wouldn't have a reason for existance.


<p>BOOL WinDismissDlg(HWND hwndDlg,ULONG ulResult);
BOOL WinDismissDlg(HWND hwndDlg,ULONG ulResult);


<p>This function is used to dismiss a dialog.  As was mentioned last time,
This function is used to dismiss a dialog.  As was mentioned last time,
this does not destroy the dialog by default; it only hides the dialog.
this does not destroy the dialog by default; it only hides the dialog.
What does this have to do with the WM_COMMAND message? Well, the typical
What does this have to do with the WM_COMMAND message? Well, the typical
Line 208: Line 208:




<p>In the above, no data is read from the dialog.  How does the program know
In the above, no data is read from the dialog.  How does the program know
what name to display?...
what name to display?...


<p>
 
<h2>The WM_CONTROL Message</h2>
<h2>The WM_CONTROL Message</h2>


<p>What happens whenever an item in a listbox is selected?  Or whenever the
What happens whenever an item in a listbox is selected?  Or whenever the
text in an entryfield changes?  Or when a checkbox is clicked on by the
text in an entryfield changes?  Or when a checkbox is clicked on by the
user? For all of these, and many other events, the owner of the control is
user? For all of these, and many other events, the owner of the control is
Line 220: Line 220:
an effect on the behavior of the application.
an effect on the behavior of the application.


<p>This is a broad message, which has a specific set of parameters based on
This is a broad message, which has a specific set of parameters based on
two criteria:
two criteria:


<p><ol>
<ol>
<li>the class of the control sending the message
<li>the class of the control sending the message
<li>the event that generate the message
<li>the event that generate the message
</ol><p>Thus, for the first scenario, the usNotify is LN_SELECT, and pvData is the
</ol>Thus, for the first scenario, the usNotify is LN_SELECT, and pvData is the
handle of the listbox.  For the second, usNotify is EN_CHANGE and pvData is
handle of the listbox.  For the second, usNotify is EN_CHANGE and pvData is
the handle of the entryfield.  And so on...
the handle of the entryfield.  And so on...
Line 268: Line 268:
the listbox, the name selected is placed in the entryfield.
the listbox, the name selected is placed in the entryfield.


<p><h3>.And the Point is...</h3>
<h3>.And the Point is...</h3>


<p>The point of introducing the WM_COMMAND and WM_CONTROL messages is to
The point of introducing the WM_COMMAND and WM_CONTROL messages is to
demonstrate the usefulness of them.  As we begin to look at the controls,
demonstrate the usefulness of them.  As we begin to look at the controls,
we will examine how they interact with the application through these
we will examine how they interact with the application through these
Line 276: Line 276:
execution of your application.
execution of your application.


<p>
 
<h2>New Functions</h2>
<h2>New Functions</h2>


<p>In addition to the WinDismissDlg() function, we will look at three
In addition to the WinDismissDlg() function, we will look at three
additional PM APIs.
additional PM APIs.
<pre><small>
<pre><small>
Line 291: Line 291:
value.  It returns a success flag.
value.  It returns a success flag.


<p><b>WinQueryWindowText</b> queries the text of the specified window and copies up
<b>WinQueryWindowText</b> queries the text of the specified window and copies up
to either the end of the text or lSzBuf characters into the buffer pointed
to either the end of the text or lSzBuf characters into the buffer pointed
to by pszBuffer.  It returns the number of characters copied.
to by pszBuffer.  It returns the number of characters copied.


<p><b>WinQueryWindowTextLength</b> returns the length of the text for the specified
<b>WinQueryWindowTextLength</b> returns the length of the text for the specified
window.
window.




<p>It is important to note that how the window text is actually used differs
It is important to note that how the window text is actually used differs
from control to control.  For example, the window text of an entryfield is
from control to control.  For example, the window text of an entryfield is
what is displayed in the entryfield itself.  This is also true for a
what is displayed in the entryfield itself.  This is also true for a
Line 308: Line 308:
text, if a titlebar exists.
text, if a titlebar exists.


<p>In other words, your mileage may vary.  :)
In other words, your mileage may vary.  :)
 


<p>
<h2>Summary</h2>
<h2>Summary</h2>


<p>This month we introduced two very important messages - WM_COMMAND and
This month we introduced two very important messages - WM_COMMAND and
WM_CONTROL - and described their purpose in a window or dialog procedure.
WM_CONTROL - and described their purpose in a window or dialog procedure.
We also looked at four new PM APIs and looked at window text for the first
We also looked at four new PM APIs and looked at window text for the first
time since they were mentioned in volume 2, issue 1.
time since they were mentioned in volume 2, issue 1.


<p>Next month, we will continue with HELLO by begining to examine the controls
Next month, we will continue with HELLO by begining to examine the controls
within it individually.
within it individually.


[[Category: PM Articles]]
[[Category: PM Articles]]

Revision as of 07:19, 8 February 2016

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 curiousity, 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 began looking at dialog boxes and their components. This month, we'll continue by delving into the source code to HELLO which was presented last month. We'll examine the messages in our dialog procedure, and will begin looking at how controls are used within dialogs.


nameDlgProc()

Below is the dialog procedure from HELLO.C condensed a bit:

MRESULT EXPENTRY nameDlgProc(HWND hwndWnd,
                             ULONG ulMsg,
                             MPARAM mpParm1,
                             MPARAM mpParm2)
{
   switch (ulMsg) {
   case WM_INITDLG:
        :
      break;
   case WM_CONTROL:
         :
      break;
   case WM_COMMAND:
         :
      break;
   default:
      return WinDefDlgProc(hwndWnd,ulMsg,mpParm1,mpParm2);
   } /* endswitch */

   return MRFROMSHORT(FALSE);
}

We looked at the WM_INITDLG message last issue; let's take a look at the other two.

WM_COMMAND

This message occurs when a command is to be performed, or when a key combination is translated to a WM_COMMAND accelerator message.

Parameters

param1

usId (USHORT)

Identifier of the command or accelerator key.


usSource (USHORT)

A CMDSRC_* constant describing the source of the message


param2

bPointer (BOOL)

Pointer indicator

TRUE The message is the result of a pointer action.
FALSE The message is the result of a keyboard action.

Returns

reply

ulReserved (BIT32)

Reserved, and must be zero.

WM_CONTROL

This message occurs when a control has a significant event to report to its owner.


Parameters

param1

usId (USHORT)

Identifier of the control sending the notification.


usNotify (USHORT)

The notification code. This is specific to the window class of the control.


param2

pvData (PVOID)

Control data. This is specific to the notification code being sent.


Returns

reply

ulReserved (BIT32)

Reserved, and must be zero.


Okay, "big deal," you say. Just add two more entries to your list of messages that you now know about? Well, these messages are a bit more important than that...


The WM_COMMAND Message

The WM_COMMAND message is important because it is the focal point through which your application will get notified that something needs to get done. Among other things...

  • menu items send this message when they are selected
  • pushbuttons send this message when they are selected
  • the frame window sends this message whenever the user presses a key combination that is defined in the accelerator table
  • dialogs automatically receive this whenever Enter or Escape are pressed.

It doesn't look like much, but as you travel the PM developer's journey, you'll find that this message is frequently sent. It becomes your central interface to the user, since most actions are requested by the user through menus on client windows and through pushbuttons on dialogs.

Let's take a look at how this message is treated in HELLO.C.

case WM_COMMAND:
   switch (SHORT1FROMMP(mpParm1)) {
   case DID_OK:
      WinDismissDlg(hwndWnd,TRUE);
      break;
   case DID_CANCEL:
      WinDismissDlg(hwndWnd,FALSE);
      break;
   default:
      return WinDefDlgProc(hwndWnd,ulMsg,mpParm1,mpParm2);
   } /* endswitch */
   break;

It isn't obvious in the documentation, if I remember correctly, so don't feel ashamed if you don't understand the constants DID_OK and DID_CANCEL.

DID_OK Sent whenever the user presses Enter
DID_CANCEL Sent whenever the user presses Escape

It is imperative that you understand that these messages are not sent by pushbuttons. Thus, even though your dialog might not have pushbuttons, it is possible to receive these messages. (If you don't believe me, comment out the DEFPUSHBUTTON and PUSHBUTTON lines in HELLO.RC, recompile and try.)

Dismissal Revisited

When reading last month's column, I realized that I was talking about the dismissal of dialogs like we were all old pro's at it; if we were, I thought, this column wouldn't have a reason for existance.

BOOL WinDismissDlg(HWND hwndDlg,ULONG ulResult);

This function is used to dismiss a dialog. As was mentioned last time, this does not destroy the dialog by default; it only hides the dialog. What does this have to do with the WM_COMMAND message? Well, the typical action for DID_OK and DID_CANCEL is to dismiss the dialog (for DID_OK, data is usually read from the dialog also and verified), so you can see that this function is used frequently.


In the above, no data is read from the dialog. How does the program know what name to display?...


The WM_CONTROL Message

What happens whenever an item in a listbox is selected? Or whenever the text in an entryfield changes? Or when a checkbox is clicked on by the user? For all of these, and many other events, the owner of the control is sent a WM_CONTROL message, meaning that something occurred that could have an effect on the behavior of the application.

This is a broad message, which has a specific set of parameters based on two criteria:

  1. the class of the control sending the message
  2. the event that generate the message

Thus, for the first scenario, the usNotify is LN_SELECT, and pvData is the

handle of the listbox. For the second, usNotify is EN_CHANGE and pvData is the handle of the entryfield. And so on...

case WM_CONTROL:
   switch (SHORT1FROMMP(mpParm1)) {
   case DNAME_LB_NAMELIST:
      switch (SHORT2FROMMP(mpParm1)) {
      case LN_SELECT:
         {
            HWND hwndLb;
            SHORT sIndex;

            hwndLb=WinWindowFromID(hwndWnd,DNAME_LB_NAMELIST);

            sIndex=WinQueryLboxSelectedItem(hwndLb);
            WinQueryLboxItemText(hwndLb,
                                 sIndex,
                                 pndiInfo->achName,
                                 sizeof(pndiInfo->achName));

            WinSetDlgItemText(hwndWnd,
                              DNAME_EF_NAME,
                              pndiInfo->achName);
         }
         break;
      case LN_ENTER:
         WinPostMsg(hwndWnd,WM_COMMAND,MPFROMSHORT(DID_OK),0);
         break;
      default:
         return WinDefDlgProc(hwndWnd,ulMsg,mpParm1,mpParm2);
      } /* endswitch */
      break;
   default:
      return WinDefDlgProc(hwndWnd,ulMsg,mpParm1,mpParm2);
   } /* endswitch */
   break;

You probably don't understand the specific functions, but you can see for yourself by running the application that, whenever an item is selected in the listbox, the name selected is placed in the entryfield.

.And the Point is...

The point of introducing the WM_COMMAND and WM_CONTROL messages is to demonstrate the usefulness of them. As we begin to look at the controls, we will examine how they interact with the application through these messages; careful exploitation will (eventually) allow you to control the execution of your application.


New Functions

In addition to the WinDismissDlg() function, we will look at three additional PM APIs.

<small>
BOOL WinSetWindowText(HWND hwndWnd,PSZ pszText);

LONG WinQueryWindowText(HWND hwndWnd,LONG lSzBuf,PSZ pszBuffer);

LONG WinQueryWindowTextLength(HWND hwndWnd);
</small>

WinSetWindowText sets the text of the specified window to the specified value. It returns a success flag.

WinQueryWindowText queries the text of the specified window and copies up to either the end of the text or lSzBuf characters into the buffer pointed to by pszBuffer. It returns the number of characters copied.

WinQueryWindowTextLength returns the length of the text for the specified window.


It is important to note that how the window text is actually used differs from control to control. For example, the window text of an entryfield is what is displayed in the entryfield itself. This is also true for a titlebar. However, a listbox has many text entries, which cannot be described by a single text item so it ignores the window text. Some controls use their window text in other ways. A frame, for example, notices when its window text changes and updates the titlebar's window text, if a titlebar exists.

In other words, your mileage may vary.  :)


Summary

This month we introduced two very important messages - WM_COMMAND and WM_CONTROL - and described their purpose in a window or dialog procedure. We also looked at four new PM APIs and looked at window text for the first time since they were mentioned in volume 2, issue 1.

Next month, we will continue with HELLO by begining to examine the controls within it individually.