Using Window Procedures(使用窗口过程)

来源:互联网 发布:罗马纪录片知乎 编辑:程序博客网 时间:2024/05/21 15:05

Using Window Procedures (MFC主题

使用窗口过程
This section explains how to perform the following tasks associated with window procedures.
这部分说明了怎样完成与窗口过程相关的三个问题

Designing a Window Procedure
设计一个窗口过程
Associating a Window Procedure with a Window Class
将窗口过程与窗口类相关联
Subclassing a Window
子分类一个窗口

1.Designing a Window Procedure
设计一个窗口过程
The following example shows the structure of a typical window procedure. The window procedure uses the message argument in a switch statement with individual messages handled by separate case statements. Notice that each case returns a specific value for each message. For messages that it does not process, the window procedure calls the DefWindowProc function.
下例显示了一个典型的窗口过程的结构。窗口过程在一个SWITCH语句中使用消息参数,利用不同的CASE语句来处理不同的消息。要注意的是,对于每一个消息,每一种情况都返回一个指定的值。对于不处理的消息,此窗口过程调用缺省的窗口过程:DefWindowProc.
Hide Example

LRESULT CALLBACK MainWndProc(
      HWND hwnd,          // handle to window
      UINT uMsg,          // message identifier
      WPARAM wParam,      // first message parameter
      LPARAM lParam)      // second message parameter
{

      switch (uMsg)
      {
          case WM_CREATE:
              // Initialize the window.
              return 0;

          case WM_PAINT:
              // Paint the window's client area.
              return 0;

          case WM_SIZE:
              // Set the size and position of the window.
              return 0;

          case WM_DESTROY:
              // Clean up window-specific data objects.
              return 0;

          //
          // Process other messages.
          //

          default:
              return DefWindowProc(hwnd, uMsg, wParam, lParam);
      }
      return 0;
}


The WM_NCCREATE message is sent just after your window is created, but if an application responds to this message by returning FALSE, CreateWindowEx function fails. The WM_CREATE message is sent after your window is already created.
WM_NCCREATE消息在你的窗口刚刚被创建之后被发送,但是如果对此消息作出响应的应用程序返回FALSE,就意味着CreateWindowEx函数失败。WM_CREATE消息在你的窗口已经被创建之后被调用。


The WM_DESTROY message is sent when your window is about to be destroyed. The DestroyWindow function takes care of destroying any child windows of the window being destroyed. The WM_NCDESTROY message is sent just before a window is destroyed.
WM_DESTORY消息在你的窗口将要被销毁之前被发送。DestoryWindow函数负责销毁即将被销毁窗口的所有子窗口。WM_NCDESTORY消息在窗口刚好被销毁之前被发送。


At the very least, a window procedure should process the WM_PAINT message to draw itself. Typically, it should handle mouse and keyboard messages as well. Consult the descriptions of individual messages to determine whether your window procedure should handle them.
最起码的一点是,一个窗口过程应该处理WM_PAINT消息来绘制它自己。典型的是,它同样应该处理鼠标和键盘消息。考虑每个消息的特性来决定你的窗口过程是否应该处理它们。


Your application can call the DefWindowProc function as part of the processing of a message. In such a case, the application can modify the message parameters before passing the message to DefWindowProc, or it can continue with the default processing after performing its own operations.
你的应该程序可以调用DefWindowProc来作为处理消息的一部分。在这种情况下,应该程序能够在消息传递给DefWindowProc这个缺省窗口过程之前修改消息的参数,或者,它也可以在执行完它自己的操作之后继续缺省处理。


A dialog box procedure receives a WM_INITDIALOG message instead of a WM_CREATE message and does not pass unprocessed messages to the DefDlgProc function. Otherwise, a dialog box procedure is exactly the same as a window procedure.
一个对话框处理过程接收WM_INITDIALOG消息而不是WM_CREATE消息,并且不传递未处理的消息给DefDlgProc处理过程。否则的话,对话框处理过程就跟窗口处理完全一样了。

2.Associating a Window Procedure with a Window Class
将窗口过程与窗口类相关联
You associate a window procedure with a window class when registering the class. You must fill a WNDCLASS structure with information about the class, and the lpfnWndProc member must specify the address of the window procedure. To register the class, pass the address of WNDCLASS structure to the RegisterClass function. Once the window class is registered, the window procedure is automatically associated with each new window created with that class.
当注册窗口类时,你需要将一个窗口过程与一个窗口类相关联。你必须将与窗口类相关的信息填入WNDCLASS结构体中,同时成员变量lpfnWndProc必须指定为窗口过程的地址。为了注册一个窗口类,需要将WNDCLASS结构体的地址传递给RegisterClass函数。一旦窗口类被注册了,此窗口过程就自动与每一个利用此窗口类创建的窗口相关联了。


The following example shows how to associate the window procedure in the previous example with a window class.
下例显示了怎样将上例中的窗口过程与一个窗口类相关联
Hide Example

int APIENTRY WinMain(
      HINSTANCE hinstance,    // handle to current instance
      HINSTANCE hinstPrev,    // handle to previous instance
      LPSTR lpCmdLine,        // address of command-line string
      int nCmdShow)           // show-window type
{
      WNDCLASS wc;

      // Register the main window class.
      wc.style = CS_HREDRAW | CS_VREDRAW;
      wc.lpfnWndProc = (WNDPROC) MainWndProc;
      wc.cbClsExtra = 0;
      wc.cbWndExtra = 0;
      wc.hInstance = hinstance;
      wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
      wc.hCursor = LoadCursor(NULL, IDC_ARROW);
      wc.hbrBackground = GetStockObject(WHITE_BRUSH);
      wc.lpszMenuName =    "MainMenu";
      wc.lpszClassName = "MainWindowClass";

      if (!RegisterClass(&wc))
         return FALSE;

      //
      // Process other messages.
      //

}


3.Subclassing a Window
子分类一个窗口
To subclass an instance of a window, call the SetWindowLong function and specify the handle to the window to subclass the GWL_WNDPROC flag and a pointer to the subclass procedure. SetWindowLong returns a pointer to the original window procedure; use this pointer to pass messages to the original procedure. The subclass window procedure must use the CallWindowProc function to call the original window procedure.
为了子分类一个窗口实例,需要调用SetWindowLong函数,同时指定需要被子分类的窗口的句柄,GWL_WNDPROC标记和指向子分类窗口过程的指针。SetWindowLong返回指向之前的窗口过程的指针,利用这一指针可以将消息传递给之前的窗口过程。子分类窗口过程必须利用CallWindowProc函数来调用之前的窗口过程。


The following example shows how to subclass an instance of an edit control in a dialog box. The subclass window procedure enables the edit control to receive all keyboard input, including the ENTER and TAB keys, whenever the control has the input focus.
下例显示了怎样子分类一个对话框中的编辑控件实例。子分类窗口过程使得此编辑控件拥有输入焦点时能够接收所有的键盘输入,包括ENTER和TAB键。
Hide Example

WNDPROC wpOrigEditProc;

LRESULT APIENTRY EditBoxProc(
      HWND hwndDlg,
      UINT uMsg,
      WPARAM wParam,
      LPARAM lParam)
{
      HWND hwndEdit;

      switch(uMsg)
      {
          case WM_INITDIALOG:
              // Retrieve the handle to the edit control.
              hwndEdit = GetDlgItem(hwndDlg, ID_EDIT);

              // Subclass the edit control.
              wpOrigEditProc = (WNDPROC) SetWindowLong(hwndEdit,
                  GWL_WNDPROC, (LONG) EditSubclassProc);
              //
              // Continue the initialization procedure.
              //
              return TRUE;

          case WM_DESTROY:
              // Remove the subclass from the edit control.
              SetWindowLong(hwndEdit, GWL_WNDPROC,
                  (LONG) wpOrigEditProc);
              //
              // Continue the cleanup procedure.
              //
              break;
      }
      return FALSE;
          UNREFERENCED_PARAMETER(lParam);
}

// Subclass procedure
LRESULT APIENTRY EditSubclassProc(
      HWND hwnd,
      UINT uMsg,
      WPARAM wParam,
      LPARAM lParam)
{
      if (uMsg == WM_GETDLGCODE)
          return DLGC_WANTALLKEYS;

      return CallWindowProc(wpOrigEditProc, hwnd, uMsg,
          wParam, lParam);
}