windows編程中,如何讓一個窗口實現真正的置頂

    也許你會說,很簡單啊。用“::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);
}

另外有任何補充的地方,歡迎在下方評論或是留言。



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章