⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ch04.htm

📁 VC使用大全。里面集合了VC使用的各种使用技巧。非常有用。
💻 HTM
📖 第 1 页 / 共 4 页
字号:
<HTML>

<HEAD>

<TITLE>Special Edition Using Visual C++ 5 - Chapter 4</TITLE>

<LINK REL="Next" HREF="ch05.htm" tppabs="http://www.mcp.com/814147200/0-7897/0-7897-1145-1/ch05.htm">

<LINK REL="Previous" HREF="ch03.htm" tppabs="http://www.mcp.com/814147200/0-7897/0-7897-1145-1/ch03.htm"></HEAD>

<BODY BGCOLOR="#FFFFFF" TEXT="#000000">



<H2><B>Chapter 4</B></H2>

<H2><B>Messages and Commands</B></H2>

<hr>

<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&#151;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>

<ul>

<li> <B>Message routing</B></P>

<P>  Windows messages direct your program to perform all the things that it does.</P>

<li> <B>Message loops</B></P>

<P>  In Windows C programming, developers write loops to deal with a steady stream of messages.</P>

<li> <B>Message maps</B></P>

<P>  MFC lightens your conceptual load by letting you catch messages without writing a message loop.</P>

<li> <B>How ClassWizard helps you catch messages</B></P>

<P>  Message map entries are easier to add with ClassWizard.</P>

<li> <B>What messages Windows can generate</B></P>

<P>  There are nearly 900 Windows messages.</P>

<li> <B>Messages versus commands</B></P>

<P>  A command can be routed to parts of your function that can't receive messages.</P>

<li> <B>The command update mechanism</B></P>

<P>  You can gray some menu items to reflect the current state of your application.</P>

<li> <B>How ClassWizard helps you catch and update commands</B></P>

<P>  Understanding command updates is tough, but arranging for them is simple with ClassWizard.</P>

</ul>

<H3><B>Message Routing</B></H3>

<P>Messages are all referred to by their names, though the operating system uses integers to refer to them. An enormous list of <font color="#008000">#define</font> statements connects names to numbers and lets Windows programmers talk about <font 
color="#008000">WM_PAINT</font> or <font color="#008000">WM_SIZE</font> or whatever message they need to talk about. (The <font color="#008000">WM</font> stands for Window Message.) 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&#146;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 gets a <font color="#008000">WM_MOUSEMOVE</font> 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) gets a <font color="#008000">WM_LBUTTONDOWN</font> message, and 
handles it, often generating another message to the window that contains the button, saying, in effect, &quot;I was clicked.&quot;</P>

<P>MFC has allowed many programmers to completely ignore low-level messages like <font color="#008000">WM_MOUSEMOVE</font> and <font color="#008000">WM_LBUTTONDOWN</font>. Instead, programmers deal only with higher-level messages that mean things like 
&quot;The third item in this list box has been selected&quot; or &quot;The Submit button has been clicked.&quot; 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 &quot;chooses&quot; to handle them. MFC makes it much simpler to announce, at the individual classes 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>

<H3><B>Message Loops</B></H3>

<P>The heart of any Windows program is the message loop, typically contained in a <font color="#008000">WinMain()</font> routine. The <font color="#008000">WinMain()</font> routine is, like the <font color="#008000">main()</font> in DOS or UNIX, the 
function called by the operating system when you run the program. You won't write any <font color="#008000">WinMain()</font> routines because it is now hidden away in the code that AppWizard generates for you. Still, there is a <font 
color="#008000">WinMain()</font>, just as there is in Windows C programs. Listing 4.1 shows a typical <font color="#008000">WinMain()</font>.</P>

<P><I>Listing 4.1&#151;Typical </I>WinMain()<I> Routine</I></P>

<pre><font color="#008000">int APIENTRY WinMain(HINSTANCE hInstance,</font></pre>

<pre><font color="#008000">               HINSTANCE hPrevInstance,</font></pre>

<pre><font color="#008000">               LPSTR lpCmdLine,</font></pre>

<pre><font color="#008000">               int nCmdShow)</font></pre>

