2013-07-26 39 views
9

我有一點問題完全理解AttachThreadInput。瞭解AttachThreadInput - 分離失去重點

我知道這是「連接」的2個線程,這(我想做的事情)讓我舉例來說,迫使我的窗口(的WinForms)在前臺消息隊列。

,我可以用這種方法做:

private void SetForegroundWindowEx(IntPtr hWnd) 
{ 
    uint SW_SHOW = 5; 
    uint appThread = GetCurrentThreadId();  
    uint foregroundThread = GetWindowThreadProcessId(GetForegroundWindow(), IntPtr.Zero);   

    if (foregroundThread != appThread) 
    { 
     AttachThreadInput(foregroundThread, appThread, true); 

     BringWindowToTop(hWnd); 
     ShowWindow(hWnd, SW_SHOW);  
     AttachThreadInput(foregroundThread, appThread, false); 

    } 
    else 
    { 
     BringWindowToTop(hWnd); 
     ShowWindow(hWnd, SW_SHOW); 
    } 
} 

但是窗戶都失去,一旦線程分離關注。

如果我等待消息隊列爲空(Application.DoEvents()),並激活我的窗口(也就是現在的前景,但不集中),它會重新獲得焦點,並保持它。

如果我在消息隊列爲空之前執行此操作,它將再次失去焦點。

所以我猜該剝離的需要的東西從我的窗戶焦點,但我不知道那是什麼或如何防止它。

這是我不明白的第一件事。

我不明白的第二件事是,如果我沒有我的窗口設置爲前景:

AttachThreadInput(foregroundThread, appThread, true); 

AttachThreadInput(foregroundThread, appThread, false); 
Application.DoEvents(); 
this.Activate(); 

等待消息隊列爲空,並激活我的窗口(這一次是不是在前臺而另一個窗口仍然有焦點),它實際上被激活,即使線程不再被連接。

也許有人有更好的理解AttachThreadInput的能回答我這2個問題。

信息:
我要偷的焦點在這種情況下,因爲我的應用程序被通過API調用。另一個調用我的應用程序,等待我的應用程序的反饋,並在大多數時間凍結,直到它獲得信息。

如果其他應用程序是全屏很多用戶沒有注意到在任務欄閃爍,並認爲其他的應用程序崩潰,並與Taskmamanger殺死它。由於我不一定能夠控制其他應用程序,因此我無法告訴它將焦點設置在我的窗口中。

此方法將不會被調用,如果它不是absolutelly必要的,在這種情況下,該行爲,這是敵對的,我知道,作爲深受我想作爲用戶。

+0

您可能會發現[this](http://blogs.msdn.com/b/oldnewthing/archive/2013/06/19/10426841.aspx)和[this](http:// blogs。 msdn.com/b/oldnewthing/archive/2008/08/01/8795860.aspx)頗有意思。 –

+0

兩個鏈接都告訴我我想要附加線程輸入有多糟糕,不是嗎?或者還有什麼我錯過了?我知道這不是一個普遍的習慣,幾乎所有的代價都應該防止,但在我的情況下,我確實需要這樣做。 – Visions

+0

請注意,我並不是這方面的專家,但最近剛剛閱讀了這篇文章。話雖如此,你可能想比較你的代碼片段的第一行和[本例中的第一行](http://blogs.msdn.com/b/oldnewthing/archive/2013/06/19/10426841。 ASPX)。從不經意的角度看,他們喜歡完全相同(因此陳述文章「錯誤」)。 YMMV當然。 –

回答

8

這是我用於相同目的的一段c#代碼。我想說明的是,有些情況下可能需要這樣的合法情況。在我們的情況下,這是MS Word自動化。無論何時用戶點擊我們應用程序內的工具欄按鈕,我們都應該立即將Word窗口帶給用戶注意。

public static void ForceWindowIntoForeground(IntPtr window) 
{ 
    uint currentThread = Win32.GetCurrentThreadId(); 

    IntPtr activeWindow = Win32.GetForegroundWindow(); 
    uint activeProcess; 
    uint activeThread = Win32.GetWindowThreadProcessId(activeWindow, out activeProcess); 

    uint windowProcess; 
    uint windowThread = Win32.GetWindowThreadProcessId(window, out windowProcess); 

    if (currentThread != activeThread) 
     Win32.AttachThreadInput(currentThread, activeThread, true); 
    if (windowThread != currentThread) 
     Win32.AttachThreadInput(windowThread, currentThread, true); 

    uint oldTimeout = 0, newTimeout = 0; 
    Win32.SystemParametersInfo(Win32.SPI_GETFOREGROUNDLOCKTIMEOUT, 0, ref oldTimeout, 0); 
    Win32.SystemParametersInfo(Win32.SPI_SETFOREGROUNDLOCKTIMEOUT, 0, ref newTimeout, 0); 
    Win32.LockSetForegroundWindow(LSFW_UNLOCK); 
    Win32.AllowSetForegroundWindow(Win32.ASFW_ANY); 

    Win32.SetForegroundWindow(window); 
    Win32.ShowWindow(window, Win32.SW_RESTORE); 

    Win32.SystemParametersInfo(Win32.SPI_SETFOREGROUNDLOCKTIMEOUT, 0, ref oldTimeout, 0); 

    if (currentThread != activeThread) 
     Win32.AttachThreadInput(currentThread, activeThread, false); 
    if (windowThread != currentThread) 
     Win32.AttachThreadInput(windowThread, currentThread, false); 
}