一、windows系统中,一个UI线程只有一个消息队列,但可以有多个消息循环。
如模态对话框的其中一种实现方式:
主线程创建了主窗口,启动了一个消息循环,当然UI线程系统会自己给其分配消息队列空间的。当要弹出一个模态对话框时,先禁用掉主窗口,模态框创建代码里启动一个消息循环。消息循环中可能会存在主窗口的消息,也有模态对话框的消息。会对其消息进行分发。如果是主窗口的消息,则调用主窗口的窗口函数来处理这个消息。如果是模态对话框的消息 ,则调用模态对话框的窗口函数来这里这个消息。当关闭模态框之前,结束模态窗口的消息循环。
二、WM_ACTIVE消息
窗口在第一次创建并显示的时候,会收到WM_ACTIVE消息,第一次隐藏的时候也会收到WM_ACTIVE消息。但是第二次显示的时候,如果窗口显示的时候设置SWP_NOACTIVAT等不激活标识,如调用:
SetWindowPos(NULL, pt.x, pt.y, 0, 0, SWP_NOZORDER|SWP_NOSIZE|SWP_NOACTIVATE|SWP_SHOWWINDOW),
则第一次之后显示和隐藏都不会收到WM_ACTIVE消息。要想每次显示和隐藏都收到WM_ACTIVE消息,则需要去掉SWP_NOACTIVAT等标识,或者每次显示的时候调用:
SetActiveWindow(m_hWnd);
三、ShowWindow函数
如果窗口显示的时候,没有设置SWP_NOACTIVATE标识,则窗口每次显示和隐藏都会收到WM_ACTIVE消息。通常当调用ShowWindow显示和隐藏窗口时,系统会收到WM_ACTIVE消息。在菜单的实现中,菜单窗口失活的时候(这也会收到WM_ACTIVE消息),需要隐藏菜单。这时在失活的消息响应函数中不能直接调用::ShowWindow(m_hWnd , SW_HIDE);
而应该重新定义一个消息,并PostMessage到自己的窗口上。在自定义的消息响应中来调用::ShowWindow(m_hWnd , SW_HIDE)。因为调用ShowWindow又会激发WM_ACTIVE消息,会使该消息发送了两次,会带来不必要的麻烦。
四、快捷键
Windows的快捷键分为全局快捷键和局部快捷键。
(1)、全局快捷键
BOOL WINAPI RegisterHotKey(
_In_opt_ HWND hWnd,
_In_ int id,
_In_ UINT fsModifiers,
_In_ UINT vk
);
一般调用
函数来注册全局快捷键,第一个参数是一个窗口句柄:A handle to the window that will receive WM_HOTKEY messages generated by the hot key. If this parameter is NULL, WM_HOTKEY messages are posted to the message queue of the calling thread and must be processed in the message loop.
。需要注销时,调用UnregisterHotKey来注销。
全局快捷键收到的是WM_HOTKEY消息,不管注册的窗口处于什么状态,只要窗口句柄存在,或者当初调用RegisterHotKey的线程存在。就会收到WM_HOTKEY消息。窗口或者线程对WM_HOTKEY进行消息响应,加入自己想做的事情。
全局快捷键可以被其他进程抢占,前提是之前占用该快捷键的线程或者窗口已经退出或者销毁不存在了。
windows系统自己的快捷键,如Alt+F4(结束当前进程),也可以被其他进程抢占,没有前提,即windows自定义的快捷键是最好被抢占的。
windows系统的所有全局快捷键可以用Windows Hotkey Explorer工具来查看。
(2)、局部快捷键
对于局部快捷键,不需要调用RegisterHotKey函数,而是简单的在窗口回调函数中对WM_KEYDOWN和WM_SYSKEYDOWN消息进行处理。该窗口必须获得键盘鼠标焦点,通常处理激活态的窗口拥有焦点。局部快捷键只有在窗口处理显示激活态时才能响应局部快捷键。