让窗体保持焦点

窗口消息:

        当一个非激活的顶级窗口或非激活的顶级窗口的子窗口被单击,首先会产生 WM_MOUSEACTIVATE 消息并传递给顶级窗口。窗口接到消息后交由 DefWindowProc 处理。

        WM_MOUSEACTIVATE 消息可以使用如下方式响应:
                MA_ACTIVATE                      激活窗口,并接收鼠标消息
                MA_NOACTIVATE                 不激活窗口,接收鼠标消息
                MA_ACTIVATENDEAT           激活窗口,忽略鼠标消息
                MA_NOACTIVATEANDEAT    不激活窗口,忽略鼠标消息


        protected override void WndProc(ref Message m)
        {
            base.WndProc(ref m);
            const int MA_NOACTIVATE = 3;
            const int WM_MOUSEACTIVATE = 0x21;
            if (m.Msg == WM_MOUSEACTIVATE)
                m.Result = (IntPtr)MA_NOACTIVATE;
        }

        若窗口被鼠标点击激活,而且 WM_MOUSEACTIVATE 返回 MA_ACTIVATE,此时会收到系统消息 WM_ACTIVATEAPP  (wParam 标识为激活),然后收到 WM_ACTIVATE 消息(wParam 标识为激活),再有 WM_SETFOCUS 消息。但是在这个过程之前原先拥有焦点的窗口会先发生如下事件: WM_ACTIVATE (wParam 标识为失活)-> WM_ACTIVATEAPP (wPARAM 标识为失活) -> WM_KILLFOCUS。
        若窗被鼠标激活,返回的是 WM_NOACTIVATEANDEAT 窗口就不会收到 WM_SETFOCUS,这将会使到当前没有窗口拥有焦点,而且窗口上的对象也无法获得鼠标的消息,包括点击。要使原窗口不失去焦点,可以在原窗口上捕获 WM_NCACTIVATE 消息,当 wParam = 0 时,把它设置回 1,即 wParam =1。那么原窗口的焦点还被保留着。

        protected override void WndProc(ref Message m)
        {
            const int WM_NCACTIVATE = 0x86;
            if (m.Msg == WM_NCACTIVATE && m.WParam == IntPtr.Zero)
                m.WParam = (IntPtr)1;
            base.WndProc(ref m);
        }


获取 wParam 的高位和低位的值:
        取 DWORD 无符号整数低位:
                (IntPtr) loword = (IntPtr) wParam & 0xffff;
        取 DWORD 无符号整数高位:
                (IntPtr) hiword = (IntPtr) wParam >> 16 & 0xffff;

WM_MOUSEACTIVATE = &H21    '当用鼠标激活窗口时
WM_ACTIVATEAPP = &H1C '窗口准备被激活前或准备失去激活状态后的消息
WM_NCACTIVATE = &H86  '窗口非客户区准备被激活时或准备失去激活状态时的消息
WM_ACTIVATE = &H6     '窗口准备被激活时或准备失去激活状态时的消息
WM_SETFOCUS = &H7     '窗口得到焦点时(比如窗口由最小化还原时)的消息
WM_KILLFOCUS = &H8    '窗口失去焦点时的消息

你可能感兴趣的:(让窗体保持焦点)