<pre><font color="#008000">{</font></pre>

<pre><font color="#008000">     MSG msg;</font></pre>

<pre><font color="#008000">     if (! InitApplication (hInstance))</font></pre>

<pre><font color="#008000">      return (FALSE);</font></pre>

<pre><font color="#008000">     if (! InitInstance (hInstance, nCmdShow))</font></pre>

<pre><font color="#008000">      return (FALSE);</font></pre>

<pre><font color="#008000">     while (GetMessage (&amp;msg, NULL, 0, 0)){</font></pre>

<pre><font color="#008000">      TranslateMessage (&amp;msg);</font></pre>

<pre><font color="#008000">      DispatchMessage (&amp;msg);</font></pre>

<pre><font color="#008000">     }</font></pre>

<pre><font color="#008000">     return (msg.wParam);</font></pre>

<pre><font color="#008000">}</font></pre>

<P>In a Windows C program like this, <font color="#008000">InitApplication()</font> typically calls <font color="#008000">RegisterWindow()</font>, and <font color="#008000">InitInstance()</font> typically calls <font color="#008000">CreateWindow()</font>. 
(More details on this are in <A HREF="indexa.htm" tppabs="http://www.mcp.com/814147200/0-7897/0-7897-1145-1/indexa.htm" target="text">Appendix A</A>, &quot;Windows Programming Review and a Look Inside Cwnd.&quot;) Then comes the message loop, the while loop that calls <font color="#008000">GetMessage()</font>. The API 
function <font color="#008000">GetMessage()</font> fills <font color="#008000">msg</font> 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 
<font color="#008000">GetMessage()</font> return False is if the message it gets is <font color="#008000">WM_QUIT</font>.</P>

<p><font color="#008000">TranslateMessage()</font> is an API function that streamlines dealing with keyboard messages. Most of the time, you don't need to know &quot;the A key just went down&quot; or&quot;the A key just went up,&quot; and so on. It's 
enough to know &quot;the user pressed A.&quot; <font color="#008000">TranslateMessage()</font> deals with that. It catches the <font color="#008000">WM_KEYDOWN</font> and <font color="#008000">WM_KEYUP</font> messages, and usually sends a <font 
color="#008000">WM_CHAR</font> 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 get the entire string out of it later, when the user has 
clicked OK. So don't worry too much about <font color="#008000">TranslateMessage()</font>.</P>

<P>The API function <font color="#008000">DispatchMessage()</font> calls the <font color="#008000">WndProc</font> for the window that the message is headed for. The <font color="#008000">WndProc</font> for a Windows C function is a huge <font 
color="#008000">switch</font> statement with one case for each message the programmer planned to catch, like the one in Listing 4.2.</P>

<P><I>Listing 4.2&#151;Typical </I>WndProc()<I> Routine</I></P>

<pre><font color="#008000">LONG APIENTRY MainWndProc (HWND hWnd, // window handle</font></pre>

<pre><font color="#008000">                    UINT message, // type of message</font></pre>

<pre><font color="#008000">                     UINT wParam, // additional information</font></pre>

<pre><font color="#008000">                     LONG lParam) // additional information</font></pre>

<pre><font color="#008000">{</font></pre>

<pre><font color="#008000">     switch (message) {</font></pre>

<pre><font color="#008000">      case WM_MOUSEMOVE:</font></pre>

<pre><font color="#008000">          //handle mouse movement</font></pre>

<pre><font color="#008000">      break;</font></pre>

<pre><font color="#008000">      case WM_LBUTTONDOWN:</font></pre>

<pre><font color="#008000">          //handle left click</font></pre>

<pre><font color="#008000">      break;</font></pre>

<pre><font color="#008000">      case WM_RBUTTONDOWN:</font></pre>

<pre><font color="#008000">          //handle right click</font></pre>

<pre><font color="#008000">      break;</font></pre>

<pre><font color="#008000">      case WM_PAINT:</font></pre>

<pre><font color="#008000">          //repaint the window</font></pre>

<pre><font color="#008000">      break;</font></pre>

<pre><font color="#008000">              </font></pre>

<pre><font color="#008000">      case WM_DESTROY: // message: window being destroyed</font></pre>

<pre><font color="#008000">      PostQuitMessage (0);</font></pre>

<pre><font color="#008000">      break;</font></pre>

<pre><font color="#008000">      default:</font></pre>

<pre><font color="#008000">      return (DefWindowProc (hWnd, message, wParam, lParam));</font></pre>

<pre><font color="#008000">     }</font></pre>

<pre><font color="#008000">     return (0);</font></pre>

<pre><font color="#008000">}</font></pre>

<P>As you can imagine, these <font color="#008000">WndProc</font>s get very long in a hurry. Program maintenance can be a nightmare.  MFC solves this problem by keeping information about message processing close to the functions that handle the messages, 
freeing you from maintaining a giant switch statement that is all in one place. Read on to see how it's done.</P>

<H3><B>Message Maps</B></H3>

<P>Message maps are part of the MFC approach to Windows programming. Instead of writing a <font color="#008000">WinMain()</font> function that sends messages to your <font color="#008000">WindProc</font> and then writing a <font 
color="#008000">WindProc</font> that checks which kind of message this is and then calls another of your functions, you just write the function that will handle the message, and add a message map to your class that says, in effect, &#147;I will handle this 
sort of message.&#148; The framework handles whatever routing is required to get that message to you.</P>

<blockquote><p><img src="tip.gif" tppabs="http://www.mcp.com/814147200/0-7897/0-7897-1145-1/tip.gif">

<P>If you've worked in Microsoft Visual Basic, you should be familiar with event procedures, which handle specific events like a mouse click. The message-handling functions you will write in C++ are equivalent to event procedures. The message map is the 
way that events are connected to their handlers.</P>

<p><img src="bottom.gif" tppabs="http://www.mcp.com/814147200/0-7897/0-7897-1145-1/bottom.gif"></blockquote>

<P>Message maps come in two parts: one in the .h file for a class and one in the corresponding .cpp. Typically, they are generated by wizards, although in some circumstances you will add entries yourself. Listing 4.3 shows the message map from the header 
file of one of the classes in a simple application called ShowString, presented in <A HREF="index09.htm" tppabs="http://www.mcp.com/814147200/0-7897/0-7897-1145-1/index09.htm" target="text">Chapter 9</A>, &quot;Building a Complete Application: ShowString.&quot;</P>

<P><I>Listing 4.3&#151;Message Map from showstring.h </I></P>

<pre><font color="#008000">//{{AFX_MSG(CShowStringApp)</font></pre>

<pre><font color="#008000">     afx_msg void OnAppAbout();</font></pre>

<pre><font color="#008000">          // NOTE - the ClassWizard will add and remove member functions here.</font></pre>

<pre><font color="#008000">          //    DO NOT EDIT what you see in these blocks of generated code !</font></pre>

<pre><font color="#008000">     //}}AFX_MSG</font></pre>

<pre><font color="#008000">     DECLARE_MESSAGE_MAP()</font></pre>

<P>This declares a function called <font color="#008000">OnAppAbout()</font>. The specially formatted comments around the declarations help ClassWizard keep track of which messages are caught by each class. <font 
color="#008000">DECLARE_MESSAGE_MAP()</font> is a macro, expanded by the C++ compiler&#146;s preprocessor, that declares some variables and functions to set up some of this magic message catching.</P>

<P>The message map in the source file, as shown in Listing 4.4, is quite similar.</P>

<P><I>Listing 4.4&#151;Message Map from <A HREF="index10.htm" tppabs="http://www.mcp.com/814147200/0-7897/0-7897-1145-1/index10.htm" target="text">Chapter 10</A>&#146;s showstring.cpp</I></P>

<pre><font color="#008000">BEGIN_MESSAGE_MAP(CShowStringApp, CWinApp)</font></pre>

<pre><font color="#008000">     //{{AFX_MSG_MAP(CShowStringApp)</font></pre>

<pre><font color="#008000">     ON_COMMAND(ID_APP_ABOUT, OnAppAbout)</font></pre>

<pre><font color="#008000">          // NOTE - the ClassWizard will add and remove mapping macros here.</font></pre>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -