2008 November 18th Tuesday (十一月 十八日 火曜日)

来源:互联网 发布:精准扶贫数据平台 编辑:程序博客网 时间:2024/04/29 15:05
   We will now tamper with three lines of code that are common to all the Windows programs we've created so far in this book. The code
is the standard message loop:

while (GetMessage (&msg, NULL, 0, 0))
{
     TranslateMessage (&msg) ;
     DispatchMessage (&msg) ;
}

Here's how we change it to use the keyboard accelerator table:

while (GetMessage (&msg, NULL, 0, 0))
{
     if (!TranslateAccelerator (hwnd, hAccel, &msg))
     {
          TranslateMessage (&msg) ;
          DispatchMessage (&msg) ;
     }
}

  The TranslateAccelerator function determines whether the message stored in the msg message structure is a keyboard message. If it is,
the function searches for a match in the accelerator table whose handle is hAccel. If it finds a match, it calls the window procedure
for the window whose handle is hwnd. If the keyboard accelerator ID corresponds to a menu item in the system menu, the message is WM_SYSCOMMAND.
Otherwise, the message is WM_COMMAND.

  When TranslateAccelerator returns, the return value is nonzero if the message has been translated (and already sent to the window procedure)
and 0 if not. If TranslateAccelerator returns a nonzero value, you should not call TranslateMessage and DispatchMessage but rather should loop
back to the GetMessage call.

  The hwnd parameter in TranslateMessage looks a little out of place because it's not required in the other three functions in the message loop.
Moreover, the message structure itself (the structure variable msg) has a member named hwnd, which is also a handle to a window.

  Here's why the function is a little different: The fields of the msg structure are filled in by the GetMessage call. When the second parameter
of GetMessage is NULL, the function retrieves messages for all windows belonging to the application. When GetMessage returns, the hwnd member of
the msg structure is the window handle of the window that will get the message. However, when TranslateAccelerator translates a keyboard message
into a WM_COMMAND or WM_SYSCOMMAND message, it replaces the msg.hwnd window handle with the hwnd window handle specified as the first parameter
to the function. That is how Windows sends all keyboard accelerator messages to the same window procedure even if another window in the application
currently has the input focus. TranslateAccelerator does not translate keyboard messages when a modal dialog box or message box has the input focus,
because messages for these windows do not come through the program's message loop.

The Dialog Box Procedure

  The dialog box procedure within your program handles messages to the dialog box. Although it looks very much like a window procedure, it is not
a true window procedure. The window procedure for the dialog box is within Windows. That window procedure calls your dialog box procedure with many
of the messages that it receives. Here's the dialog box procedure for ABOUT1:

BOOL CALLBACK AboutDlgProc (HWND hDlg, UINT message,
                            WPARAM wParam, LPARAM lParam)
{
     switch (message)
     {
     case WM_INITDIALOG :
          return TRUE ;
         
     case WM_COMMAND :
          switch (LOWORD (wParam))
          {
          case IDOK :
          case IDCANCEL :
               EndDialog (hDlg, 0) ;
               return TRUE ;
          }
          break ;
     }
     return FALSE ;
}

  The parameters to this function are the same as those for a normal window procedure; as with a window procedure, the dialog box procedure must
be defined as a CALLBACK function. Although I've used hDlg for the handle to the dialog box window, you can use hwnd instead if you like. Let's
note first the differences between this function and a window procedure:

  A window procedure returns an LRESULT; a dialog box procedure returns a BOOL, which is defined in the Windows header files as an int.

  A window procedure calls DefWindowProc if it does not process a particular message; a dialog box procedure returns TRUE (nonzero) if it processes
a message and FALSE (0) if it does not.

  A dialog box procedure does not need to process WM_PAINT or WM_DESTROY messages. A dialog box procedure will not receive a WM_CREATE message;
instead, the dialog box procedure performs initialization during the special WM_INITDIALOG message.

  The WM_INITDIALOG message is the first message the dialog box procedure receives. This message is sent only to dialog box procedures. If the dialog
box procedure returns TRUE, Windows sets the input focus to the first child window control in the dialog box that has a WS_TABSTOP style. In this
dialog box, the first child window control that has a WS_TABSTOP style is the push button. Alternatively, during the processing of WM_INITDIALOG,
the dialog box procedure can use SetFocus to set the focus to one of the child window controls in the dialog box and then return FALSE.

  The messages for a modal dialog box don't go through your program's message queue, so you needn't worry about the effect of keyboard accelerators
within the dialog box.

  When you invoke the dialog box, use DialogBoxParam rather than DialogBox. This function has a fifth argument that can be any 32-bit value you'd like.
Generally, it is set to a pointer to a structure, in this case the ABOUTBOX_DATA structure in WndProc:

case IDM_ABOUT:
     if (DialogBoxParam (hInstance, TEXT ("AboutBox"),
                         hwnd, AboutDlgProc, &ad))
          InvalidateRect (hwnd, NULL, TRUE) ;
     return 0 ;

  Here's the key: the last argument to DialogBoxParam is passed to the dialog procedure as lParam in the WM_INITDIALOG message.

原创粉丝点击