也许你会说,很简单啊。用“::SetWindowPos(m_hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE);”这个函数不就一下子可以解决了。然而事实有时却没有这么容易。
前几天做了一个项目,我们的软件是对接体重秤的,有的时候需要刷卡(刷卡器扫描二维码),刷卡的实质其实接收的是键盘上的消息。但是有的时候却会有广告弹出来,弹出来的广告会抢占当前刷卡的主界面,导致刷卡不成功。这个时候我们需要将我们的窗口再次置顶。可以使用一下两个函数。
SetForegroundWindow(m_hWnd);
SetFocus(m_hWnd);
对于接收普通的消息,此时可能已经满足需求了。但是刷卡需要接收的是键盘的消息,光是上面的两个函数,还不足以将光标置顶。于是代码就变成了下面的这种:
AttachThreadInput(GetWindowThreadProcessId(::GetForegroundWindow(), NULL), GetCurrentThreadId(), TRUE);
SetForegroundWindow(m_hWnd);
SetFocus(m_hWnd);
AttachThreadInput(GetWindowThreadProcessId(::GetForegroundWindow(), NULL), GetCurrentThreadId(), FALSE);
重点就是AttachThreadInput这个函数的使用,这个函数中将当前应用程序中的当前线程连接到最前端的窗口中,就导致键盘输入的消息会最先本分发到当前的线程中。之后设置当前窗口的焦点之后,释放连接。
为了使得代码达到最优,我们可以将线程的连接与消息的响应关联起来。其他进程消息的响应是WM_ACTIVATEAPP,但是我们不能将上面的代码写在这个消息里,不然会不起作用,于是我就设置了一个定时器。
else if (uMsg == WM_ACTIVATEAPP){
m_bOutFocusFlag = true;
SetTimer(m_hWnd, FOCUSE_OUT_ID, 60, NULL);
}
定时器中的代码如下:
else if (FOCUSE_OUT_ID == nIDEvent){
AttachThreadInput(GetWindowThreadProcessId(::GetForegroundWindow(), NULL), GetCurrentThreadId(), TRUE);
SetForegroundWindow(m_hWnd);
SetFocus(m_hWnd);
AttachThreadInput(GetWindowThreadProcessId(::GetForegroundWindow(), NULL), GetCurrentThreadId(), FALSE);
m_bOutFocusFlag = false;
KillTimer(m_hWnd, FOCUSE_OUT_ID);
}
另外有任何补充的地方,欢迎在下方评论或是留言。