📄 ch03.htm
字号:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<HTML>
<HEAD>
<SCRIPT LANGUAGE="JavaScript">
<!--
function popUp(pPage) {
var fullURL = document.location;
var textURL = fullURL.toString();
var URLlen = textURL.length;
var lenMinusPage = textURL.lastIndexOf("/");
lenMinusPage += 1;
var fullPath = textURL.substring(0,lenMinusPage);
popUpWin = window.open('','popWin','resizable=yes,scrollbars=no,width=525,height=394');
figDoc= popUpWin.document;
zhtm= '<HTML><HEAD><TITLE>' + pPage + '</TITLE>';
zhtm += '<link rel="stylesheet" href="/includes/stylesheets/ebooks.css"></head>';
zhtm += '<BODY bgcolor="#FFFFFF">';
zhtm += '<IMG SRC="' + fullPath + pPage + '">';
zhtm += '<P><B>' + pPage + '</B>';
zhtm += '</BODY></HTML>';
window.popUpWin.document.write(zhtm);
window.popUpWin.document.close();
// Johnny Jackson 4/28/98
}
//-->
</SCRIPT>
<link rel="stylesheet" href="ebooks.css" tppabs="http://www.fintech.ru/includes/stylesheets/ebooks.css">
<TITLE>Special Edition Using Visual C++ 6 -- Ch 3 -- Messages and Commands</TITLE>
</HEAD>
<BODY TEXT="#000000" BGCOLOR="#FFFFFF">
<CENTER>
<H1><IMG SRC="que.gif" tppabs="http://www.fintech.ru/library/prog/SEUsingVC6/button/que.gif" WIDTH="171" HEIGHT="66" ALIGN="BOTTOM" BORDER="0"><BR>
Special Edition Using Visual C++ 6</H1>
</CENTER>
<CENTER>
<P><A HREF="ch02.htm" tppabs="http://www.fintech.ru/library/prog/SEUsingVC6/ch02/ch02.htm"><IMG SRC="previous.gif" tppabs="http://www.fintech.ru/library/prog/SEUsingVC6/button/previous.gif" WIDTH="128" HEIGHT="28"
ALIGN="BOTTOM" ALT="Previous chapter" BORDER="0"></A><A HREF="ch04.htm" tppabs="http://www.fintech.ru/library/prog/SEUsingVC6/ch04/ch04.htm"><IMG
SRC="next.gif" tppabs="http://www.fintech.ru/library/prog/SEUsingVC6/button/next.gif" WIDTH="128" HEIGHT="28" ALIGN="BOTTOM" ALT="Next chapter"
BORDER="0"></A><A HREF="index.htm" tppabs="http://www.fintech.ru/library/prog/SEUsingVC6/index.htm"><IMG SRC="contents.gif" tppabs="http://www.fintech.ru/library/prog/SEUsingVC6/button/contents.gif" WIDTH="128"
HEIGHT="28" ALIGN="BOTTOM" ALT="Contents" BORDER="0"></A>
<HR>
</CENTER>
<CENTER>
<H1>- 3 -</H1>
<H1>Messages and Commands</H1>
</CENTER>
<UL>
<LI><A HREF="#Heading1">Understanding Message Routing</A>
<LI><A HREF="#Heading2">Understanding Message Loops</A>
<LI><A HREF="#Heading3">Reading Message Maps</A>
<UL>
<LI><A HREF="#Heading4">Message Map Macros</A>
<LI><A HREF="#Heading5">How Message Maps Work</A>
<LI><A HREF="#Heading6">Messages Caught by MFC Code</A>
</UL>
<LI><A HREF="#Heading7">Learning How ClassWizard Helps You Catch Messages</A>
<UL>
<LI><A HREF="#Heading8">The ClassWizard Tabbed Dialog Box</A>
<LI><A HREF="#Heading9">The Add Windows Message Handler Dialog Box</A>
<LI><A HREF="#Heading10">Which Class Should Catch the Message?</A>
</UL>
<LI><A HREF="#Heading11">Recognizing Messages</A>
<LI><A HREF="#Heading12">Understanding Commands</A>
<LI><A HREF="#Heading13">Understanding Command Updates</A>
<LI><A HREF="#Heading14">Learning How ClassWizard Helps You Catch Commands and Command
Updates</A>
</UL>
<P>
<HR SIZE="4">
<CENTER>
<H1></H1>
</CENTER>
<H2><A NAME="Heading1"></A>Understanding Message Routing</H2>
<P>If there is one thing that sets Windows programming apart from other kinds of
programming, it is messages. Most DOS programs, for example, relied on watching (sometimes
called <I>polling</I>) possible sources of input like the keyboard or the mouse to
await input from them. A program that wasn't polling the mouse would not react to
mouse input. In contrast, everything that happens in a Windows program is mediated
by messages. A message is a way for the operating system to tell an application that
something has happened--for example, the user has typed, clicked, or moved the mouse,
or the printer has become available. A window (and every screen element is a window)
can also send a message to another window, and typically most windows react to messages
by passing a slightly different message along to another window. MFC has made it
much easier to deal with messages, but you must understand what is going on beneath
the surface.</P>
<P>Messages are all referred to by their names, though the operating system uses
integers to refer to them. An enormous list of #define statements connects names
to numbers and lets Windows programmers talk about WM_PAINT or WM_SIZE or whatever
message they need to talk about. (The WM stands for Window Message.) An excerpt from
that list is shown in Listing 3.1.</P>
<P>
<H4>Listing 3.1  Excerpt from winuser.h Defining Message Names</H4>
<PRE>#define WM_SETFOCUS 0x0007
#define WM_KILLFOCUS 0x0008
#define WM_ENABLE 0x000A
#define WM_SETREDRAW 0x000B
#define WM_SETTEXT 0x000C
#define WM_GETTEXT 0x000D
#define WM_GETTEXTLENGTH 0x000E
#define WM_PAINT 0x000F
#define WM_CLOSE 0x0010
#define WM_QUERYENDSESSION 0x0011
#define WM_QUIT 0x0012
#define WM_QUERYOPEN 0x0013
#define WM_ERASEBKGND 0x0014
#define WM_SYSCOLORCHANGE 0x0015
</PRE>
<PRE>#define WM_ENDSESSION 0x0016
</PRE>
<P>As well as a name, a message knows what window it is for and can have up to two
parameters. (Often, several different values are packed into these parameters, but
that's another story.)</P>
<P>Different messages are handled by different parts of the operating system or your
application. For example, when the user moves the mouse over a window, the window
receives a WM_MOUSEMOVE message, which it almost certainly passes to the operating
system to deal with. The operating system redraws the mouse cursor at the new location.
When the left button is clicked over a button, the button (which is a window) receives
a WM_LBUTTONDOWN message and handles it, often generating another message to the
window that contains the button, saying, in effect, "I was clicked."</P>
<P>MFC has enabled many programmers to completely ignore low-level messages such
as WM_MOUSEMOVE and WM_LBUTTONDOWN. Instead, programmers deal only with higher level
messages that mean things like "The third item in this list box has been selected"
or "The Submit button has been clicked." All these kinds of messages move
around in your code and the operating system code in the same way as the lower level
messages. The only difference is what piece of code chooses to handle them. MFC makes
it much simpler to announce, at the individual class's level, which messages each
class can handle. The old C way, which you will see in the next section, made those
announcements at a higher level and interfered with the object-oriented approach
to Windows programming, which involves hiding implementation details as much as possible
inside objects.</P>
<P>
<H2><A NAME="Heading2"></A>Understanding Message Loops</H2>
<P>The heart of any Windows program is the message loop, typically contained in a
WinMain() routine. The WinMain() routine is, like the main() in DOS or UNIX, the
function called by the operating system when you run the program. You won't write
any WinMain() routines because it is now hidden away in the code that AppWizard generates
for you. Still, there is a WinMain(), just as there is in Windows C programs. Listing
3.2 shows a typical WinMain().</P>
<P>
<H4>Listing 3.2  Typical WinMain() Routine</H4>
<PRE>int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
MSG msg;
if (! InitApplication (hInstance))
return (FALSE);
if (! InitInstance (hInstance, nCmdShow))
return (FALSE);
while (GetMessage (&msg, NULL, 0, 0)){
TranslateMessage (&msg);
DispatchMessage (&msg);
}
return (msg.wParam);
</PRE>
<PRE>}
</PRE>
<P>In a Windows C program like this, InitApplication() typically calls RegisterWindow(),
and InitInstance() typically calls CreateWindow(). (More details on this are in Appendix
B, "Windows Programming Review and a Look Inside Cwnd.") Then comes the
message loop, the while loop that calls GetMessage(). The API function GetMessage()
fills msg with a message destined for this application and almost always returns
TRUE, so this loop runs over and over until the program is finished. The only thing
that makes GetMessage() return FALSE is if the message it receives is WM_QUIT.</P>
<P>TranslateMessage() is an API function that streamlines dealing with keyboard messages.
Most of the time, you don't need to know that "the A key just went down"
or "the A key just went up," and so on. It's enough to know that "the
user pressed A." TranslateMessage() deals with that. It catches the WM_KEYDOWN
and WM_KEYUP messages and usually sends a WM_CHAR message in their place. Of course,
with MFC, most of the time you don't care that the user pressed A. The user types
into an edit box or similar control, and you can retrieve the entire string out of
it later, when the user has clicked OK. Don't worry too much about TranslateMessage().</P>
<P>The API function DispatchMessage() calls the WndProc for the window that the message
is headed for. The WndProc() function for a Windows C program is a huge switch statement
with one case for each message the programmer planned to catch, such as the one in
Listing 3.3.</P>
<P>
<H4>Listing 3.3  Typical WndProc() Routine</H4>
<PRE>LONG APIENTRY MainWndProc (HWND hWnd, // window handle
UINT message, // type of message
UINT wParam, // additional information
LONG lParam) // additional information
{
switch (message) {
case WM_MOUSEMOVE:
//handle mouse movement
break;
case WM_LBUTTONDOWN:
//handle left click
break;
case WM_RBUTTONDOWN:
//handle right click
break;
case WM_PAINT:
//repaint the window
break;
case WM_DESTROY: // message: window being destroyed
PostQuitMessage (0);
break;
default:
return (DefWindowProc (hWnd, message, wParam, lParam));
}
return (0);
</PRE>
<PRE>}
</PRE>
<P>As you can imagine, these WndProcs become very long in a hurry. Program maintenance
can be a nightmare. MFC solves this problem by keeping information about message
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -