WEB开发网
开发学院软件开发VC 深度解析VC中的消息(中) 阅读

深度解析VC中的消息(中)

 2009-10-27 20:31:19 来源:WEB开发网   
核心提示:窗口过程窗口过程是一个用于处理所有发送到这个窗口的消息的函数,任何一个窗口类都有一个窗口过程,深度解析VC中的消息(中)(2),同一个类的窗口使用同样的窗口过程来响应消息, 系统发送消息给窗口过程将消息数据作为参数传递给他,好了,事情到这里也算是也段落了,消息到来之后,按照消息类型排序进行处理

窗口过程

窗口过程是一个用于处理所有发送到这个窗口的消息的函数。任何一个窗口类都有一个窗口过程。同一个类的窗口使用同样的窗口过程来响应消息。 系统发送消息给窗口过程将消息数据作为参数传递给他,消息到来之后,按照消息类型排序进行处理,其中的参数则用来区分不同的消息,窗口过程使用参数产生合适行为。

一个窗口过程不经常忽略消息,如果他不处理,它会将消息传回到执行默认的处理。窗口过程通过调用DefWindowProc来做这个处理。窗口过程必须return一个值作为它的消息处理结果。大多数窗口只处理小部分消息和将其他的通过DefWindowProc传递给系统做默认的处理。窗口过程被所有属于同一个类的窗口共享,能为不同的窗口处理消息。下面我们来看一下具体的实例:

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
PAINTSTRUCT ps;
HDC hdc;
TCHAR szHello[MAX_LOADSTRING];
LoadString(hInst, IDS_HELLO, szHello, MAX_LOADSTRING);
switch (message)
{
  case WM_COMMAND:
     wmId  = LOWORD(wParam);
     wmEvent = HIWORD(wParam);
     // Parse the menu selections:
     switch (wmId)
     {
     case IDM_ABOUT:
        DialogBox(hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd, (DLGPROC)About);
        break;
     case IDM_EXIT:
        DestroyWindow(hWnd);
       break;
      default:
       return DefWindowProc(hWnd, message, wParam, lParam);
     }
  break;
  case WM_PAINT:
     hdc = BeginPaint(hWnd, &ps);
     // TODO: Add any drawing code here...
     RECT rt;
     GetClientRect(hWnd, &rt);
     DrawText(hdc, szHello, strlen(szHello), &rt, DT_CENTER);
     EndPaint(hWnd, &ps);
     break;
  case WM_DESTROY:
     PostQuitMessage(0);
     break;
  default:
     return DefWindowProc(hWnd, message, wParam, lParam);
  }
  return 0;
}

消息分流器

通常的窗口过程是通过一个switch语句来实现的,这个事情很烦,有没有更简便的方法呢?有,那就是消息分流器,利用消息分流器,我们可以把switch语句分成更小的函数,每一个消息都对应一个小函数,这样做的好处就是对消息更容易管理。

之所以被称为消息分流器,就是因为它可以对任何消息进行分流。下面我们做一个函数就很清楚了:

void MsgCracker(HWND hWnd,int id,HWND hWndCtl,UINT codeNotify)
{
    switch(id)
    {
   case ID_A:
          if(codeNotify==EN_CHANGE)...
          break;
   case ID_B:
          if(codeNotify==BN_CLICKED)...
          break;
       ....
    }
}

然后我们修改一下窗口过程:

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch(message)
    {
       HANDLE_MSG(hWnd,WM_COMMAND,MsgCracker);
       HANDLE_MSG(hWnd,WM_DESTROY,MsgCracker);
       default:
           return DefWindowProc(hWnd, message, wParam, lParam);
   }
  return 0;
}

在WindowsX.h中定义了如下的HANDLE_MSG宏:

#define HANDLE_MSG(hwnd,msg,fn) \

switch(msg): return HANDLE_##msg((hwnd),(wParam),(lParam),(fn));

实际上,HANDLE_WM_XXXX都是宏,例如:HANDLE_MSG(hWnd,WM_COMMAND,MsgCracker);将被转换成如下定义:

#define HANDLE_WM_COMMAND(hwnd,wParam,lParam,fn)

((fn)((hwnd),(int)(LOWORD(wParam)),(HWND)(lParam),(UINT)HIWORD(wParam)),0L);

好了,事情到了这一步,应该一切都明朗了。

不过,我们发现在windowsx.h里面还有一个宏:FORWARD_WM_XXXX,我们还是那WM_COMMAND为例,进行分析:

#define FORWARD_WM_COMMAND(hwnd, id, hwndCtl, codeNotify, fn)

(void)(fn)((hwnd), WM_COMMAND, MAKEWPARAM((UINT)(id),(UINT)(codeNotify)), (LPARAM)(HWND)(hwndCtl))

所以实际上,FORWARD_WM_XXXX将消息参数进行了重新构造,生成了wParam && lParam,然后调用了我们定义的函数。

好了,事情到这里也算是也段落了,下次我们在分析消息在MFC中的处理。

未完(待续...)

上一页  1 2 

Tags:深度 解析 VC

编辑录入:爽爽 [复制链接] [打 印]
赞助商链接