WndProc Windows Messages



  • @JamesChester
    Statt Application->Run() kannst du die Nachrichten auch selbst behandeln:

    MSG msg;
    for( bool done = false; !done; )
    {
       BOOL result = GetMessage( &msg, nullptr, 0, 0 );
       if( result == 0 )
       {
          // WM_QUIT 
       }
       else if( result == -1 )
       {
          // sonstiger Fehler
       }
       else
       {
          TranslateMessage( &msg );
          DispatchMessage( &msg );
       }
    }
    

    Ob das zu irgendwelchen Problemen führt kann ich dir jetzt nicht sagen, ich habe in normalen Desktop Anwendungen bisher nichts feststellen können.



  • Vielleicht sollte ich mal versuchen das Problem anders bzw. etwas genauer zu beschreiben.

    Letztendlich geht es um automatisierte Oberflächentests.

    Ich habe ein externes Tool mit dem ich meine Anwendung automatisch testen will. Dieses Tool benötigt eine eindeutige ID von jedem Objekt auf dem Formular. Leider liefern mir Anwendungen, die im RadStudio Programmiert sind, keine eindeutige ID. Der Name, der eigentlich eindeutig sein sollte, wird mit dem Caption belegt. Wenn ich also drei Buttons auf der Oberfläche habe die das Caption "Button" haben, können die nicht unterschieden werden.

    Meine Idee ist also, dass ich WM_GETOBJECT von den Objekten abfange und den Namen mit dem richtigen Wert überschreibe.

    Zum testen habe ich einen eigenen Button erzeugt (von TCustomControl abgeleitet) der genau das macht was ich haben will.

    Es wäre jetzt aber zu aufwendig, alle Objekte (TEdit, TButton TCheckbox etc.) abzuleiten. Daher die frage ob ich noch von einer anderen Stelle an die Objekte und somit an die Nachricht komme.

    ich habe schon versucht über über Hooks an die Daten zu kommen, kenne mich aber nicht wirklich damit aus und weiß auch nicht ob das zielführend ist.

    	hMouseHook = SetWindowsHookEx( WH_CALLWNDPROCRET, mouseProc, hInstance, GetCurrentThreadId() );
    


  • Was genau ist denn eine eindeutige ID? Muss die numerisch sein oder gehen aus strings? Alle von TComponent abgeleiteten Klasse haben einen eindeutigen Namen, darüber müsstest du deine Controls identifizieren können.
    Über die Eigenschaften ComponentCount und Components[] hast du Zugriff auf alle Kindkomponenten.



  • Es gehen auch Strings. Innerhalb der VLC sind die Namen auch eindeutig, aber irgend ein schlauer Programmierer von Embarcadero hat sich gedacht er überschreibt die Namen besser mit den Beschriftungen.
    Mit dem Inspect Tool von Microsoft kann man sich von allen Objekten auf einem Formular die Parameter anzeigen lassen. Einer der angezeigten Parameter heiß auch "Name". Nur leider steht da nicht der Name vom Objekt drin, sondern das Caption (z.B. bei einem Button). Bei TEdit Objekten wird als Name ein leerer String übertragen.

    Daher vermute ich mal das diese ganzen Mechanismen für Automatisierte Tests noch nicht wirklich fertig Programmiert wurden von Embarcadero. Das versuche ich jetzt irgendwie auszugleichen und das scheitert daran das ich nicht an die richtigen nachrichten komme.

    Am einfachsten wäre es wenn ich die WndProc von TWinControl oder TComponent direkt bearbeiten könnte. Ich hab aber keine Ahnung wie ich nach Bearbeitung der z.B. Vcl.Controls.pas die neu Compiliert bekomme.



  • Zum Verständnis:
    Du hast ein Tool zum Testen von GUIs, das soll skriptgesteuert oder wie auch immer auf verschiedene Bedienelemente klicken. Dazu brauchst du eine ID, das das Element kennzeichnet, damit das Tool draufklicken kann?



  • Ja. genau so ist es.



  • Ah, ok. WM_GETOBJECT ist Teil der MS UI Automation, und da kenne ich mich leider überhaupt nicht aus.
    Ich habe gehofft, dass das noch iwie anders zu lösen ist, aber ich fürchte, das Tool setzt Unterstützung für die Automatisierung voraus, die die VCL nicht anbietet.



  • @JamesChester
    Dann schau dir bitte mal das Ereignis WindowProc an, das bietet jedes TWinControl an und das ist im Prinizp nix anderes als die WndProc der Komponente. Das kann man sich auf eine eigene TWndMethod- Methode "umbiegen", die du in der zugehörigenTForm Instanz definierst:
    Hier mal als Beispiel für eine ComboBox:

    TWndMethod m_OrgCBWindowProc;
    
    __fastcall TFrmMain::TFrmMain(TComponent* Owner)
    {
        m_OrgCBWindowProc = ComboBox1->WindowProc;
        ComboBox1->WindowProc = CBWndProc;
    
    }
    
    void __fastcall TFrmMain::CBWndProc(Messages::TMessage& Message)
    {
    ....
        m_OrgCBWindowProc (Message);
    }
    
    


  • @Burkhi
    Danke, das hat weitergeholfen. War mir nicht klar das es so möglich ist.

    Wenn ich mal eine gescheite klasse draus gemacht habe, kann ich den Quelltext ja mal posten.



  • @JamesChester
    Damit habe ich schon einige Sachen angestellt, z.B. eine ComboBox, die als Suchbox umfunktioniert wird, die zeigt dann in der ausgeklappten ListBox nur die Einträge, in denen ein Teilstring von der Eingabe vorhanden ist.😉 😉


Log in to reply