• Windows消息机制


    消息是指什么?
         消息系统对于一个win32程序来说十分重要,它是一个程序运行的动力源泉。一个消息,是系统定义的一个32位的值,他唯一的定义了一个事件,向 Windows发出一个通知,告诉应用程序某个事情发生了。例如,单击鼠标、改变窗口尺寸、按下键盘上的一个键都会使Windows发送一个消息给应用程序。
        消息本身是作为一个记录传递给应用程序的,这个记录中包含了消息的类型以及其他信息。例如,对于单击鼠标所产生的消息来说,这个记录中包含了单击鼠标时的坐标。这个记录类型叫做MSG,MSG含有来自windows应用程序消息队列的消息信息,它在Windows中声明如下:

    typedef struct tagMsg
    {
           HWND    hwnd;       //接受该消息的窗口句柄
           UINT    message;    //消息常量标识符,也就是我们通常所说的消息号
           WPARAM  wParam;     //32位消息的特定附加信息,确切含义依赖于消息值
           LPARAM  lParam;     //32位消息的特定附加信息,确切含义依赖于消息值
           DWORD   time;       //消息创建时的时间
           POINT   pt;         //消息创建时的鼠标/光标在屏幕坐标系中的位置
    }MSG;


        消息可以由系统或者应用程序产生。系统在发生输入事件时产生消息。举个例子, 当用户敲键, 移动鼠标或者单击控件。系统也产生消息以响应由应用程序带来的变化, 比如应用程序改变系统字体改变窗体大小。应用程序可以产生消息使窗体执行任务,或者与其他应用程序中的窗口通讯。

    消息中有什么?
       
    我们给出了上面的注释,是不是会对消息结构有了一个比较清楚的认识?如果还没有,那么我们再试着给出下面的解释:
         hwnd 32位的窗口句柄。窗口可以是任何类型的屏幕对象,因为Win32能够维护大多数可视对象的句柄(窗口、对话框、按钮、编辑框等)。
         message用于区别其他消息的常量值,这些常量可以是Windows单元中预定义的常量,也可以是自定义的常量。消息标识符以常量命名的方式指出消息的含义。当窗口过程接收到消息之后,他就会使用消息标识符来决定如何处理消息。例如、WM_PAINT告诉窗口过程窗体客户区被改变了需要重绘。符号常量指定系统消息属于的类别,其前缀指明了处理解释消息的窗体的类型。
         wParam 通常是一个与消息有关的常量值,也可能是窗口或控件的句柄。
         lParam 通常是一个指向内存中数据的指针。由于WParam、lParam和Pointer都是32位的,因此,它们之间可以相互转换。

    消息标识符的值
         系统保留消息标识符的值在0x0000在0x03ff(WM_USER-1)范围。这些值被系统定义消息使用。应用程序不能使用这些值给自己的消息。应用程序消息从WM_USER(0X0400)到0X7FFF,或0XC000到0XFFFF;WM_USER到 0X7FFF范围的消息由应用程序自己使用;0XC000到0XFFFF范围的消息用来和其他应用程序通信,我们顺便说一下具有标志性的消息值:
         WM_NULL---0x0000    空消息。
         0x0001----0x0087    主要是窗口消息。
         0x00A0----0x00A9    非客户区消息 
         0x0100----0x0108    键盘消息
         0x0111----0x0126    菜单消息
         0x0132----0x0138    颜色控制消息
         0x0200----0x020A    鼠标消息
         0x0211----0x0213    菜单循环消息
         0x0220----0x0230    多文档消息
         0x03E0----0x03E8    DDE消息
         0x0400              WM_USER
         0x8000              WM_APP
         0x0400----0x7FFF    应用程序自定义私有消息

    消息有哪几种?
       
    其实,windows中的消息虽然很多,但是种类并不繁杂,大体上有3种:窗口消息、命令消息和控件通知消息。
         窗口消息大概是系统中最为常见的消息,它是指由操作系统和控制其他窗口的窗口所使用的消息。例如CreateWindow、DestroyWindow和MoveWindow等都会激发窗口消息,还有我们在上面谈到的单击鼠标所产生的消息也是一种窗口消息。
         命令消息,这是一种特殊的窗口消息,他用来处理从一个窗口发送到另一个窗口的用户请求,例如按下一个按钮,他就会向主窗口发送一个命令消息。
         控件通知消息,是指这样一种消息,一个窗口内的子控件发生了一些事情,需要通知父窗口。通知消息只适用于标准的窗口控件如按钮、列表框、组合框、编辑框,以及Windows公共控件如树状视图、列表视图等。例如,单击或双击一个控件、在控件中选择部分文本、操作控件的滚动条都会产生通知消息。她类似于命令消息,当用户与控件窗口交互时,那么控件通知消息就会从控件窗口发送到它的主窗口。但是这种消息的存在并不是为了处理用户命令,而是为了让主窗口能够改变控件,例如加载、显示数据。例如按下一个按钮,他向父窗口发送的消息也可以看作是一个控件通知消息;单击鼠标所产生的消息可以由主窗口直接处理,然后交给控件窗口处理。
        其中窗口消息及控件通知消息主要由窗口类即直接或间接由CWND类派生类处理。相对窗口消息及控件通知消息而言,命令消息的处理对象范围就广得多,它不仅可以由窗口类处理,还可以由文档类,文档模板类及应用类所处理。
        由于控件通知消息很重要的,人们用的也比较多,但是具体的含义往往令初学者晕头转向,所以我决定把常见的几个列出来供大家参考:
    按扭控件
    BN_CLICKED        用户单击了按钮
     BN_DISABLE 按钮被禁止
     BN_DOUBLECLICKED  用户双击了按钮
     BN_HILITE  用/户加亮了按钮
     BN_PAINT  按钮应当重画
     BN_UNHILITE 加亮应当去掉

    组合框控件
     CBN_CLOSEUP 组合框的列表框被关闭
     CBN_DBLCLK 用户双击了一个字符串
     CBN_DROPDOWN 组合框的列表框被拉出
     CBN_EDITCHANGE 用户修改了编辑框中的文本
     CBN_EDITUPDATE 编辑框内的文本即将更新
     CBN_ERRSPACE 组合框内存不足
     CBN_KILLFOCUS 组合框失去输入焦点
     CBN_SELCHANGE 在组合框中选择了一项
     CBN_SELENDCANCEL 用户的选择应当被取消
     CBN_SELENDOK 用户的选择是合法的
     CBN_SETFOCUS 组合框获得输入焦点

    编辑框控件
     EN_CHANGE 编辑框中的文本己更新
     EN_ERRSPACE 编辑框内存不足
     EN_HSCROLL 用户点击了水平滚动条
     EN_KILLFOCUS 编辑框正在失去输入焦点
     EN_MAXTEXT 插入的内容被截断
     EN_SETFOCUS 编辑框获得输入焦点
     EN_UPDATE 编辑框中的文本将要更新
     EN_VSCROLL 用户点击了垂直滚动条消息含义

    列表框控件
     LBN_DBLCLK 用户双击了一项
     LBN_ERRSPACE 列表框内存不够
     LBN_KILLFOCUS 列表框正在失去输入焦点
     LBN_SELCANCEL 选择被取消
     LBN_SELCHANGE 选择了另一项
     LBN_SETFOCUS 列表框获得输入焦点

    队列消息和非队列消息
       
    从消息的发送途径来看,消息可以分成2种:队列消息和非队列消息。消息队列由可以分成系统消息队列和线程消息队列。系统消息队列由Windows维护,线程消息队列则由每个GUI线程自己进行维护,为避免给non-GUI现成创建消息队列,所有线程产生时并没有消息队列,仅当线程第一次调用GDI函数时系统才给线程创建一个消息队列。队列消息送到系统消息队列,然后到线程消息队列;非队列消息直接送给目的窗口过程。
         对于队列消息,最常见的是鼠标和键盘触发的消息,例如WM_MOUSERMOVE,WM_CHAR等消息,还有一些其它的消息,例如:WM_PAINT、 WM_TIMER和WM_QUIT。当鼠标、键盘事件被触发后,相应的鼠标或键盘驱动程序就会把这些事件转换成相应的消息,然后输送到系统消息队列,由 Windows系统去进行处理。Windows系统则在适当的时机,从系统消息队列中取出一个消息,根据前面我们所说的MSG消息结构确定消息是要被送往那个窗口,然后把取出的消息送往创建窗口的线程的相应队列,下面的事情就该由线程消息队列操心了,Windows开始忙自己的事情去了。线程看到自己的消息队列中有消息,就从队列中取出来,通过操作系统发送到合适的窗口过程去处理。
         一般来讲,系统总是将消息Post在消息队列的末尾。这样保证窗口以先进先出的顺序接受消息。然而,WM_PAINT是一个例外,同一个窗口的多个 WM_PAINT被合并成一个 WM_PAINT 消息, 合并所有的无效区域到一个无效区域。合并WM_PAIN的目的是为了减少刷新窗口的次数。



        非队列消息将会绕过系统队列和消息队列,直接将消息发送到窗口过程,。系统发送非队列消息通知窗口,系统发送消息通知窗口。例如,当用户激活一个窗口系统发送WM_ACTIVATE, WM_SETFOCUS, and WM_SETCURSOR。这些消息通知窗口它被激活了。非队列消息也可以由当应用程序调用系统函数产生。例如,当程序调用SetWindowPos系统发送WM_WINDOWPOSCHANGED消息。一些函数也发送非队列消息,例如下面我们要谈到的函数。
         
    消息的发送
         了解了上面的这些基础理论之后,我们就可以进行一下简单的消息发送与接收。
         把一个消息发送到窗口有3种方式:发送、寄送和广播。
         发送消息的函数有SendMessage、SendMessageCallback、SendNotifyMessage、 SendMessageTimeout;寄送消息的函数主要有PostMessage、PostThreadMessage、 PostQuitMessage;广播消息的函数我知道的只有BroadcastSystemMessage、 BroadcastSystemMessageEx。
         SendMessage的原型如下:LRESULT SendMessage(HWND hWnd,UINT Msg,WPARAM wParam,LPARAM lParam),这个函数主要是向一个或多个窗口发送一条消息,一直等到消息被处理之后才会返回。不过需要注意的是,如果接收消息的窗口是同一个应用程序的一部分,那么这个窗口的窗口函数就被作为一个子程序马上被调用;如果接收消息的窗口是被另外的线程所创建的,那么窗口系统就切换到相应的线程并且调用相应的窗口函数,这条消息不会被放进目标应用程序队列中。函数的返回值是由接收消息的窗口的窗口函数返回,返回的值取决于被发送的消息。
         PostMessage的原型如下:BOOL PostMessage(HWND hWnd,UINT Msg,WPARAM wParam,LPARAM lParam),该函数把一条消息放置到创建hWnd窗口的线程的消息队列中,该函数不等消息被处理就马上将控制返回。需要注意的是,如果hWnd参数为 HWND_BROADCAST,那么,消息将被寄送给系统中的所有的重叠窗口和弹出窗口,但是子窗口不会收到该消息;如果hWnd参数为NULL,则该函数类似于将dwThreadID参数设置成当前线程的标志来调用PostThreadMEssage函数。
      从上面的这2个具有代表性的函数,我们可以看出消息的发送方式和寄送方式的区别所在:被发送的消息是否会被立即处理,函数是否立即返回。被发送的消息会被立即处理,处理完毕后函数才会返回;被寄送的消息不会被立即处理,他被放到一个先进先出的队列中,一直等到应用程序空线的时候才会被处理,不过函数放置消息后立即返回。

      实际上,发送消息到一个窗口处理过程和直接调用窗口处理过程之间并没有太大的区别,他们直接的唯一区别就在于你可以要求操作系统截获所有被发送的消息,但是不能够截获对窗口处理过程的直接调用。
      以寄送方式发送的消息通常是与用户输入事件相对应的,因为这些事件不是十分紧迫,可以进行缓慢的缓冲处理,例如鼠标、键盘消息会被寄送,而按钮等消息则会被发送。
      广播消息用得比较少,BroadcastSystemMessage函数原型如下:
          long BroadcastSystemMessage(DWORD dwFlags,LPDWORD lpdwRecipients,UINT uiMessage,WPARAM wParam,LPARAM lParam);该函数可以向指定的接收者发送一条消息,这些接收者可以是应用程序、可安装的驱动程序、网络驱动程序、系统级别的设备驱动消息和他们的任意组合。需要注意的是,如果dwFlags参数是BSF_QUERY并且至少一个接收者返回了BROADCAST_QUERY_DENY,则返回值为0,如果没有指定BSF_QUERY,则函数将消息发送给所有接收者,并且忽略其返回值。

    消息的接收
     
    消息的接收主要有3个函数:GetMessage、PeekMessage、WaitMessage。
      GetMessage原型如下:BOOL GetMessage(LPMSG lpMsg,HWND hWnd,UINT wMsgFilterMin,UINT wMsgFilterMax);该函数用来获取与hWnd参数所指定的窗口相关的且wMsgFilterMin和wMsgFilterMax参数所给出的消息值范围内的消息。需要注意的是,如果hWnd为NULL,则GetMessage获取属于调用该函数应用程序的任一窗口的消息,如果 wMsgFilterMin和wMsgFilterMax都是0,则GetMessage就返回所有可得到的消息。函数获取之后将删除消息队列中的除 WM_PAINT消息之外的其他消息,至于WM_PAINT则只有在其处理之后才被删除。
       PeekMessage原型如下:BOOL PeekMessage(LPMSG lpMsg,HWND hWnd,UINT wMsgFilterMin,UINT wMsgFilterMax,UINT wRemoveMsg);该函数用于查看应用程序的消息队列,如果其中有消息就将其放入lpMsg所指的结构中,不过,与GetMessage不同的是,PeekMessage函数不会等到有消息放入队列时才返回。同样,如果hWnd为NULL,则PeekMessage获取属于调用该函数应用程序的任一窗口的消息,如果hWnd=-1,那么函数只返回把hWnd参数为NULL的PostAppMessage函数送去的消息。如果 wMsgFilterMin和wMsgFilterMax都是0,则PeekMessage就返回所有可得到的消息。函数获取之后将视最后一个参数来决定是否删除消息队列中的除 WM_PAINT消息之外的其他消息,至于WM_PAINT则只有在其处理之后才被删除。
       WaitMessage原型如下:BOOL WaitMessage();当一个应用程序无事可做时,该函数就将控制权交给另外的应用程序,同时将该应用程序挂起,直到一个新的消息被放入应用程序的队列之中才返回。

    消息的处理
      接下来我们谈一下消息的处理,首先我们来看一下VC中的消息泵:

    while(GetMessage(&msg, NULL, 0, 0))
    {
           if(!TranslateAccelerator(msg.hWnd, hAccelTable, &msg))
          
                TranslateMessage(&msg);
                DispatchMessage(&msg);
           }
    }

       首先,GetMessage从进程的主线程的消息队列中获取一个消息并将它复制到MSG结构,如果队列中没有消息,则GetMessage函数将等待一个消息的到来以后才返回。如果你将一个窗口句柄作为第二个参数传入GetMessage,那么只有指定窗口的的消息可以从队列中获得。GetMessage也可以从消息队列中过滤消息只接受消息队列中落在范围内的消息。这时候就要利用GetMessage/PeekMessage指定一个消息过滤器。这个过滤器是一个消息标识符的范围或者是一个窗体句柄,或者两者同时指定。当应用程序要查找一个后入消息队列的消息是很有用。WM_KEYFIRST 和 WM_KEYLAST 常量用于接受所有的键盘消息。 WM_MOUSEFIRST 和 WM_MOUSELAST 常量用于接受所有的鼠标消息。 
     然后TranslateAccelerator判断该消息是不是一个按键消息并且是一个加速键消息,如果是,则该函数将把几个按键消息转换成一个加速键消息传递给窗口的回调函数。处理了加速键之后,函数TranslateMessage将把两个按键消息WM_KEYDOWN和WM_KEYUP转换成一个 WM_CHAR,不过需要注意的是,消息WM_KEYDOWN,WM_KEYUP仍然将传递给窗口的回调函数。     
     处理完之后,DispatchMessage函数将把此消息发送给该消息指定的窗口中已设定的回调函数。如果消息是WM_QUIT,则 GetMessage返回0,从而退出循环体。应用程序可以使用PostQuitMessage来结束自己的消息循环。通常在主窗口的 WM_DESTROY消息中调用。
     下面我们举一个常见的小例子来说明这个消息泵的运用:

    if (::PeekMessage(&msg, m_hWnd, WM_KEYFIRST,WM_KEYLAST, PM_REMOVE))
    {
              if (msg.message == WM_KEYDOWN && msg.wParam == VK_ESCAPE)...
    }


      这里我们接受所有的键盘消息,所以就用WM_KEYFIRST 和 WM_KEYLAST作为参数。最后一个参数可以是PM_NOREMOVE 或者 PM_REMOVE,表示消息信息是否应该从消息队列中删除。                 
       所以这段小代码就是判断是否按下了Esc键,如果是就进行处理。

    窗口过程
     窗口过程是一个用于处理所有发送到这个窗口的消息的函数。任何一个窗口类都有一个窗口过程。同一个类的窗口使用同样的窗口过程来响应消息。系统发送消息给窗口过程将消息数据作为参数传递给他,消息到来之后,按照消息类型排序进行处理,其中的参数则用来区分不同的消息,窗口过程使用参数产生合适行为。
     一个窗口过程不经常忽略消息,如果他不处理,它会将消息传回到执行默认的处理。窗口过程通过调用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中的实现。

    MFC消息的处理实现方式
      初看MFC中的各种消息,以及在头脑中根深蒂固的C++的影响,我们可能很自然的就会想到利用C++的三大特性之一:虚拟机制来实现消息的传递,但是经过分析,我们看到事情并不是想我们想象的那样,在MFC中消息是通过一种所谓的消息映射机制来处理的。
      为什么呢?在潘爱民老师翻译的《Visual C++技术内幕》(第4版)中给出了详细的原因说明,我再简要的说一遍。在CWnd类中大约有110个消息,还有其它的MFC的类呢,算起来消息太多了,在C++中对程序中用到的每一个派生类都要有一个vtable,每一个虚函数在vtable中都要占用一个4字节大小的入口地址,这样一来,对于每个特定类型的窗口或控件,应用程序都需要一个440KB大小的表来支持虚拟消息控件函数。
      如果说上面的窗口或控件可以勉强实现的话,那么对于菜单命令消息及按钮命令消息呢?因为不同的应用程序有不同的菜单和按钮,我们怎么处理呢?在MFC 库的这种消息映射系统就避免了使用大的vtable,并且能够在处理常规Windows消息的同时处理各种各样的应用程序的命令消息。
      说白了,MFC中的消息机制其实质是一张巨大的消息及其处理函数的一一对应表,然后加上分析处理这张表的应用框架内部的一些程序代码.这样就可以避免在SDK编程中用到的繁琐的CASE语句。

    MFC的消息映射的基类CCmdTarget
      如果你想让你的控件能够进行消息映射,就必须从CCmdTarget类中派生。CCmdTarget类是MFC处理命令消息的基础、核心。MFC为该类设计了许多成员函数和一些成员数据,基本上是为了解决消息映射问题的,所有响应消息或事件的类都从它派生,例如:应用程序类、框架类、文档类、视图类和各种各样的控件类等等,还有很多。
    不过这个类里面有2个函数对消息映射非常重要,一个是静态成员函数DispatchCmdMsg,另一个是虚函数OnCmdMsg。
    DispatchCmdMsg专门供MFC内部使用,用来分发Windows消息。OnCmdMsg用来传递和发送消息、更新用户界面对象的状态。
    CCmdTarget对OnCmdMsg的默认实现:在当前命令目标(this所指)的类和基类的消息映射数组里搜索指定命令消息的消息处理函数。
      这里使用虚拟函数GetMessageMap得到命令目标类的消息映射入口数组_messageEntries,然后在数组里匹配命令消息ID相同、控制通知代码也相同的消息映射条目。其中GetMessageMap是虚拟函数,所以可以确认当前命令目标的确切类。
    如果找到了一个匹配的消息映射条目,则使用DispachCmdMsg调用这个处理函数;
    如果没有找到,则使用_GetBaseMessageMap得到基类的消息映射数组,查找,直到找到或搜寻了所有的基类(到CCmdTarget)为止;
    如果最后没有找到,则返回FASLE。
      每个从CCmdTarget派生的命令目标类都可以覆盖OnCmdMsg,利用它来确定是否可以处理某条命令,如果不能,就通过调用下一命令目标的 OnCmdMsg,把该命令送给下一个命令目标处理。通常,派生类覆盖OnCmdMsg时,要调用基类的被覆盖的OnCmdMsg。
      在MFC框架中,一些MFC命令目标类覆盖了OnCmdMsg,如框架窗口类覆盖了该函数,实现了MFC的标准命令消息发送路径。必要的话,应用程序也可以覆盖OnCmdMsg,改变一个或多个类中的发送规定,实现与标准框架发送规定不同的发送路径。例如,在以下情况可以作这样的处理:在要打断发送顺序的类中把命令传给一个非MFC默认对象;在新的非默认对象中或在可能要传出命令的命令目标中。

    消息映射的内容
        通过ClassWizard为我们生成的代码,我们可以看到,消息映射基本上分为2大部分:
        在头文件(.h)中有一个宏DECLARE_MESSAGE_MAP(),他被放在了类的末尾,是一个public属性的;与之对应的是在实现部分(.cpp)增加了一章消息映射表,内容如下:
        BEGIN_MESSAGE_MAP(当前类, 当前类的基类)
           //{{AFX_MSG_MAP(CMainFrame)
             消息的入口项
           //}}AFX_MSG_MAP
       END_MESSAGE_MAP()
       但是仅是这两项还远不足以完成一条消息,要是一个消息工作,必须有以下3个部分去协作:
    1.在类的定义中加入相应的函数声明;
    2.在类的消息映射表中加入相应的消息映射入口项;
    3.在类的实现中加入相应的函数体;

    消息的添加
       有了上面的这些只是作为基础,我们接下来就做我们最熟悉、最常用的工作:添加消息。MFC消息的添加主要有2种方法:自动/手动,我们就以这2种方法为例,说一下如何添加消息。
       1、利用Class Wizard实现自动添加
          在菜单中选择View-->Class Wizard,也可以用单击鼠标右键,选择Class Wizard,同样可以激活Class Wizard。选择Message Map标签,从Class name组合框中选取我们想要添加消息的类。在Object IDs列表框中,选取类的名称。此时, Messages列表框显示该类的大多数(若不是全部的话)可重载成员函数和窗口消息。类重载显示在列表的上部,以实际虚构成员函数的大小写字母来表示。其他为窗口消息,以大写字母出现,描述了实际窗口所能响应的消息ID。选中我们向添加的消息,单击Add Function按钮,Class Wizard自动将该消息添加进来。
          有时候,我们想要添加的消息本应该出现在Message列表中,可是就是找不到,怎么办?不要着急,我们可以利用Class Wizard上Class Info标签以扩展消息列表。在该页中,找到Message Filter组合框,通过它可以改变首页中Messages列表框中的选项。这里,我们选择Window,从而显示所有的窗口消息,一把情况下,你想要添加的消息就可以在Message列表框中出现了,如果还没有,那就接着往下看:)

       2、手动地添加消息处理函数
        如果在Messages列表框中仍然看不到我们想要的消息,那么该消息可能是被系统忽略掉或者是你自己创建的,在这种情况下,就必须自己手工添加。根据我们前面所说的消息工作的3个部件,我们一一进行处理:
          1) 在类的. h文件中添加处理函数的声明,紧接在//}}AFX_MSG行之后加入声明,注意:一定要以afx_msg开头。
         通常,添加处理函数声明的最好的地方是源代码中Class Wizard维护的表下面,但是在它标记其领域的{{}}括弧外面。这些括弧中的任何东西都将会被Class Wizard销毁。
          2) 接着,在用户类的.cpp文件中找到//}}AFX_MSG_MAP行,紧接在它之后加入消息入口项。同样,也是放在{ {} }的外面
          3) 最后,在该文件中添加消息处理函数的实体。

    消息范围

    说 明

    0 ~ WM_USER – 1

    系统消息

    WM_USER ~ 0x7FFF

    自定义窗口类整数消息

    WM_APP ~ 0xBFFF

    应用程序自定义消息

    0xC000 ~ 0xFFFF

    应用程序字符串消息

    > 0xFFFF

    为以后系统应用保留

    表A-2  常用Windows消息

    消息名称

    说  明

    WM_NULL 

    0x0000

    空消息,此消息将被接收窗口忽略

    WM_CREATE 

    0x0001

    应用程序创建一个窗口

    WM_DESTROY

    0x0002

    一个窗口被销毁

    WM_MOVE

    0x0003

    移动一个窗口

    WM_SIZE

    0x0005

    改变一个窗口的大小

    WM_ACTIVATE

    0x0006

    一个窗口被激活或失去激活状态

    WM_SETFOCUS

    0x0007

    获得焦点后

    WM_KILLFOCUS

    0x0008

    失去焦点

    WM_ENABLE

    0x000A

    应用程序Enable状态改变时产生

    WM_SETREDRAW

    0x000B

    设置窗口是否能重画

    WM_SETTEXT

    0x000C

    应用程序发送此消息来设置一个窗口的文本

    WM_GETTEXT

    0x000D

    应用程序发送此消息来复制对应窗口的文本到缓冲区

    WM_GETTEXTLENGTH

    0x000E

    得到与一个窗口有关的文本的长度(不包含空字符)

    WM_PAINT

    0x000F

    要求一个窗口重绘自己

    WM_CLOSE

    0x0010

    当一个窗口或应用程序要关闭时发送一个信号

    WM_QUERYENDSESSION

    0x0011

    用户选择结束对话框或应用程序自己调用ExitWindows()函数

    WM_QUIT

    0x0012

    用来结束程序运行或应用程序调用Postquitmessage()函数来产生此消息

    WM_QUERYOPEN

    0x0013

    当用户窗口恢复以前的大小位置时,把此消息发送给某个图标

    WM_ERASEBKGND

    0x0014

    当窗口背景必须被擦除时(例如在窗口改变大小时)

    WM_SYSCOLORCHANGE

    0x0015

    当系统颜色改变时,发送此消息给所有顶级窗口

    WM_ENDSESSION

    0x0016

    当系统进程发出WM_QUERYENDSESSION消息后,此消息发送给应用程序

    WM_SHOWWINDOW

    0x0018

    当隐藏或显示窗口是发送此消息给这个窗口

    WM_ACTIVATEAPP

    0x001C

    当某个窗口将被激活时,将被激活窗口和当前活动(即将失去激活)窗口会收到此消息,发此消息给应用程序哪个窗口是激活的,哪个是非激活的

    WM_FONTCHANGE

    0x001D

    当系统的字体资源库变化时发送此消息给所有顶级窗口

    WM_TIMECHANGE

    0x001E

    当系统的时间变化时发送此消息给所有顶级窗口

    WM_CANCELMODE

    0x001F

    发送此消息来取消某种正在进行的操作

    WM_SETCURSOR

    0x0020

    如果鼠标引起光标在某个窗口中移动且鼠标输入没有被捕获时,发消息给该窗口

    WM_MOUSEACTIVATE

    0x0021

    当光标在某个非激活的窗口中而用户正按着鼠标的某个键发送此消息给当前窗口

    WM_CHILDACTIVATE

    0x0022

    发送此消息给MDI子窗口当用户点击此窗口的标题栏,或当窗口被激活、移动、改变大小

    WM_QUEUESYNC

    0x0023

    此消息由基于计算机的训练程序发送,通过WH_JOURNALPALYBACK的Hook程序分离出用户输入消息

    WM_GETMINMAXINFO

    0x0024

    当窗口要将要改变大小或位置时,发送此消息给该窗口

    WM_PAINTICON

    0x0026

    当窗口图标将要被重绘时,发送此消息给该窗口

    WM_ICONERASEBKGND

    0x0027

    在一个最小化窗口的图标在重绘前,当图标背景必须被重绘时,发送此消息给该窗口

    WM_NEXTDLGCTL

    0x0028

    发送此消息给一个对话框程序以更改焦点位置

    WM_SPOOLERSTATUS

    0x002A

    当打印管理列队增加或减少一条作业时发出此消息

    WM_DRAWITEM

    0x002B

    当Button,ComboBox,Listbox,Menu控件的外观改变时,发送此消息给这些控件的所有者

    WM_MEASUREITEM

    0x002C

    当Button,ComboBox,list box,ListView,Menu 项被创建时,发送此消息给控件的所有者

    WM_DELETEITEM

    0x002D

    当ListBox 或 ComboBox 被销毁或当某些项通过发送LB_DELETESTRING、LB_RESETCONTENT、 CB_DELETESTRING、CB_RESETCONTENT 消息被删除时,发送此消息给控件的所有者

    WM_VKEYTOITEM

    0x002E

    一个具有LBS_WANTKEYBOARDINPUT风格的ListBox控件发送此消息给它的所有者,以此来响应WM_KEYDOWN消息

    WM_CHARTOITEM

    0x002F

    一个具有LBS_WANTKEYBOARDINPUT风格的ListBox控件发送此消息给它的所有者,以此来响应WM_CHAR消息

    WM_SETFONT

    0x0030

    应用程序绘制控件时,发送此消息得到以何种字体绘制控件中的文本

    WM_GETFONT

    0x0031

    应用程序发送此消息得到当前控件绘制文本的字体

    WM_SETHOTKEY

    0x0032

    应用程序发送此消息让一个窗口与一个热键相关联

    WM_GETHOTKEY

    0x0033

    应用程序发送此消息来判断热键与某个窗口是否有关联

    WM_QUERYDRAGICON

    0x0037

    此消息发送给最小化窗口,当此窗口将要被拖放而它的类中没有定义图标,应用程序就返回一个图标或光标的句柄,当用户拖放图标时系统显示这个图标或光标

    WM_COMPAREITEM

    0x0039

    发送此消息来判定ComboBox或ListBox新增加的项的相对位置

    WM_COMPACTING

    0x0041

    显示内存已经很少了

    WM_WINDOWPOSCHANGING

    0x0046

    当调用SetWindowPos()函数改变窗口的大小和位置后,发送此消息给该窗口

    WM_POWER

    0x0048

    当系统将进入挂起状态时发送此消息给所有进程

    WM_COPYDATA

    0x004A

    当一个应用程序传递数据给另一个应用程序时发送此消息

    WM_CANCELJOURNAL

    0x004B

    当某个用户取消程序日志激活状态,发送此消息给应用程序

    WM_NOTIFY

    0x004E

    当某个控件的某个事件已经发生或这个控件需要得到一些信息时,发送此消息给它的父窗口

    WM_INPUTLANGCHANGEREQUEST

    0x0050

    当用户选择某种输入语言,或输入语言的热键改变

    WM_INPUTLANGCHANGE

    0x0051

    当应用程序输入语言改变后发送此消息给受影响的最顶级窗口

    WM_TCARD

    0x0052

    当应用程序已经初始化Windows帮助例程时发送此消息给应用程序

    WM_HELP

    0x0053

    当用户按下了F1,如果某个菜单是激活的,就发送此消息给此窗口关联的菜单,否则就发送给有焦点的窗口,如果当前都没有焦点,就把此消息发送给当前激活的窗口

    WM_USERCHANGED

    0x0054

    当用户已经登录或退出后发送此消息给所有的窗口,当用户登录或退出时系统更新用户的具体设置信息,在用户更新设置时系统马上发送此消息

    WM_NOTIFYFORMAT

    0x0055

    公用控件和它们的父窗口通过此消息来判断在WM_NOTIFY消息中是使用ANSI还是UNICODE形式的结构,使用此控件能使某个控件与它的父控件进行相互通信

    WM_CONTEXTMENU

    0x007B

    当用户在某个窗口中点击右键,则发送此消息给该窗口

    WM_STYLECHANGING

    0x007C

    当将要调用SetWindowLong()函数窗口的一个或多个风格时,发送此消息给该窗口

    WM_STYLECHANGED

    0x007D

    当调用SetWindowLong()函数改变了窗口的一个或多个风格后,发送此消息给该窗口

    WM_DISPLAYCHANGE

    0x007E

    当显示器的分辨率改变后发送此消息给所有的窗口

    WM_GETICON

    0x007F

    发送此消息给某个窗口,返回与某个窗口有关联的大图标或小图标的句柄

    WM_SETICON

    0x0080

    应用程序发送此消息让一个新的大图标或小图标与某个窗口关联

    WM_NCCREATE

    0x0081

    当某个窗口第一次被创建时,此消息在WM_CREATE消息被发送前发送

    WM_NCDESTROY

    0x0082

    此消息通知某个窗口,正在销毁非客户区

    WM_NCCALCSIZE

    0x0083

    当计算某个窗口的客户区大小和位置时发送此消息

    WM_NCHITTEST

    0x0084

    移动鼠标,按住或释放鼠标时产生此消息

    WM_NCPAINT

    0x0085

    当某个窗口的框架必须被绘制时,应用程序发送此消息给该窗口

    WM_NCACTIVATE

    0x0086

    通过改变某个窗口的非客户区来表示窗口是处于激活还是非激活状态时,此消息被发送给该窗口

    WM_NCMOUSEMOVE

    0x00A0

    当光标在窗口的非客户区(窗口标题栏及边框)内移动时发送此消息给该窗口

    WM_NCLBUTTONDOWN

    0x00A1

    当光标在窗口的非客户区并按下鼠标左键时发送此消息

    WM_NCLBUTTONUP

    0x00A2

    当光标在窗口的非客户区并释放鼠标左键时发送此消息

    WM_NCLBUTTONDBLCLK

    0x00A3

    当光标在窗口的非客户区并双击鼠标左键时发送此消息

    WM_NCRBUTTONDOWN

    0x00A4

    当光标在窗口的非客户区并按下鼠标右键时发送此消息

    WM_NCRBUTTONUP

    0x00A5

    当光标在窗口的非客户区并释放鼠标右键时发送此消息

    WM_NCRBUTTONDBLCLK

    0x00A6

    当光标在窗口的非客户区并双击鼠标右键时发送此消息

    WM_NCMBUTTONDOWN

    0x00A7

    当光标在窗口的非客户区并按下鼠标中键时发送此消息

    WM_NCMBUTTONUP

    0x00A8

    当光标在窗口的非客户区并释放鼠标中键时发送此消息

    WM_NCMBUTTONDBLCL

    0x00A9

    当光标在窗口的非客户区并双击鼠标中键时发送此消息

    WM_KEYDOWN

    0x0100

    按下一个非系统键(按下键时未按下“ALT”键)

    WM_KEYUP

    0x0101

    释放一个非系统键

    WM_CHAR

    0x0102

    按下某键,当TranslateMessage()转发WM_KEYDOWN后发送本消息

    WM_DEADCHAR

    0x0103

    释放某键,当TranslateMessage()转发WM_KEYUP后发送本消息

    WM_SYSKEYDOWN

    0x0104

    当按住ALT键同时按下其他键时发送此消息给拥有键盘焦点的窗口

    WM_SYSKEYUP

    0x0105

    当释放一个键同时按住ALT键时发送此消息给拥有键盘焦点的窗口

    WM_SYSCHAR

    0x0106

    当TranslateMessage()转发WM_SYSKEYDOWN后发送此消息给拥有键盘焦点的窗口

    WM_SYSDEADCHAR

    0x0107

    当TranslateMessage()转发WM_SYSKEYUP后发送此消息给拥有键盘焦点的窗口

    WM_INITDIALOG

    0x0110

    在被显示前发送此消息对话框,通常用此消息初始化控件和执行其他任务

    WM_COMMAND

    0x0111

    选择窗口菜单项或某个控件发送一条消息给它的父窗口或按下一个快捷键时产生此消息

    WM_SYSCOMMAND

    0x0112

    选择窗口菜单项或选择最大化或最小化时,发送此消息给该窗口

    WM_TIMER

    0x0113

    发生了定时器事件

    WM_HSCROLL

    0x0114

    当窗口水平滚动条产生一个滚动事件时发送此消息给该窗口和滚动条的所有者

    WM_VSCROLL

    0x0115

    当窗口垂直滚动条产生一个滚动事件时发送此消息给该窗口和滚动条的所有者

    WM_INITMENU

    0x0116

    当一个菜单将要被激活时发送此消息,它发生在按下菜单项或按下菜单快捷键时,它允许程序在显示前更改菜单

    WM_INITMENUPOPUP

    0x0117

    当一个下拉菜单或子菜单将要被激活时发送此消息,它允许显示前在修改菜单而不必更改整个菜单

    WM_MENUSELECT

    0x011F

    选择一条菜单项时发送此消息给菜单的所有者(一般是窗口)

    WM_MENUCHAR

    0x0120

    当菜单已被激活且用户按下了某个键(非快捷键),发送此消息给菜单的所有者

    WM_ENTERIDLE

    0x0121

    当一个有模式对话框或菜单进入空闲状态时发送此消息给它的所有者,空闲状态指在处理完一条或几条先前的消息后,消息列队为空

    WM_MENURBUTTONUP

    0x0122

    当光标位于菜单项上时,释放鼠标右键产生此消息

    WM_MENUDRAG

    0x0123

    当拖动菜单项时,发送此消息给拖放菜单的所有者

    WM_MENUGETOBJECT

    0x0124

    当光标移入菜单项或者从菜单项中心移到菜单项顶部或底部时,发送此消息给拖放菜单的所有者

    WM_UNINITMENUPOPUP

    0x0125

    当下拉菜单或者子菜单被销毁时产生此消息

    WM_MENUCOMMAND

    0x0126

    当用户选择菜单项时产生此消息

    WM_CHANGEUISTATE

    0x0127

    应用程序发送此消息表明用户界面(UI)状态应当被改变

    WM_UPDATEUISTATE

    0x0128

    应用程序发送此消息改变指定窗口及其子窗口的用户界面(UI)状态

    WM_QUERYUISTATE

    0x0129

    应用程序发送此消息得到某个窗口的用户界面(UI)状态

    WM_CTLCOLORMSGBOX

    0x0132

    绘制消息框前发送此消息给它的父窗口,通过响应这条消息,父窗口可以通过使用给定的相关显示设备的句柄来设置消息框的文本和背景颜色

    WM_CTLCOLOREDIT

    0x0133

    绘制编辑型控件前发送此消息给它的父窗口,可用来设置编辑框的文本和背景颜色

    WM_CTLCOLORLISTBOX

    0x0134

    绘制列表框控件前发送此消息给它的父窗口,可用来设置编辑框的文本和背景颜色

    WM_CTLCOLORBTN

    0x0135

    绘制按钮控件前发送此消息给它的父窗口,可用来设置编辑框的文本和背景颜色

    WM_CTLCOLORDLG

    0x0136

    绘制对话框前发送此消息给它的父窗口,可用来设置编辑框的文本和背景颜色

    WM_CTLCOLORSCROLLBAR

    0x0137

    绘制滚动条控件前发送此消息给它的父窗口,可用来设置滚动条控件的文本和背景颜色

    WM_CTLCOLORSTATIC

    0x0138

    绘制静态控件前发送此消息给它的父窗口,可用来设置静态控件的文本和背景颜色

    WM_MOUSEMOVE

    0x0200

    鼠标移动

    WM_LBUTTONDOWN

    0x0201

    按下鼠标左键

    WM_LBUTTONUP

    0x0202

    释放鼠标左键

    WM_LBUTTONDBLCLK

    0x0203

    双击鼠标左键

    WM_RBUTTONDOWN

    0x0204

    按下鼠标右键

    WM_RBUTTONUP

    0x0205

    释放鼠标右键

    WM_RBUTTONDBLCLK

    0x0206

    双击鼠标右键

    WM_MBUTTONDOWN

    0x0207

    按下鼠标中键

    WM_MBUTTONUP

    0x0208

    释放鼠标中键

    WM_MBUTTONDBLCLK

    0x0209

    双击鼠标中键

    WM_MOUSEWHEEL

    0x020A

    当鼠标滚轮转动时发送此消息给当前获得焦点的窗口

    WM_PARENTNOTIFY

    0x0210

    当MDI子窗口被创建或被销毁,或当光标位于子窗口上且用户按了一下鼠标键时,发送此消息给它的父窗口

    WM_ENTERMENULOOP

    0x0211

    发送此消息通知应用程序的主窗口进程已经进入了菜单模式循环

    WM_EXITMENULOOP

    0x0212

    发送此消息通知应用程序的主窗口进程已经退出了菜单模式循环

    WM_SIZING

    0x0214

    调整窗口大小时发送此消息给窗口,通过此消息应用程序可以监视或修改窗口大小和位置

    WM_CAPTURECHANGED

    0x0215

    当窗口设定为不捕获鼠标事件时,发送此消息给该窗口

    WM_MOVING

    0x0216

    移动窗口时发送此消息给窗口,通过此消息应用程序可以监视或修改窗口大小和位置

    WM_POWERBROADCAST

    0x0218

    发送此消息给应用程序通知它有关电源管理事件

    WM_DEVICECHANGE

    0x0219

    当设备的硬件配置改变时发送此消息给应用程序或设备驱动程序

    WM_MDICREATE

    0x0220

    应用程序发送此消息给多文档的客户窗口来创建一个MDI 子窗口

    WM_MDIDESTROY

    0x0221

    应用程序发送此消息给多文档的客户窗口来关闭一个MDI 子窗口

    WM_MDIACTIVATE

    0x0222

    应用程序发送此消息给多文档的客户窗口通知客户窗口激活另一个MDI子窗口,当客户窗口收到此消息后,它发出WM_MDIACTIVE消息给MDI子窗口(未激活)来激活它

    WM_MDIRESTORE

    0x0223

    应用程序发送此消息给MDI客户窗口通知子窗口恢复到原来大小

    WM_MDINEXT

    0x0224

    应用程序发送此消息给MDI客户窗口激活下一个或前一个窗口

    WM_MDIMAXIMIZE

    0x0225

    应用程序发送此消息给MDI客户窗口以最大化一个MDI子窗口

    WM_MDITILE

    0x0226

    应用程序发送此消息给MDI客户窗口以平铺方式重新排列所有MDI子窗口

    WM_MDICASCADE

    0x0227

    应用程序发送此消息给MDI客户窗口以层叠方式重新排列所有MDI子窗口

    WM_MDIICONARRANGE

    0x0228

    应用程序发送此消息给MDI客户窗口重新排列所有最小化的MDI子窗口

    WM_MDIGETACTIVE

    0x0229

    应用程序发送此消息给MDI客户窗口以找到激活的子窗口的句柄

    WM_MDISETMENU

    0x0230

    应用程序发送此消息给MDI客户窗口用MDI菜单代替子窗口的菜单

    WM_ENTERSIZEMOVE

    0x0231

    当窗口进入移动或改变大小模式循环时,发送此消息给该窗口

    WM_EXITSIZEMOVE

    0x0232

    当窗口退出移动或改变大小模式循环时,发送此消息给该窗口

    WM_DROPFILES

    0x0233

    当用户在应用程序窗口中拖动某个文件时,产生此消息

    WM_MDIREFRESHMENU

    0x0234

    应用程序发送此消息给MDI客户窗口以刷新窗口菜单

    WM_MOUSEHOVER

    0x02A1

    当光标在窗口客户区悬停超过TrackMouseEvent()指定的时间时,发送此消息给该窗口

    WM_MOUSELEAVE

    0x02A3

    当光标离开窗口客户区超过TrackMouseEvent()指定的时间时,发送此消息给该窗口

    WM_CUT

    0x0300

    应用程序发送此消息给一个编辑框或ComboBox以删除当前选择的文本

    WM_COPY

    0x0301

    应用程序发送此消息给一个编辑框或ComboBox以复制当前选择的文本到剪贴板

    WM_PASTE 

    0x0302

    应用程序发送此消息给一个编辑框或ComboBox以从剪贴板中得到数据

    WM_CLEAR

    0x0303

    应用程序发送此消息给一个编辑框或ComboBox以清除当前选择的内容

    WM_UNDO

    0x0304

    应用程序发送此消息给一个编辑框或ComboBox以撤消最后一次操作

    WM_DESTROYCLIPBOARD

    0x0307

    当调用EmptyClipboard()清空剪贴板时,发送此消息给剪贴板所有者

    WM_DRAWCLIPBOARD

    0x0308

    当剪贴板的内容变化时发送此消息给剪贴板观察链中的第一个窗口,它允许用剪贴板观察窗口来显示剪贴板的新内容

    WM_PAINTCLIPBOARD

    0x0309

    当剪贴板包含CF_OWNERDIPLAY格式的数据且剪贴板观察窗口的客户区需要重绘时,发送此消息给剪贴板所有者

    WM_VSCROLLCLIPBOARD

    0x030A

    当剪贴板包含CF_OWNERDIPLAY格式的数据且剪贴板观察窗口发生垂直滚动条事件时,剪贴板观察窗口发送此消息给剪贴板所有者

    WM_SIZECLIPBOARD

    0x030B

    当剪贴板包含CF_OWNERDIPLAY格式的数据且剪贴板观察窗口的客户区域的大小已经改变时,剪贴板观察窗口发送此消息给剪贴板的所有者

    WM_ASKCBFORMATNAME

    0x030C

    剪贴板观察窗口发送此消息给剪贴板所有者以获得CF_OWNERDISPLAY剪贴板格式的名字

    WM_CHANGECBCHAIN

    0x030D

    当一个窗口从剪贴板观察链中移去时发送此消息给剪贴板观察链中的第一个窗口

    WM_HSCROLLCLIPBOARD

    0x030E

    当剪贴板包含CF_OWNERDIPLAY格式的数据且剪贴板观察窗口发生水平滚动条事件时,剪贴板观察窗口发送此消息给剪贴板所有者

    WM_QUERYNEWPALETTE

    0x030F

    发送此消息给将要获得键盘焦点的窗口,此消息使窗口在获得焦点时同时有机会实现它的逻辑调色板

    WM_PALETTEISCHANGING

    0x0310

    应用程序将要实现它的逻辑调色板时发送此消息通知所有应用程序

    WM_PALETTECHANGED

    0x0311

    获得焦点的窗口实现它的逻辑调色板后发送此消息给所有顶级并重叠的窗口,以此

    来改变系统调色板

    WM_HOTKEY

    0x0312

    当用户按下由RegisterHotKey()注册的热键时产生此消息

    WM_PRINT

    0x0317

    应用程序发送此消息给窗口,要求窗口在指定设备环境中绘制自己,一般情况下是打印机设备环境

    WM_PRINTCLIENT

    0x0318

    应用程序发送此消息给窗口,要求窗口在指定设备环境中绘制窗口客户区,一般情况下是打印机设备环境

    WM_APP

    0x8000

    帮助用户自定义消息,自定义消息可以为WM_APP+X,X为正整数

    WM_USER

    0x0400

    帮助用户自定义消息,自定义消息可以为WM_USER+X,X为正整数

      表A-3  通知消息-按钮

    消息名称

    说 明

    BN_CLICKED

    单击按钮

    BN_DISABLE

    按钮被禁止

    BN_DOUBLECLICKED

    双击按钮

    BN_HILITE

    加亮按钮

    BN_PAINT

    按钮应当重画

    BN_UNHILITE

    加亮应当去掉

    表A-4  通知消息-组合框

    消息名称

    说 明

    CBN_CLOSEUP

    组合框的列表框被关闭

    CBN_DBLCLK

    用户双击了一个字符串

    CBN_DROPDOWN

    组合框的列表框被拉下

    CBN_EDITCHANGE

    用户修改了组合框中的文本

    CBN_EDITUPDATE

    组合框内的文本即将更新

    CBN_ERRSPACE

    组合框内存不足

    CBN_KILLFOCUS

    组合框失去输入焦点

    CBN_SELCHANGE

    在组合框中选择了一项

    CBN_SELENDCANCEL

    用户的选择将被忽略

    CBN_SELENDOK

    用户的选择将被执行

    CBN_SETFOCUS

    组合框获得输入焦点

    表A-5  通知消息-编辑框

    消息名称

    说 明

    EN_CHANGE

    编辑框中的文本己更新

    EN_ERRSPACE

    编辑框内存不足

    EN_HSCROLL

    用户点击了水平滚动条

    EN_KILLFOCUS

    编辑框失去输入焦点

    EN_MAXTEXT

    插入的内容被截断

    EN_SETFOCUS

    编辑框获得输入焦点

    EN_UPDATE

    编辑框中的文本将要更新

    EN_VSCROLL

    用户点击了垂直滚动条

    表A-6  通知消息-列表框

    消息名称

    说 明

    LBN_DBLCLK

    用户双击了一项

    LBN_ERRSPACE

    列表框内存不足

    LBN_KILLFOCUS

    列表框正在失去输入焦点

    LBN_SELCANCEL

    用户选择被取消

    LBN_SELCHANGE

    用户选择将改变

    LBN_SETFOCUS

    列表框获得输入焦点

    Windows消息大全

      Windows是一消息(Message)驱动式系统,Windows消息提供了应用程序与应用程序之间、应用程序与Windows系统之间进行通讯的手段。应用程序要实现的功能由消息来触发,并靠对消息的响应和处理来完成。Windows系统中有两种消息队列,一种是系统消息队列,另一种是应用程序消息队列。计算机的所有输入设备由 Windows监控,当一个事件发生时,Windows先将输入的消息放入系统消息队列中,然后再将输入的消息拷贝到相应的应用程序队列中,应用程序中的消息循环从它的消息队列中检索每一个消息并发送给相应的窗口函数中。一个事件的发生,到达处理它的窗口函数必须经历上述过程。值得注意的是消息的非抢先性,即不论事件的急与缓,总是按到达的先后排队(一些系统消息除外),这就使得一些外部实时事件可能得不到及时的处理。

      由于Windows本身是由消息驱动的,举一个例子来说明这个问题。打开记事本程序,该程序有一个File菜单,那么,在运行该应用程序的时候,如果用户单击了File菜单里New命令时,这个动作将被Windows (而不是应用程序本身!)所捕获,Windows经过分析得知这个动作应该由上面所说的那个应用程序去处理,既然是这样,Windows就发送了个叫做WM_COMMAND的消息给应用程序,该消息所包含信息告诉应用程序:"用户单击了New菜单",应用程序得知这一消息之后,采取相应的动作来响应它,这个过程称为消息处理。Windows为每一个应用程序(确切地说是每一个线程)维护了相应的消息队列,应用程序的任务就是不停的从它的消息队列中获取消息,分析消息和处理消息,直到一条接到叫做WM_QUIT消息为止,这个过程通常是由一种叫做消息循环的程序结构来实现的。

      消息本身是作为一个记录传递给应用程序的,这个记录中包含了消息的类型以及其他信息。例如,对于单击鼠标所产生的消息来说,这个记录中包含了单击鼠标时的坐标。这个记录类型叫做T M s g,它在Wi n d o w s单元中是这样声明的:

    type

    TMsg = packedrecord

    hwnd: HWND / /窗口句柄

    message: UINT / /消息常量标识符

    wParam: WPA R AM  // 32位消息的特定附加信息

    lParam: LPA R AM  // 32位消息的特定附加信息

    time: DWORD / /消息创建时的时间

    pt: TPoint / /消息创建时的鼠标位置

    end

    消息中有什么?

    是否觉得一个消息记录中的信息像希腊语一样?如果是这样,那么看一看下面的解释:

    hwnd 32位的窗口句柄。窗口可以是任何类型的屏幕对象,因为Win32能够维护大多数可视对象的句柄(窗口、对话框、按钮、编辑框等)。

    message 用于区别其他消息的常量值,这些常量可以是Windows单元中预定义的常量,也可以是自定义的常量。

    wParam 通常是一个与消息有关的常量值,也可能是窗口或控件的句柄。

    lParam 通常是一个指向内存中数据的指针。由于WParm、lParam和Pointer都是32位的,因此,它们之间可以相互转换。

    WM_NULL = 0

    WM_CREATE = 1

    应用程序创建一个窗口

    WM_DESTROY = 2

    一个窗口被销毁

    WM_MOVE = 3

    移动一个窗口

    WM_SIZE = 5

    改变一个窗口的大小

    WM_ACTIVATE = 6

    一个窗口被激活或失去激活状态;

    WM_SETFOCUS = 7

    获得焦点后

    WM_KILLFOCUS = 8

    失去焦点

    WM_ENABLE = 10

    改变enable状态

    WM_SETREDRAW = 11

    设置窗口是否能重画

    WM_SETTEXT = 12

    应用程序发送此消息来设置一个窗口的文本

    WM_GETTEXT = 13

    应用程序发送此消息来复制对应窗口的文本到缓冲区

    WM_GETTEXTLENGTH =14

    得到与一个窗口有关的文本的长度(不包含空字符)

    WM_PAINT = 15

    要求一个窗口重画自己

    WM_CLOSE = 16

    当一个窗口或应用程序要关闭时发送一个信号

    WM_QUERYENDSESSION= 17

    当用户选择结束对话框或程序自己调用ExitWindows函数

    WM_QUIT = 18

    用来结束程序运行或当程序调用postquitmessage函数

    WM_QUERYOPEN = 19

    当用户窗口恢复以前的大小位置时,把此消息发送给某个图标

    WM_ERASEBKGND = 20

    当窗口背景必须被擦除时(例在窗口改变大小时)

    WM_SYSCOLORCHANGE =21

    当系统颜色改变时,发送此消息给所有顶级窗口

    WM_ENDSESSION = 22

    当系统进程发出WM_QUERYENDSESSION消息后,此消息发送给应用程序,

    通知它对话是否结束

    WM_SYSTEMERROR = 23

    WM_SHOWWINDOW = 24

    当隐藏或显示窗口是发送此消息给这个窗口

    WM_ACTIVATEAPP = 28

    发此消息给应用程序哪个窗口是激活的,哪个是非激活的;

    WM_FONTCHANGE = 29

    当系统的字体资源库变化时发送此消息给所有顶级窗口

    WM_TIMECHANGE = 30

    当系统的时间变化时发送此消息给所有顶级窗口

    WM_CANCELMODE = 31

    发送此消息来取消某种正在进行的摸态(操作)

    WM_SETCURSOR = 32

    如果鼠标引起光标在某个窗口中移动且鼠标输入没有被捕获时,就发消息给某个窗口

    WM_MOUSEACTIVATE =33

    当光标在某个非激活的窗口中而用户正按着鼠标的某个键发送此消息给当前窗口

    WM_CHILDACTIVATE =34

    发送此消息给MDI子窗口当用户点击此窗口的标题栏,或当窗口被激活,移动,改变大小

    WM_QUEUESYNC = 35

    此消息由基于计算机的训练程序发送,通过WH_JOURNALPALYBACK的hook程序

    分离出用户输入消息

    WM_GETMINMAXINFO =36

    此消息发送给窗口当它将要改变大小或位置;

    WM_PAINTICON = 38

    发送给最小化窗口当它图标将要被重画

    WM_ICONERASEBKGND =39

    此消息发送给某个最小化窗口,仅当它在画图标前它的背景必须被重画

    WM_NEXTDLGCTL = 40

    发送此消息给一个对话框程序去更改焦点位置

    WM_SPOOLERSTATUS =42

    每当打印管理列队增加或减少一条作业时发出此消息

    WM_DRAWITEM = 43

    当button,combobox,listbox,menu的可视外观改变时发送

    此消息给这些空件的所有者

    WM_MEASUREITEM = 44

    当button, combo box, list box, list view control, or menu item 被创建时

    发送此消息给控件的所有者

    WM_DELETEITEM = 45

    当the list box 或 combo box 被销毁 或 当 某些项被删除通过LB_DELETESTRING,LB_RESETCONTENT, CB_DELETESTRING, or CB_RESETCONTENT 消息

    WM_VKEYTOITEM = 46

    此消息有一个LBS_WANTKEYBOARDINPUT风格的发出给它的所有者来响应WM_KEYDOWN消息

    WM_CHARTOITEM = 47

    此消息由一个LBS_WANTKEYBOARDINPUT风格的列表框发送给他的所有者来响应WM_CHAR消息

    WM_SETFONT = 48

    当绘制文本时程序发送此消息得到控件要用的颜色

    WM_GETFONT = 49

    应用程序发送此消息得到当前控件绘制文本的字体

    WM_SETHOTKEY = 50

    应用程序发送此消息让一个窗口与一个热键相关连

    WM_GETHOTKEY = 51

    应用程序发送此消息来判断热键与某个窗口是否有关联

    WM_QUERYDRAGICON =55

    此消息发送给最小化窗口,当此窗口将要被拖放而它的类中没有定义图标,应用程序能

    返回一个图标或光标的句柄,当用户拖放图标时系统显示这个图标或光标

    WM_COMPAREITEM = 57

    发送此消息来判定combobox或listbox新增加的项的相对位置

    WM_GETOBJECT = 61

    WM_COMPACTING = 65

    显示内存已经很少了

    WM_WINDOWPOSCHANGING= 70

    发送此消息给那个窗口的大小和位置将要被改变时,来调用setwindowpos函数或其它窗口管理函数

    WM_WINDOWPOSCHANGED= 71

    发送此消息给那个窗口的大小和位置已经被改变时,来调用setwindowpos函数或其它窗口管理函数

    WM_POWER = 72(适用于16位的windows)

    当系统将要进入暂停状态时发送此消息

    WM_COPYDATA = 74

    当一个应用程序传递数据给另一个应用程序时发送此消息

    WM_CANCELJOURNAL =75

    当某个用户取消程序日志激活状态,提交此消息给程序

    WM_NOTIFY = 78

    当某个控件的某个事件已经发生或这个控件需要得到一些信息时,发送此消息给它的父窗口

    WM_INPUTLANGCHANGEREQUEST= 80

    当用户选择某种输入语言,或输入语言的热键改变

    WM_INPUTLANGCHANGE= 81

    当平台现场已经被改变后发送此消息给受影响的最顶级窗口

    WM_TCARD = 82

    当程序已经初始化windows帮助例程时发送此消息给应用程序

    WM_HELP = 83

    此消息显示用户按下了F1,如果某个菜单是激活的,就发送此消息个此窗口关联的菜单,否则就

    发送给有焦点的窗口,如果当前都没有焦点,就把此消息发送给当前激活的窗口

    WM_USERCHANGED = 84

    当用户已经登入或退出后发送此消息给所有的窗口,当用户登入或退出时系统更新用户的具体

    设置信息,在用户更新设置时系统马上发送此消息;

    WM_NOTIFYFORMAT =85

    公用控件,自定义控件和他们的父窗口通过此消息来判断控件是使用ANSI还是UNICODE结构

    在WM_NOTIFY消息,使用此控件能使某个控件与它的父控件之间进行相互通信

    WM_CONTEXTMENU =123

    当用户某个窗口中点击了一下右键就发送此消息给这个窗口

    WM_STYLECHANGING =124

    当调用SETWINDOWLONG函数将要改变一个或多个 窗口的风格时发送此消息给那个窗口

    WM_STYLECHANGED =125

    当调用SETWINDOWLONG函数一个或多个 窗口的风格后发送此消息给那个窗口

    WM_DISPLAYCHANGE =126

    当显示器的分辨率改变后发送此消息给所有的窗口

    WM_GETICON = 127

    此消息发送给某个窗口来返回与某个窗口有关连的大图标或小图标的句柄;

    WM_SETICON = 128

    程序发送此消息让一个新的大图标或小图标与某个窗口关联;

    WM_NCCREATE = 129

    当某个窗口第一次被创建时,此消息在WM_CREATE消息发送前发送;

    WM_NCDESTROY = 130

    此消息通知某个窗口,非客户区正在销毁

    WM_NCCALCSIZE = 131

    当某个窗口的客户区域必须被核算时发送此消息

    WM_NCHITTEST =132//移动鼠标,按住或释放鼠标时发生

    WM_NCPAINT = 133

    程序发送此消息给某个窗口当它(窗口)的框架必须被绘制时;

    WM_NCACTIVATE = 134

    此消息发送给某个窗口仅当它的非客户区需要被改变来显示是激活还是非激活状态;

    WM_GETDLGCODE = 135

    发送此消息给某个与对话框程序关联的控件,widdows控制方位键和TAB键使输入进入此控件

    通过响应WM_GETDLGCODE消息,应用程序可以把他当成一个特殊的输入控件并能处理它

    WM_NCMOUSEMOVE =160

    当光标在一个窗口的非客户区内移动时发送此消息给这个窗口 //非客户区为:窗体的标题栏及窗

    的边框体

    WM_NCLBUTTONDOWN =161

    当光标在一个窗口的非客户区同时按下鼠标左键时提交此消息

    WM_NCLBUTTONUP =162

    当用户释放鼠标左键同时光标某个窗口在非客户区十发送此消息;

    WM_NCLBUTTONDBLCLK= 163

    当用户双击鼠标左键同时光标某个窗口在非客户区十发送此消息

    WM_NCRBUTTONDOWN =164

    当用户按下鼠标右键同时光标又在窗口的非客户区时发送此消息

    WM_NCRBUTTONUP =165

    当用户释放鼠标右键同时光标又在窗口的非客户区时发送此消息

    WM_NCRBUTTONDBLCLK= 166

    当用户双击鼠标右键同时光标某个窗口在非客户区十发送此消息

    WM_NCMBUTTONDOWN =167

    当用户按下鼠标中键同时光标又在窗口的非客户区时发送此消息

    WM_NCMBUTTONUP =168

    当用户释放鼠标中键同时光标又在窗口的非客户区时发送此消息

    WM_NCMBUTTONDBLCLK= 169

    当用户双击鼠标中键同时光标又在窗口的非客户区时发送此消息

    WM_KEYFIRST = 256

    WM_KEYDOWN = 256

    //按下一个键

    WM_KEYUP = 257

    //释放一个键

    WM_CHAR = 258

    //按下某键,并已发出WM_KEYDOWN, WM_KEYUP消息

    WM_DEADCHAR = 259

    当用translatemessage函数翻译WM_KEYUP消息时发送此消息给拥有焦点的窗口

    WM_SYSKEYDOWN = 260

    当用户按住ALT键同时按下其它键时提交此消息给拥有焦点的窗口;

    WM_SYSKEYUP = 261

    当用户释放一个键同时ALT 键还按着时提交此消息给拥有焦点的窗口

    WM_SYSCHAR = 262

    当WM_SYSKEYDOWN消息被TRANSLATEMESSAGE函数翻译后提交此消息给拥有焦点的窗口

    WM_SYSDEADCHAR =263

    当WM_SYSKEYDOWN消息被TRANSLATEMESSAGE函数翻译后发送此消息给拥有焦点的窗口

    WM_KEYLAST = 264

    WM_INITDIALOG = 272

    在一个对话框程序被显示前发送此消息给它,通常用此消息初始化控件和执行其它任务

    WM_COMMAND = 273

    当用户选择一条菜单命令项或当某个控件发送一条消息给它的父窗口,一个快捷键被翻译

    WM_SYSCOMMAND = 274

    当用户选择窗口菜单的一条命令或当用户选择最大化或最小化时那个窗口会收到此消息

    WM_TIMER = 275 //发生了定时器事件

    WM_HSCROLL = 276

    当一个窗口标准水平滚动条产生一个滚动事件时发送此消息给那个窗口,也发送给拥有它的控件

    WM_VSCROLL = 277

    当一个窗口标准垂直滚动条产生一个滚动事件时发送此消息给那个窗口也,发送给拥有它的控件 WM_INITMENU = 278

    当一个菜单将要被激活时发送此消息,它发生在用户菜单条中的某项或按下某个菜单键,它允许

    程序在显示前更改菜单

    WM_INITMENUPOPUP =279

    当一个下拉菜单或子菜单将要被激活时发送此消息,它允许程序在它显示前更改菜单,而不要

    改变全部

    WM_MENUSELECT = 287

    当用户选择一条菜单项时发送此消息给菜单的所有者(一般是窗口)

    WM_MENUCHAR = 288

    当菜单已被激活用户按下了某个键(不同于加速键),发送此消息给菜单的所有者;

    WM_ENTERIDLE = 289

    当一个模态对话框或菜单进入空载状态时发送此消息给它的所有者,一个模态对话框或菜单进入空载状态就是在处理完一条或几条先前的消息后没有消息它的列队中等待

    WM_MENURBUTTONUP =290

    WM_MENUDRAG = 291

    WM_MENUGETOBJECT =292

    WM_UNINITMENUPOPUP= 293

    WM_MENUCOMMAND =294

    WM_CHANGEUISTATE =295

    WM_UPDATEUISTATE =296

    WM_QUERYUISTATE =297

    WM_CTLCOLORMSGBOX =306

    在windows绘制消息框前发送此消息给消息框的所有者窗口,通过响应这条消息,所有者窗口可以

    通过使用给定的相关显示设备的句柄来设置消息框的文本和背景颜色

    WM_CTLCOLOREDIT =307

    当一个编辑型控件将要被绘制时发送此消息给它的父窗口;通过响应这条消息,所有者窗口可以

    通过使用给定的相关显示设备的句柄来设置编辑框的文本和背景颜色

    WM_CTLCOLORLISTBOX= 308

    当一个列表框控件将要被绘制前发送此消息给它的父窗口;通过响应这条消息,所有者窗口可以

    通过使用给定的相关显示设备的句柄来设置列表框的文本和背景颜色

    WM_CTLCOLORBTN =309

    当一个按钮控件将要被绘制时发送此消息给它的父窗口;通过响应这条消息,所有者窗口可以

    通过使用给定的相关显示设备的句柄来设置按纽的文本和背景颜色

    WM_CTLCOLORDLG =310

    当一个对话框控件将要被绘制前发送此消息给它的父窗口;通过响应这条消息,所有者窗口可以

    通过使用给定的相关显示设备的句柄来设置对话框的文本背景颜色

    WM_CTLCOLORSCROLLBAR=311

    当一个滚动条控件将要被绘制时发送此消息给它的父窗口;通过响应这条消息,所有者窗口可以

    通过使用给定的相关显示设备的句柄来设置滚动条的背景颜色

    WM_CTLCOLORSTATIC =312

    当一个静态控件将要被绘制时发送此消息给它的父窗口;通过响应这条消息,所有者窗口可以

    通过使用给定的相关显示设备的句柄来设置静态控件的文本和背景颜色

    WM_MOUSEFIRST = 512

    WM_MOUSEMOVE = 512

    // 移动鼠标

    WM_LBUTTONDOWN =513

    //按下鼠标左键

    WM_LBUTTONUP = 514

    //释放鼠标左键

    WM_LBUTTONDBLCLK =515

    //双击鼠标左键

    WM_RBUTTONDOWN =516

    //按下鼠标右键

    WM_RBUTTONUP = 517

    //释放鼠标右键

    WM_RBUTTONDBLCLK =518

    //双击鼠标右键

    WM_MBUTTONDOWN =519

    //按下鼠标中键

    WM_MBUTTONUP = 520

    //释放鼠标中键

    WM_MBUTTONDBLCLK =521

    //双击鼠标中键

    WM_MOUSEWHEEL = 522

    当鼠标轮子转动时发送此消息个当前有焦点的控件

    WM_MOUSELAST = 522

    WM_PARENTNOTIFY =528

    当MDI子窗口被创建或被销毁,或用户按了一下鼠标键而光标在子窗口上时发送此消息给它的父窗口

    WM_ENTERMENULOOP =529

    发送此消息通知应用程序的主窗口that已经进入了菜单循环模式

    WM_EXITMENULOOP =530

    发送此消息通知应用程序的主窗口that已退出了菜单循环模式

    WM_NEXTMENU = 531

    WM_SIZING = 532

    当用户正在调整窗口大小时发送此消息给窗口;通过此消息应用程序可以监视窗口大小和位置

    也可以修改他们

    WM_CAPTURECHANGED =533

    发送此消息给窗口当它失去捕获的鼠标时;

    WM_MOVING = 534

    当用户在移动窗口时发送此消息,通过此消息应用程序可以监视窗口大小和位置

    也可以修改他们;

    WM_POWERBROADCAST =536

    此消息发送给应用程序来通知它有关电源管理事件;

    WM_DEVICECHANGE =537

    当设备的硬件配置改变时发送此消息给应用程序或设备驱动程序

    WM_IME_STARTCOMPOSITION= 269

    WM_IME_ENDCOMPOSITION= 270

    WM_IME_COMPOSITION= 271

    WM_IME_KEYLAST =271

    WM_IME_SETCONTEXT =641

    WM_IME_NOTIFY = 642

    WM_IME_CONTROL =643

    WM_IME_COMPOSITIONFULL= 644

    WM_IME_SELECT = 645

    WM_IME_CHAR = 646

    WM_IME_REQUEST =648

    WM_IME_KEYDOWN =656

    WM_IME_KEYUP = 657

    WM_MDICREATE = 544

    应用程序发送此消息给多文档的客户窗口来创建一个MDI 子窗口

    WM_MDIDESTROY = 545

    应用程序发送此消息给多文档的客户窗口来关闭一个MDI 子窗口

    WM_MDIACTIVATE =546

    应用程序发送此消息给多文档的客户窗口通知客户窗口激活另一个MDI子窗口,当客户窗口收到

    此消息后,它发出WM_MDIACTIVE消息给MDI子窗口(未激活)激活它;

    WM_MDIRESTORE = 547

    程序发送此消息给MDI客户窗口让子窗口从最大最小化恢复到原来大小

    WM_MDINEXT = 548

    程序发送此消息给MDI客户窗口激活下一个或前一个窗口

    WM_MDIMAXIMIZE =549

    程序发送此消息给MDI客户窗口来最大化一个MDI子窗口;

    WM_MDITILE = 550

    程序发送此消息给MDI客户窗口以平铺方式重新排列所有MDI子窗口

    WM_MDICASCADE = 551

    程序发送此消息给MDI客户窗口以层叠方式重新排列所有MDI子窗口

    WM_MDIICONARRANGE =552

    程序发送此消息给MDI客户窗口重新排列所有最小化的MDI子窗口

    WM_MDIGETACTIVE =553

    程序发送此消息给MDI客户窗口来找到激活的子窗口的句柄

    WM_MDISETMENU = 560

    程序发送此消息给MDI客户窗口用MDI菜单代替子窗口的菜单

    WM_ENTERSIZEMOVE =561

    WM_EXITSIZEMOVE =562

    WM_DROPFILES = 563

    WM_MDIREFRESHMENU =564

    WM_MOUSEHOVER = 673

    WM_MOUSELEAVE = 675

    WM_CUT = 768

    程序发送此消息给一个编辑框或combobox来删除当前选择的文本

    WM_COPY = 769

    程序发送此消息给一个编辑框或combobox来复制当前选择的文本到剪贴板

    WM_PASTE = 770

    程序发送此消息给editcontrol或combobox从剪贴板中得到数据

    WM_CLEAR = 771

    程序发送此消息给editcontrol或combobox清除当前选择的内容;

    WM_UNDO = 772

    程序发送此消息给editcontrol或combobox撤消最后一次操作

    WM_RENDERFORMAT =773

    WM_DESTROYCLIPBOARD= 775

    当调用ENPTYCLIPBOARD函数时 发送此消息给剪贴板的所有者

    WM_DRAWCLIPBOARD =776

    当剪贴板的内容变化时发送此消息给剪贴板观察链的第一个窗口;它允许用剪贴板观察窗口来

    显示剪贴板的新内容;

    WM_PAINTCLIPBOARD =777

    当剪贴板包含CF_OWNERDIPLAY格式的数据并且剪贴板观察窗口的客户区需要重画;

    WM_VSCROLLCLIPBOARD= 778

    WM_SIZECLIPBOARD =779

    当剪贴板包含CF_OWNERDIPLAY格式的数据并且剪贴板观察窗口的客户区域的大小已经改变是此消息通过剪贴板观察窗口发送给剪贴板的所有者;

    WM_ASKCBFORMATNAME= 780

    通过剪贴板观察窗口发送此消息给剪贴板的所有者来请求一个CF_OWNERDISPLAY格式的剪贴板的名字

    WM_CHANGECBCHAIN =781

    当一个窗口从剪贴板观察链中移去时发送此消息给剪贴板观察链的第一个窗口;

    WM_HSCROLLCLIPBOARD= 782

    此消息通过一个剪贴板观察窗口发送给剪贴板的所有者;它发生在当剪贴板包含CFOWNERDISPALY格式的数据并且有个事件在剪贴板观察窗的水平滚动条上;所有者应滚动剪贴板图象并更新滚动条的值;

    WM_QUERYNEWPALETTE= 783

    此消息发送给将要收到焦点的窗口,此消息能使窗口在收到焦点时同时有机会实现他的逻辑调色板

    WM_PALETTEISCHANGING=784

    当一个应用程序正要实现它的逻辑调色板时发此消息通知所有的应用程序

    WM_PALETTECHANGED =785

    此消息在一个拥有焦点的窗口实现它的逻辑调色板后发送此消息给所有顶级并重叠的窗口,以此

    来改变系统调色板

    WM_HOTKEY = 786

    当用户按下由REGISTERHOTKEY函数注册的热键时提交此消息

    WM_PRINT = 791

    应用程序发送此消息仅当WINDOWS或其它应用程序发出一个请求要求绘制一个应用程序的一部分;

    WM_PRINTCLIENT =792

    WM_HANDHELDFIRST =856

    WM_HANDHELDLAST =863

    WM_PENWINFIRST =896

    WM_PENWINLAST = 911

    WM_COALESCE_FIRST =912

    WM_COALESCE_LAST =927

    WM_DDE_FIRST = 992

    WM_DDE_INITIATE =WM_DDE_FIRST + 0

    一个DDE客户程序提交此消息开始一个与服务器程序的会话来响应那个指定的程序和主题名;

    WM_DDE_TERMINATE =WM_DDE_FIRST + 1

    一个DDE应用程序(无论是客户还是服务器)提交此消息来终止一个会话;

    WM_DDE_ADVISE =WM_DDE_FIRST + 2

    一个DDE客户程序提交此消息给一个DDE服务程序来请求服务器每当数据项改变时更新它

    WM_DDE_UNADVISE =WM_DDE_FIRST + 3

    一个DDE客户程序通过此消息通知一个DDE服务程序不更新指定的项或一个特殊的剪贴板格式的项

    WM_DDE_ACK = WM_DDE_FIRST+ 4

    此消息通知一个DDE(动态数据交换)程序已收到并正在处理WM_DDE_POKE, WM_DDE_EXECUTE, WM_DDE_DATA, WM_DDE_ADVISE,WM_DDE_UNADVISE, or WM_DDE_INITIAT消息

    WM_DDE_DATA =WM_DDE_FIRST + 5

    一个DDE服务程序提交此消息给DDE客户程序来传递个一数据项给客户或通知客户的一条可用数据项

    WM_DDE_REQUEST =WM_DDE_FIRST + 6

    一个DDE客户程序提交此消息给一个DDE服务程序来请求一个数据项的值;

    WM_DDE_POKE =WM_DDE_FIRST + 7

    一个DDE客户程序提交此消息给一个DDE服务程序,客户使用此消息来请求服务器接收一个未经同意的数据项;服务器通过答复WM_DDE_ACK消息提示是否它接收这个数据项;

    WM_DDE_EXECUTE =WM_DDE_FIRST + 8

    一个DDE客户程序提交此消息给一个DDE服务程序来发送一个字符串给服务器让它象串行命令一样被处理,服务器通过提交WM_DDE_ACK消息来作回应;

    WM_DDE_LAST =WM_DDE_FIRST + 8

    WM_APP = 32768

    WM_USER = 1024

    此消息能帮助应用程序自定义私有消息;

    /////////////////////////////////////////////////////////////////////

    通知消息(Notification message)是指这样一种消息,一个窗口内的子控件发生了一些事情,需要通

    知父窗口。通知消息只适用于标准的窗口控件如按钮、列表框、组合框、编辑框,以及Windows 95公

    共控件如树状视图、列表视图等。例如,单击或双击一个控件、在控件中选择部分文本、操作控件的

    滚动条都会产生通知消息。

    按扭

    B N _ C L I C K E D//用户单击了按钮

    B N _ D I S A B L E//按钮被禁止

    B N _ D O U B L E CL I C K E D //用户双击了按钮

    B N _ H I L I T E//用户加亮了按钮

    B N _ PA I N T按钮应当重画

    B N _ U N H I L I TE加亮应当去掉

    组合框

    C B N _ C L O S E UP组合框的列表框被关闭

    C B N _ D B L C L K用户双击了一个字符串

    C B N _ D R O P D OW N组合框的列表框被拉出

    C B N _ E D I T C HA N G E用户修改了编辑框中的文本

    C B N _ E D I T U PD AT E编辑框内的文本即将更新

    C B N _ E R R S PAC E组合框内存不足

    C B N _ K I L L F OC U S组合框失去输入焦点

    C B N _ S E L C H AN G E在组合框中选择了一项

    C B N _ S E L E N DC A N C E L用户的选择应当被取消

    C B N _ S E L E N DO K用户的选择是合法的

    C B N _ S E T F O CU S组合框获得输入焦点

    编辑框

    E N _ C H A N G E编辑框中的文本己更新

    E N _ E R R S PA CE编辑框内存不足

    E N _ H S C R O L L用户点击了水平滚动条

    E N _ K I L L F O CU S编辑框正在失去输入焦点

    E N _ M A X T E X T插入的内容被截断

    E N _ S E T F O C US编辑框获得输入焦点

    E N _ U P D AT E编辑框中的文本将要更新

    E N _ V S C R O L L用户点击了垂直滚动条消息含义

    列表框

    L B N _ D B L C L K用户双击了一项

    L B N _ E R R S PAC E列表框内存不够

    L B N _ K I L L F OC U S列表框正在失去输入焦点

    L B N _ S E L C A NC E L选择被取消

    L B N _ S E L C H AN G E选择了另一项

    L B N _ S E T F O CU S列表框获得输入焦点

    转载:

    http://blog.csdn.net/zhangguofu2/article/details/19236081

    http://www.cppblog.com/suiaiguo/archive/2009/07/18/90412.html

  • 相关阅读:
    mysql 8 查询报错(sql_mode=only_full_group_by)
    docker安装mysql8版本后 客户端连接出现client does not support authentication...
    docker常用命令
    查看tomcat日志相关Linux命令
    java项目部署到linux服务器涉及的命令
    ehcache与redis对比
    JS中调用BigDecimal处理金额
    thymeleaf模板 th:href 踩坑
    汇总一些绝对有价值的解决方案,边学习边收集
    spring注解总结,spring注解大全
  • 原文地址:https://www.cnblogs.com/DeeLMind/p/6886067.html
Copyright © 2020-2023  润新知