DialogMessage in DLL-Injection
-
Hallo,
bin mal wieder am experimentieren mit der WIN-API. Folgendes Szenario:
Ich habe ein externes Programm (kein Sourcecode verfügbar), in welches ich mittels DLL-Injection Funktionen einbaue. Dafür erstelle ich in DllMain meine GUI und lade sie mittels SetParent in das entsprechende externe Fenster.
Dementsprechend benutzen meine eigenen Fenster auch die Messagequeue des externen Fensters. Das funktioniert soweit auch.
Jetzt will ich aber Unterfenster als Dialogs einbauen. Problem ist, diese empfangen keine Kommandos wie wenn man z.B. TAB drückt. Normalerweise kann man ja mit TAB durch die verschiedenen Controlls eines Dialogs durchswitchen.
Im "normalen" Fall muss man dafür ja nur die Message-Loop entsprechend erweitern:
while (GetMessage(&msg, NULL, 0, 0) > 0) { if (!TranslateAccelerator(wnd, hacc, &msg)) { if (IsDialogMessage(myDialog, &msg)) // Dialog continue; TranslateMessage(&msg); DispatchMessage(&msg); } }
Mein Problem ist jetzt aber, dass ich ja keinen Zugriff auf die Message-Loop habe, da die ja in dem externen Programm läuft und dementsprechend kann ich dort das benötigte
if(...) continue;
nicht einbauen.Wie könnte man hier vorgehen um das trotzdem zu erreichen?
-
Update: Habe inzwischen einen Ansatz gefunden, mit einer Message-Hook (die per
WH_GETMESSAGE
installiert wird):LRESULT CALLBACK MyMessageHook(int code, WPARAM wParam, LPARAM lParam) { MSG *msg = reinterpret_cast<MSG*>(lParam); if (code == HC_ACTION && wParam == PM_NOREMOVE) { if (IsDialogMessage(myDialog, msg)) { msg->message = WM_NULL; msg->lParam = 0L; msg->wParam = 0; } } return CallNextHookEx(OriginalMessageHandler, code, wParam, lParam); }
Damit kann man jetzt durch das Control durchtaben, es gibt mit dieser Methode aber ein neues Problem:
Aus mir unerfindlichen Gründen wird bei jeder Textbox des betreffenen Controls, wenn man einen Buchstaben eingibt, dieser viermal in das Textfeld eingetragen. Also ich tippe auf der Tastatur einmal auf "a" und in die Textbox werden "aaaa" eingetragen.
Jemand eine Idee woran das liegen könnte bzw. wie man das beheben kann? (return 0 bzw. 1 in dem inneren if habe ich schon getestet, ändert leider nichts)
-
Deine Nachrichtenbehandlung wird einfach nicht korrekt sein.
Dir ist hoffentlich klar, dass IsDialogMessage x andere Nachrichten auslöst?Dein Code ist in sofern schon gefährlich, weil es eben alle Nachrichten behandelt. Warum behandelst Du nicht nur die, die auch an das Fenster oder ein Kindfenster gehen?
-
Martin Richter schrieb:
Dir ist hoffentlich klar, dass IsDialogMessage x andere Nachrichten auslöst?
Ja, ist mir klar.
Martin Richter schrieb:
Dein Code ist in sofern schon gefährlich, weil es eben alle Nachrichten behandelt. Warum behandelst Du nicht nur die, die auch an das Fenster oder ein Kindfenster gehen?
Naja, weil das doch die übliche Implementierung ist (oder verstehe ich da was falsch)? Normalerweise schreibt man ja etwas wie
while (GetMessage(&msg, NULL, 0, 0) > 0) { if (IsDialogMessage(myDialog, &msg)) // Dialog continue; TranslateMessage(&msg); DispatchMessage(&msg); }
Hier wird ja auch für alle erstmal IsDialogMessage aufgerufen (und halt Translate und DispatchMessage übersprungen falls es eine Dialog-Message war).
Die Nachricht anhand der Fenster zu filtern habe ich schon getestet (etwa so):
LRESULT CALLBACK MyMessageHook(int code, WPARAM wParam, LPARAM lParam) { MSG *msg = reinterpret_cast<MSG*>(lParam); if (code == HC_ACTION && wParam == PM_NOREMOVE) { // Alternativ auch mit IsChild / Auflistung aller beteiligten Windows etc. if (msg->hwnd == myDialog && IsDialogMessage(myDialog, msg)) { msg->message = WM_NULL; msg->lParam = 0L; msg->wParam = 0; } } return CallNextHookEx(OriginalMessageHandler, code, wParam, lParam); }
Funktioniert aber nicht, es werden trotzdem 4 Buchstaben übertragen.
-
Nö. Schreibt man nicht. Man filter auf die entsprechenden Dialoge oder Fenster
-
Martin Richter schrieb:
Nö. Schreibt man nicht. Man filter auf die entsprechenden Dialoge oder Fenster
Wo steht das? Auf MSDN finde ich nur Beispiele wo nicht nochmal explizit gefiltert wird... ich bin davon ausgegangen dass das richtig ist?
Außerdem filtert doch IsDialogMessage schon, schließlich nimmt das ja als Parameter das Handle auf die Dialog-Message:
MSDN schrieb:
Determines whether a message is intended for the specified dialog box and, if it is, processes the message.
Aber unabhängig davon löst filtern das Problem nicht, es scheint also mit etwas anderem zusammen zu hängen...
-
Dann sind es vermutlich die extra Nachrichten, die ausgelöst werden.
Wundert mich aber.Hast Du ein minimales Sample?
-
Noch mal zum FIltern. Ich würde grundsätzlich schon mal nur auf WM_KEY... Nachrichten filtern.
Also ich habe mal etwas gegoogelt und es müsste so gehen. Der Code sieht "vernünftig" aus.
https://www.falconview.org/svn/FalconView/trunk/public/fvw_core/Collaborate/DialogMessageHook.cpp
-
happystudent schrieb:
LRESULT CALLBACK MyMessageHook(int code, WPARAM wParam, LPARAM lParam) { MSG *msg = reinterpret_cast<MSG*>(lParam); if (code == HC_ACTION && wParam == PM_NOREMOVE) { // Alternativ auch mit IsChild / Auflistung aller beteiligten Windows etc. if (msg->hwnd == myDialog && IsDialogMessage(myDialog, msg)) { msg->message = WM_NULL; msg->lParam = 0L; msg->wParam = 0; } } return CallNextHookEx(OriginalMessageHandler, code, wParam, lParam); }
PM_NOREMOVE => PM_REMOVE
-
Martin Richter schrieb:
Noch mal zum FIltern. Ich würde grundsätzlich schon mal nur auf WM_KEY... Nachrichten filtern.
Also ich habe mal etwas gegoogelt und es müsste so gehen. Der Code sieht "vernünftig" aus.
https://www.falconview.org/svn/FalconView/trunk/public/fvw_core/Collaborate/DialogMessageHook.cpp
hustbaer schrieb:
PM_NOREMOVE => PM_REMOVE
Danke, die Kombination aus beidem wars.
Mit PM_REMOVE statt PM_NOREMOVE kann man Tab benutzen und korrekt nur einen Buchstaben eingeben, und ohne auf WM_KEY* zu filtern stürzt das Ganze ab.
Aber jetzt geht es, vielen Dank