2013-07-26 19 views
9

ich ein kleines Problem vollständig Verständnis AttachThreadInput bekam.Verständnis AttachThreadInput - Abnehmen verlieren Fokus

Ich weiß, es ist "verbinden" die Nachrichtenwarteschlange von 2 Threads, die (zum Beispiel, was ich tun möchte) ermöglicht es mir, mein Fenster (winforms) im Vordergrund zu erzwingen.

Was ich mit dieser Methode kann:

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

jedoch beide Fenster so schnell verlieren konzentrieren, da die Fäden lösen.

Wenn ich darauf warte, dass die Nachrichtenwarteschlange leer wird (Application.DoEvents()) und mein Fenster aktiviert (das jetzt im Vordergrund aber nicht fokussiert ist), wird es den Fokus wieder erlangen und behalten.

Wenn ich es vor der Nachrichtenwarteschlange zu tun ist leer wird es wieder den Fokus verlieren.

Also ich würde vermuten, etwas von der Ablösung nimmt den Fokus von meinen Fenstern, aber ich habe keine Ahnung, was das ist oder wie man es verhindert.

Dies ist die erste Sache, die ich nicht ganz verstehen.

Die zweite Sache, die ich nicht bekommen, ist, wenn ich mein Fenster nicht den Vordergrund gesetzt:

AttachThreadInput(foregroundThread, appThread, true); 

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

Warten auf die Nachrichtenwarteschlange leer, und meine Fenster aktivieren (diesmal ist es nicht im Vordergrund und das andere Fenster hat immer noch den Fokus), es wird tatsächlich aktiviert, obwohl die Threads nicht mehr angehängt sind.

vielleicht jemand mit einem besseren Verständnis der AttachThreadInput kann mir diese 2 Fragen beantworten.

INFO:
Ich brauche den Fokus in diesem Fall zu stehlen, weil meine App über eine API aufgerufen wird. Die andere App, die meins aufruft, wartet auf Feedback von meiner App und friert in den meisten Fällen ein, bis sie die Info bekommt.

Wenn die andere App Vollbild ist, bemerken viele Benutzer nicht das Blinken in der Taskleiste und denken, dass die andere App abgestürzt ist und töte sie mit dem Taskmanager. Da ich nicht unbedingt die Kontrolle über die andere App habe, kann ich nicht sagen, dass sie den Fokus auf mein Fenster legen soll.

Diese Methode wird nicht aufgerufen, wenn es nicht absolut notwendig ist, in diesem Fall wird dieses Verhalten, das feindselig ist, ich weiß, auch von mir selbst als vom Benutzer gewollt.

+0

Sie können feststellen, [diese] (http://blogs.msdn.com/b/oldnewthing/archive/2013/06/19/10426841.aspx) und [diese] (http: // blogs. msdn.com/b/oldnewthing/archive/2008/08/01/8795860.aspx) ziemlich interessant. –

+0

Nun, beide Links sagen mir, wie schlecht ich Thread-Input anhängen will, nicht wahr? Oder gibt es noch etwas, das ich vermisst habe? Ich weiß, das ist keine gewöhnliche Übung, und es sollte zu fast allen Kosten verhindert werden, aber in meinem Fall muss ich es tatsächlich tun. – Visions

+0

Wohlgemerkt, ich bin hier kein Experte, aber habe erst kürzlich diesen einen Artikel gelesen.Nachdem dies gesagt wurde, möchten Sie vielleicht die ersten Zeilen Ihres Codefragments mit den ersten Zeilen in [diesem Beispiel] vergleichen (http://blogs.msdn.com/b/oldnewthing/archive/2013/06/19/10426841). aspx). Aus einer lockeren Sicht mögen sie ziemlich identisch (und damit den Artikel "falsch"). YMMV natürlich. –

Antwort

8

Hier ist ein Stück von C# Code, den ich für den gleichen Zweck verwendet werden. Ich möchte darauf hinweisen, dass es legitime Fälle gibt, in denen dies erforderlich sein könnte. In unserer Situation war es MS Word Automatisierung. Wenn ein Nutzer in unserer App auf eine Schaltfläche in der Symbolleiste klickt, sollten wir sofort das Word-Fenster dem Nutzer zur Kenntnis bringen.

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