创建窗体,不抢夺焦点
http://www.cnblogs.com/cartler/
经过资料查找,发现可以设置WS_EX_NOACTIVATE
界面编程里面,经常碰到焦点问题,以下几点可注意:
1. Create时指定 WS_EX_NOACTIVATE属性,注意同时去掉WS_VISIBLE,这样创建窗口时不会抢焦点。
2.响应 WM_MOUSEACTIVATE 消息,返回 MA_NOACTIVATE,这样鼠标在其上操作时不会抢焦点,在popup窗口上做这条即可,对其子窗口一并有效。
3.可以用 GetGUIThreadInfo() 取得当前焦点相应信息,用于查看焦点抢占情况。
经过这样设置的窗口,基本上解决不了我的问题。原因如下:
WINDOWS为每一个线程创建一个数据结构称为"线程本地输入状态",里面记录了该线程创建的窗口中哪个是活动窗口,哪个具有输入焦点,以及光标等信息(由操作系统维护)。
根据以上原理,如果是一个线程创建的两个窗口,用户是无法控制输入焦点的。因此要想在激活另一个窗口时,同时不能改变输入焦点,只能让这两个窗口分属于不同的线程(不必是不同的进程)。
看了你的问题后,我有个方案觉得很适合你的要求:
1)Frame1始终让edit控件具有输入焦点;
2)Frame2由另一个线程来创建;
3)使用WIN32 API的AttachThreadInput(Thread1ID, Thread2ID, TRUE)将Frame1和Frame2两个窗口的线程本地状态关联起来;
说得通俗点,Frame1和Frame2共享一个输入焦点,且两个窗口共享所有的鼠标,键盘操作。这或许是AttachThreadInput这个API的命名又来。具体使用情况楼主看下MSDN,自己码下代码!
也就是说同一个线程创建的窗口用WS_EX_NOACTIVATE样式是没有效果的。
问题还是需要解决,经过查证已找到正确方法:
- 创建窗口时去掉WS_VISIBLE属性,加上WS_DISABLED属性。
- 创建窗口,得到窗口句柄。
- ::ShowWindow(m_hWnd,SW_SHOWNOACTIVATE)显示窗口,则不会抢夺焦点。
- 更进一步,可以屏蔽鼠标点击时获得焦点的行为,响应WM_MOUSEACTIVATE,返回MA_NOACTIVATE。
完美收工!