消息循环原理,函数

 

原理:

消息分为  队列消息(进入线程的消息队列)  和  非队列消息(不进入线程的消息队列)

对于队列消息,最常见的是鼠标键盘触发的消息,例如WM_MOUSERMOVE、WM_CHAR、WM_PAINT、WM_TIMER和WM_QUIT。当鼠标、键盘事件被触发后,相应的鼠标或键盘驱动程序就会把这些事件转换成相应的消息,然后输送到系统消息队列,由Windows系统负责把消息加入到相应线程的消息队列中,于是就有了消息循环(从消息队列中读取并派送消息)。

还有一种是非队列消息,他绕过系统消息队列,直接将消息发送到窗口过程。例如,当用户激活一个窗口系统发送WM_ACTIVATE、WM_SETFOCUS、WM_SETCURSOR,创建窗口时发送WM_CREATE消息。

MSG结构体:

​​//MSG 结构体
typedef struct tagMSG {
    HWND        hwnd;
    UINT        message;    //消息ID
    WPARAM      wParam;    //标识按下或释放的键码
    LPARAM      lParam;    //含有对了解按键非常有用的其他信息
    DWORD       time;    //时间(消息投递到消息队列的时间)
    POINT       pt;   //光标在屏幕上的当前位置
} MSG, *PMSG, NEAR *NPMSG, FAR *LPMSG;

产生过程:

事件 ——>封装消息(MSG结构体)——>传递消息到队列 ——>消息响应(消息处理函数)

(  消息队列 ——>GetMessage() ——>DispatchMessage() ——>winProc  )

函数:


GetMessage():

例:GetMessage(&msg, NULL, 0, 0)

原型:

BOOL GetMessage(      

    LPMSG lpMsg,  //MSG结构体的消息指针
    HWND hWnd,  //要检索消息的窗口的句柄,窗口必须属于调用线程
    UINT wMsgFilterMin,  //指定要检索的最小消息值的整数值
    UINT wMsgFilterMax  //指定要检索的最大消息值的整数值
);

其中如果第二个参数取值NULL:

代表GetMessage检索属于调用线程的任何窗口的消息和使用PostThreadMessage函数发布到调用线程的线程消息。

第三个参数:使用WM_KEYFIRST指定第一个键盘消息或WM_MOUSEFIRST指定第一个鼠标消息。

第四个参数:使用WM_KEYLAST指定最后的键盘消息或WM_MOUSEFIRST指定最后的鼠标消息。

过程:

当前消息队列 ——>查看窗口是否重绘(WM_PAINT)

                       ——>查看定时器(WM_TIMER)

                       ——>优化内存,优化资源

                       ——>等待

返回值:

如果函数检索到的消息不是WM_QUIT消息,则返回非0值。

如果函数检索到了WM_QUIT消息,则返回0值。

如果发生错误,返回值为-1。例如,参数hWnd是一个无效的窗口句柄或lpMsg是一个无效的指针。要获得更多的错误信息可以调用GetLastError函数。

警告:

因为函数的返回值可以为非0,0,-1,所以应该避免如下代码:

while(GetMessage( lpMsg, hWnd, 0, 0) ......)

当返回值为-1时,可能导致程序致命的错误。

另外,如果这样写的话:

​while(GetMessage( lpMsg, hWnd, 0, 0) != 0 && GetMessage( lpMsg, hWnd, 0, 0) != -1)

相当于调用了两次GetMessage()函数,获取了两次msg消息,却只在while的循环里只处理了一次msg......这就会出现问题。

应使用如下代码:

BOOL bRet;
while( (bRet = GetMessage( &msg, NULL, 0, 0 )) !=0)
{
    if (bRet == -1)
    {
        // handle the error and possibly exit
    }
    else
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
}

TIPS:

程序通常使用返回值来确定是否应该结束主消息循环并退出程序。

GetMessage函数检索由hWnd参数标识的关联窗体,或者由IsChild函数指定的它们子窗体的消息,并且消息范围在wMsgFilterMin和wMsgFilterMax参数指定值之间的消息。

注意,不管在wMsgFilterMin和wMsgFilterMax指定的范围如何,GetMassage函数总是检索会WM_QUIT消息。

在函数调用期间,系统用SendMessage、SendMessageCallback,、SendMessageTimeout或者SendNotifyMessage函数发送待处理的、非队列的消息给属于当前线程的窗口。系统也可能处理内部事件。消息的处理顺序如下:

       Sentmessages(发送消息)

       Postedmessages(投递消息)

       输入(硬件)消息或者系统内部事件

       Sentmessages (again)(发送消息)

      WM_PAINT消息

      WM_TIMER消息

