Bei Topmost Programmfenster den Eingabefokus an vorher aktives Programm abgeben



  • Guten Tag

    Ich habe ein Programm, dass sich kurzzeitig den Eingabefokus mit SetForegroundWindow holt um Eingaben zu empfangen.

    Wie kann ich diesen Eingabefokus wieder zurückgeben, und zwar genau so, wie er war bevor sich das Programm den Eingabefokus geholt hat.

    Ich habe schon versucht das vorhergehende Programm mit GetTopWindow und GetNextWindow zu ermitteln und dieses dann mit SetForegroundWindow in den Vordergund zu setzen, aber da verlieren die vorher aktiven Elemente den Eingabefokus.

    Die Einstellungen meines Programmes sehen folgendermaßen aus:
    Das Programm ist Dialogfeldbasierend.
    Das Programm wurde mit SetWindowPos topmost gesetzt.
    Beim Initialisieren wird das Programm mit ModifyStyleEx(WS_EX_APPWINDOW, WS_EX_TOOLWINDOW); aus der Taskliste entfert.

    Für das Suchen des vorher aktiven Programms wird folgende Funktion verwendet:

    // Gibt das zuvor aktive Programmfenster zurück
    CWnd* CMyClass::GetPrevWnd()
    {
    	CWnd* cWnd = CWnd::FromHandle(GetTopWindow(NULL));
    	if(cWnd == NULL)
    	{
    		return NULL;
    	}
    	// String in den der Fenstertext gespeichert wird
    	CString str;
    
    	do
    	{
    		//cWnd = cWnd->GetNextWindow(GW_HWNDPREV);
    		cWnd = cWnd->GetNextWindow(GW_HWNDNEXT);
    		if(cWnd == NULL)
    		{
    			return NULL;
    		}
    
    		cWnd->GetWindowText(str);
    
    	// Es wird überprüft, ob das gefundene Fenster sichtbar ist
    	// Wenn das aufrufende Programm topmost ist, kann der erste Treffer der Start sein
    	}while( !cWnd->IsWindowVisible() || (str.MakeUpper() == _T("START")));
    
    	return cWnd;
    }
    

    Für das Erteilen des Eingabefokus verwende ich folgende Funktion:

    //Setzt ein Fenster in den Vordergrund
    BOOL CMyClass::ForceForegroundWindow(HWND hWnd) 
    { 
        if(!hWnd || !::IsWindow(hWnd)) 
            return FALSE; 
    
        HWND hWndCurrentWindow = ::GetForegroundWindow(); 
        if(hWndCurrentWindow == NULL) 
        { 
            return ::SetForegroundWindow(hWnd); 
        } 
    
        DWORD dwCurProcId, dwCurThreadId = ::GetWindowThreadProcessId(hWndCurrentWindow, &dwCurProcId);
         DWORD dwHWndProcId; 
        ::GetWindowThreadProcessId(hWnd, &dwHWndProcId); 
    
        BOOL bReturn = FALSE; 
    
        if(dwHWndProcId == dwCurProcId) 
        { 
            bReturn = ::SetForegroundWindow(hWnd); 
        } 
        else 
        { 
            DWORD dwMyThreadId = ::GetCurrentThreadId(); 
    
            if(::AttachThreadInput(dwMyThreadId, dwCurThreadId, TRUE)) 
            { 
                bReturn = ::SetForegroundWindow(hWnd); 
                ::AttachThreadInput(dwMyThreadId, dwCurThreadId, FALSE); 
            } 
            else 
            { 
                bReturn = ::SetForegroundWindow(hWnd); 
            } 
        } 
    
        return bReturn; 
    }
    

    Weis jemand was ich falsch mache bzw. wie ich den Eingabefokus einfach wieder zurückgeben kann?


  • Mod

    Du musst Dir den Focus des alten fenster mit GetFocus holen nachdem Du AttachThreadInput durchgeführt hast und auch wieder mit SetFocus setzen.



  • Dank deiner Hilfe funktioniert das Programm größtenteils so wie es soll.

    Doch leider funktioniert das Zurückgeben des Eingabefokus nicht mehr richtig nachdem ich den Fensterstiel mit ModifyStyleEx(WS_EX_APPWINDOW, WS_EX_TOOLWINDOW); aus der Taskliste entfert habe.

    Nach dieser Änderung wird der Fokus nur mehr zurückgegeben wenn man mein Programm zuvor durch hineinklicken aktiviert hat.

    Wenn es mit ForceForegroundWindow den Eingabefokus erhalten hat ist beim Zurückgeben des Eingabefokus wie es aussieht die Bedingung dwHWndProcId == dwCurProcId true.
    Da funktioniert das Erteilen des Eingabefokus aber nicht.

    Gibt es für dieses Problem eine Lösung?


  • Mod

    Und Du bist sicher als hWnd das andere fenster angegeben zu haben und dann hast Du auch SetFocus ausgeführt?



  • Martin Richter schrieb:

    Und Du bist sicher als hWnd das andere fenster angegeben zu haben und dann hast Du auch SetFocus ausgeführt?

    Ich bin ziemlich sicher dass ich die richtige hWnd verwende, da ich mir den Fenstertitel als Debugausgabe ausgebe. und der passt.

    Wenn ich den Fensterstiel nicht verändere, funktioniert alles wie es soll.

    GetFocus / SetFocus habe ich so eingebunden wie du vorgeschlagen hast.

    Es sieht fast so aus, als ob mein Programm, wenn ich den Style des Fensters ändere mit SetForegroundWindow zwar den Eingabefokus erhält, aber nicht richtig aktiv wird.
    Da dürfte Windows ein wenig durcheinander kommen, weil das Fenster zwar angezeigt wird, sich aber kein Eintrag in der Taskleiste befindet.


Anmelden zum Antworten