1. 程式人生 > >windows程式設計中,如何讓一個視窗實現真正的置頂

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);
}

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