在投递消息之前检索输入消息,可以利用wMsgFilterMin和wMsgFilterMax参数做检索设置。

GetMessage不会从消息队列中移除WM_PAINT消息。该消息将一直存在于消息队列中直到被处理。


PeekMessage():

例:PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)

原型:

BOOL PeekMessage(      
    LPMSG lpMsg,
    HWND hWnd,
    UINT wMsgFilterMin,
    UINT wMsgFilterMax,
    UINT wRemoveMsg  //指定消息的处理方式
);

前四项参数都与GetMessage()一样,最后一项参数有以下几种取值:

PM_NOREMOVE:消息经PeekMessage处理后并不从消息队列中移除。

PM_REMOVE:消息经PeekMessage处理后从消息队列中移除。

(PS:可以有选择性的组合PM_NOYIELD 和 PM_NOREMOVE  | |  PM_NOYIELD 和 PM_REMOVE。PM_NOYIELD标志将阻止系统释放等待调用程序空闲的线程。)

PM_QS_INPUT:Windows 98/Me,Windows 2000/XP: 处理鼠标和键盘消息。

PM_QS_PAINT:Windows 98/Me,Windows 2000/XP:处理绘图消息。

PM_QS_POSTMESSAGE:Windows 98/Me,Windows 2000/XP:处理所有投递消息,包括定时器和热键消息。

PM_QS_SENDMESSAGE:Windows 98/Me,Windows 2000/XP: 处理所有发送消息。

过程:同GetMessage()

返回值:

如果有可用的消息,则返回值为非0;

如果没有可用的消息,则返回值为0;

TIPS:

同GetMessage(),另:但是,如果WM_PAINT消息的更新区域为空,则PeekMessage会将其从消息队列中移除。


TranslateMessage():

例:TranslateMessage(&msg)

原型:

BOOL TranslateMessage(
  CONST MSG *lpMsg
);

返回值:将键盘消息转换为字符消息,如果字符消息被发送到线程的消息队列,则返回值为非0。

如果消息是WMYKEYDOWN、WMYKEYUP、WMYSysKEYDOWN或WMY SysKyUp,则返回值为非零,而不考虑转换。

如果消息未被转换(即,字符消息未被发送到线程的消息队列),则返回值为0。


DispatchMessage():

例:DispatchMessage(&msg)

原型:

LRESULT DispatchMessage(
  CONST MSG *lpMsg
);

功能:分发一个消息给回调函数。

返回值:

返回值指定窗口过程返回的值。虽然它的含义取决于正在发送的消息,但返回值通常被忽略。

( LRESULT:指的是从窗口程序或者回调函数返回的32位值,LRESULT = LONG + RESULT也就是长整型。)


SendMessage():

例:SendMessage(hWnd, WM_CLOSE, 0, 0)

原型:

LRESULT SendMessage(
  HWND   hWnd,
  UINT   Msg,
  WPARAM wParam,
  LPARAM lParam
);

hWnd:其窗口程序将接收消息的窗口的句柄。如果此参数为HWND_BROADCAST,则消息将被发送到系统中所有顶层窗口,包括无效或不可见的非自身拥有的窗口、被覆盖的窗口和弹出式窗口,但消息不被发送到子窗口。

功能:发送一个指定的消息到一个窗口。

返回值:

返回值指定窗口过程返回的值,它的含义取决于正在发送的消息。

 


PostMessage():

例:PostMessage(hWnd, WM_CLOSE, 0, 0)

原型:

BOOL PostMessage(
  HWND   hWnd,
  UINT   Msg,
  WPARAM wParam,
  LPARAM lParam
);

hWnd:其窗口程序将接收消息的窗口的句柄。如果此参数为HWND_BROADCAST,则消息将被发送到系统中所有顶层窗口,包括无效或不可见的非自身拥有的窗口、被覆盖的窗口和弹出式窗口,但消息不被发送到子窗口。如果为NULL,此函数的操作和调用参数dwThread设置为当前线程的标识符PostThreadMessage函数一样

功能:该函数将一个消息放入(寄送)到与指定窗口创建的线程相联系消息队列里,不等待线程处理消息就返回,是异步消息模式。

返回值:如果调用成功,则返回非0值,否则返回0。

 

你可能感兴趣的:(WIN32编程)