Fenster fangen - zu unzuverlässig



  • Hallo,

    ich habe mir eine Funktion geschrieben, die das Fenster einer externen Anwendung fangen soll sobald dieses geöffnet wird. Momentan mache ich das etwa so:

    HWND myWindow = NULL;
    
    while (myWindow == NULL) {
        myWindow = FindWindow(NULL, L"Name des Fensters");
        Sleep(5);
    }
    

    Das funktioniert schonmal, auch wenn man (vermutlich wegen dem Sleep) eine kurze Zeitverzögerung hat die ein kurzes flackern verursacht.

    Problematischer wird es jetzt wenn myWindow vorliegt. Auf diesem Fenster befinden sich nämlich verschiedene Child-Fenster, die ich auch alle korrekt zuordnen möchte/muss. Etwa zwei Edit-Controls, die sich nur aufgrund ihrer Position unterscheiden.

    Diese versuche ich jetzt wieder folgendermaßen zu fangen:

    HWND myEditWindow1 = NULL;
    HWND myEditWindow2 = NULL;
    
    while (myEditWindow1 == NULL && myEditWindow2 == NULL) {
        // 1. EnumChildWindows
        // 2. Vergleiche die Position der (einzigen) zwei Edit-Controls
        // 3. Weise diese den Variablen myEditWindow1 und myEditWindow2 zu
    
        Sleep(5);
    }
    

    Problem ist jetzt, dass die Positionen der Child-Fenster bei Erstellung ihres Parents anscheinend noch nicht ihre endgültige Position haben. Auch die Reihenfolge ist anscheinend immer unterschiedlich. Daher ist es momentan reine Glücksache dass die richtigen Fenster gefunden und zugewiesen werden.

    Wie löst man so etwas sicher (also richtig)? Kann man irgendwie überprüfen ob ein Fenster mit der Erstellung seiner Childs "fertig" ist und diese ihre endgültige Position eingenommen haben?

    Oder gibts noch andere, bessere Techniken?



  • ID herausfinden (Spy++, res.editor..) und Handle mit http://msdn.microsoft.com/en-us/library/windows/desktop/ms645481 holen.



  • Hallo,

    hab das ausprobiert und die Methode mit GetDlgItem hat leider genau das gleiche Problem wie meine Methode mit EnumChildWindows.

    Und zwar scheinen die Child Windows nach der ersten While Schleife einfach noch nicht erstellt zu sein wenn man die Dauer des Sleep zu gering einstellt. Also hier:

    HWND myWindow = NULL;
    
    while (myWindow == NULL) {
        myWindow = FindWindow(NULL, L"Name des Fensters");
        Sleep(5);
    }
    
    // Ab hier liegt zwar myWindow vor, dessen Childs existieren aber noch nicht zwangsläufig
    HWND myEditWindow1 = GetDlgItem(myWindow, ITEM_ID); // <- Hier knallts dann, myEditWindow1 ist je nach Glück/Pech NULL
    

    Eine Erhöhung der Sleep Dauer löst das Problem zwar einigermaßen, aber eben nicht perfekt. Die Dauer des Sleep will ich außerdem aus zwei Gründen nicht erhöhen. Erstens erhöht sich damit die Verzögerung der Funktion und damit das bereits beschriebene Flackern; zweitens ist selbst ein Sleep von 500 ms nicht immer und unter allen Umständen ausreichend um zu gewährleisten dass das oben beschriebene Problem nicht mehr auftritt.

    Das Parent Fenster benötigt nämlich anscheinend je nachdem wie aufwendig die Daten sind welche es darstellt sehr unterschiedlich lange, bis alle seine Childs erstellt sind.

    Daher brauche ich irgendeine Method die (am besten synchron) wartet bis das Fenster sicher alle Childs auch erstellt hat.



  • Von wegen happystudent du bist gerade bestimmt gar nicht happy weil dein Programm nicht zuverlässig funktioniert.



  • Dann warte doch, sobald du das Fenster hast, in ner Schleife auf alle Childs (zB EnumChildWindows bis alle IDs da sind, oder eben einzeln bis GetDlgItem für alle nötigen Controls nicht Null liefert).

    Oder sauberer, indem du das Programm erweiterst (Hooks setzen etc. wenn du den Source nicht hast).



  • happystudent schrieb:

    ich irgendeine Method die (am besten synchron) wartet bis das Fenster sicher alle Childs auch erstellt hat.

    SetWinEventHook() mit EVENT_OBJECT_SHOW und/oder EVENT_OBJECT_CREATE.



  • Hi schrieb:

    Dann warte doch, sobald du das Fenster hast, in ner Schleife auf alle Childs (zB EnumChildWindows bis alle IDs da sind, oder eben einzeln bis GetDlgItem für alle nötigen Controls nicht Null liefert).

    Ok das funktioniert schonmal als schneller Fix.

    Werd mir demnächst dann aber mal SetWinEventHook() anschauen, das sieht vielversprechend aus.

    Danke für die Hilfe 🙂


  • Mod

    Bei der Fenstererzeugung ist ein CBT Hook am einfachsten. Und ist zuverlässig.


Log in to reply