SetActiveWindow / SetForegroundWindow?



  • Ich versuche gerade, mit C++ ein beliebiges Fenster als "aktiv" zu vermerken, also als wenn man in der Taskleiste ein Fenster auswählt. MSDN sagt zu SetActiveWindow bzw. zu SetForegroundWindow ich muss als Parameter ein Handle zu dem Fenster übrergeben, welches in den Vordergrund soll bzw. aktiv sein soll. Ich frage mich nun, wie soll ich ein Handle auf ein Fenster angeben, dass ich gar nicht selbst erzeugt habe? Also beispielsweise ein Browserfenster oder ähnliches...





  • Danke!

    Ich arbeite allderings erst seit gestern mit der WINAPI.

    Wenn ich nun die Funktion FindWindow aufrufe, wie siehts da mit den Parametern aus. Kann ich als WindowName einfach den Namen des Windows in "" angeben? Gibts dort evtl. einen Bsp. Code?

    Was mir gerade ebenfalls auffällt:

    Als Fenster - Schliess - Code habe ich

    // Wurde eine Taste gedrückt?
        case WM_KEYDOWN:
        {
          // Ja, also je nach Taste verzweigen
          switch (wParam)
          {
            // Wurde "Escape" gedrückt?
            case VK_ESCAPE:
            {
              // Ja, also Nachricht zum Beenden schicken
              PostQuitMessage (0);
              return (0);
    
            }
          }
        }break;
       }
    

    Wenn ich nun versuche noch ein Case hinzuzufügen, was aber auf die Rechte Maustaste reagieren soll, gibt es zwar keine Compilerfehler, passieren tut allerdings auch nichts!

    case WM_RBUTTONDOWN:
    			{
    				PostQuitMessage (0);
    				return (0);
    			};
    

    Funktioniert einfach nicht, selbst wenn ich mich mit der Maus im Fenster befinde.



  • Hallo Schlurmann,

    ich glaube du machst folgenden Fehler:
    Du fügst den Case-Zweig bei dem zweiten Switch ein und das kann nicht funktionieren, da wParam nie WM_RBUTTONDOWN enthalten wird. Du musst diesen Zweig einfach in dein erstes switch mit einfügen.

    Falls du den Case-Zweig doch innerhalb des ersten switch gesetzt hast, ist das break dein Problem. Die Abarbeitung der kompletten Switch-Kontroll-Struktur wird durch dieses break abgebrochen. Setze das break einfach mit in den davorstehenden Anweisungsblock.



  • Hey danke WilMen, funktioniert!

    Das FindWindow Problem besteht allerdings. Ich suche nach einer Lösung ein Window zu aktivieren (z.B. das Browserfenster) oder einfach die Tastenbefehle (LBUTTONDOWN -> Funktion) allgemein gültig zu machen, also nicht nur im erzeugten Fenster.


  • Mod

    SetForegorundWindow ist nicht grundsätzlich mehr arlaubt seit W2K!
    Es soll verhindern, dass ein User in der aktuellen Tätigkeit gestört wird und das ist gut so.
    Es gibt nichts nervenderes als ein Programm, was in den Vordergund hüpft wen ich gerade hier im Browser etwas schreibe...

    Warum möchtest Du das?
    Wie steht es mit FlashWindow?

    Es gibt eine Möglichkeit über AttachThreadInput SetForegroundWindow zu erzwingen, alerdings ist das nicht die feine englische Art!

    BOOL ForceSetForegroundWindow(HWND hWnd) 
    { 
         // Ist das Fenster gültig 
         if (!hWnd || !::IsWindow(hWnd)) 
             return FALSE; 
    
         // Aktuelle Werte bestimmen 
         HWND hCurrentWnd  ::GetForegroundWindow(); 
         if (hCurrentWndNULL) 
             /* Wir können einfach das neue ForeGroundWindow setzen 
              * da es aktuell keines gibt */ 
              return ::SetForegroundWindow(hWnd); 
    
         /* Bestimme Thread und Prozess des aktuellen ForeGroundWindows 
          * damit wir sehen können was zu tun ist und auf welchen 
          * ThreadInput wir uns draufhängen */ 
         DWORD   dwCurrentProcessId, 
                 dwCurrentThreadId  ::GetWindowThreadProcessId(hCurrentWnd, 
    &dwCurrentProcessId); 
    
         /* Das ganze ist nur notwendig, wenn der aktuelle Thread 
          * nicht zu dem Process gehört den wir aktivieren 
          * wollen */ 
         DWORD dwHwndProcessId; 
         ::GetWindowThreadProcessId(hWnd, &dwHwndProcessId); 
    
         // Prüfe ob dies der selbe Process ist 
         BOOL bReturn  FALSE; 
         if (dwHwndProcessIddwCurrentProcessId) 
             /* Normale Funktion verwenden, da die Prozesse sowieso 
              * die selben sind */ 
              bReturn  ::SetForegroundWindow(hWnd); 
         else 
         { 
             // Meinen Thread bestimmen 
             DWORD   dwMyThreadId  ::GetCurrentThreadId(); 
    
             /* Unter Windows 2000 gibt es dazu eine Sperre, diese 
              * kann jedoch umgangen werden indem wir uns kurz auf den 
              * selben ThreadInput der aktuell im ForeGround ist attachen. 
              * Damit gehören wir beide zum selben ThreadInput und können 
              * SetForeGroundWindow durchführen */ 
             if (::AttachThreadInput(dwMyThreadId,dwCurrentThreadId,TRUE)) 
             { 
                 // Nun dürfen wir das, also bringen wir uns in den Foreground 
                 bReturn  ::SetForegroundWindow(hWnd); 
    
                 // Nun heben wir den Attach einfach wieder auf 
                 ::AttachThreadInput(dwMyThreadId,dwCurrentThreadId,FALSE); 
             } 
             else 
             { 
                 /* AttachThreadInput ist schief gegangen dann versuchen 
                  * wir es eben normal */ 
                 bReturn  ::SetForegroundWindow(hWnd); 
             } 
         } 
    
         // Und exit 
         return bReturn; 
    }
    


  • Mir geht es einfach darum, die Tastenbedingungen wie LBUTTONDOWN allgemein gültig zu machen, also wenn ich das Programm anhabe soll es in jedem Fenster funktionieren. Alternativ wäre die Idee eben das Fenster, in dem ich die Tastenbedingungen benutzen möchte, zu aktivieren, also als wenn ich es normal in der Taskleiste anklicke, also suche ich entweder nach einem Beispiel Code für FindWindow oder eben nach einer möglichkeit das Programm überall wirken zu lassen.



  • Professor Schlurmann schrieb:

    (...) oder eben nach einer möglichkeit das Programm überall wirken zu lassen.

    Das Verhalten eines Programmes bei z.B. WM_KEYDOWN lässt sich *nur* bei selbstgeschriebenen Programmen festlegen.
    Die WinAPI bietet keine Möglichkeiten, die Reaktion auf z.B. WM_KEYDOWN allgemeingültig für alle laufenden Programme zu machen.
    Und das ist auch gut so. 🙂



  • merker schrieb:

    Die WinAPI bietet keine Möglichkeiten, die Reaktion auf z.B. WM_KEYDOWN allgemeingültig für alle laufenden Programme zu machen.
    Und das ist auch gut so. 🙂

    Das ist eine Falschinformation! Es gibt Hooks.



  • WebFritzi schrieb:

    Das ist eine Falschinformation! Es gibt Hooks.

    Hooks können Botschaften manipulieren.
    Sie beeinflussen aber nicht die Art und Weise wie eine Anwendung auf Botschaften zu reagieren hat.



  • Das heißt also, ich kann z.B. nicht auf mein Browserfenster zugreifen, und dort Mausbewegungen ausführen lassen?



  • Doch, schon. Mausbewegungen auf dem Browserfenster ausführen lassen, geht.
    Aber Du kannst nicht festlegen, was das Browserfenster machen soll wenn z.B. die linke Maustaste gedrückt wird.



  • Ich habe die Aufgabe mittels eines Taskswitchers(im Hintergrund) jeweils eine aus mehreren gleichzeitig laufenden Anwendungen in den Vordergrund zu bringen.
    Dabei benutze ich die API-Funktion FindWindow() und SetForegroundWindow() bzw. ForceSetForegroundWindow().
    Leider passiert es hin und wieder, dass das Window-Handle der betreffenden Anwendung zwar mit FindWindow() ermittelt werden konnte, aber die Funktion SetForegroundWindow() ein zweites, vorher noch nicht dagewesenes undefiniertes Fenster erzeugt(es existieren dann 2 Fenster "palTitle" aber nur ein Prozess "pal.exe") und dieses in den Vordergrund bringt.

    Wie kann es denn zu so einem ungewollten Verhalten kommen?
    Kann mir jemand helfen ?


Anmelden zum Antworten