GetMenuItemInfo liefert String von Items nicht
-
Bei mir funktioniert der Code, sofern:
a) die Abbruchbedingung mii.wID < 60000 || mii.wID > 69999 so wirklich stimmt,
b) die Größe von cBuffer1 richtig initialisiert bzw. definiert wurde.Allerdings habe ich den Code nur in einer Nicht-Unicode-Anwendung (mit UCHAR statt WCHAR) getestet.
Versagt denn GetMenuString() ebenfalls?
Walter Zorn
-
Walter Z schrieb:
Bei mir funktioniert der Code, sofern:
a) die Abbruchbedingung mii.wID < 60000 || mii.wID > 69999 so wirklich stimmt,
b) die Größe von cBuffer1 richtig initialisiert bzw. definiert wurde.Allerdings habe ich den Code nur in einer Nicht-Unicode-Anwendung (mit UCHAR statt WCHAR) getestet.
Versagt denn GetMenuString() ebenfalls?
Walter Zorn
a) hat mit dem Problem ja nichts zu tun.
b) selbst wenn ich dwTypeData und cch auf 0 setze funktioniert es nicht wie es sollGetMenuString() funktioniert ebenfalls nicht.
Hast du das mit einem (am besten dynamisch erzeugten) Menü eines anderen Programms getestet?
-
Hast du das mit einem (am besten dynamisch erzeugten) Menü eines anderen Programms getestet?
Ja, mit einem dynamisch erzeugten Menu in einem anderen Programm (nicht einer anderen Instanz des selben Programms).
Allerdings liefert MN_GETHMENU bei mir auch auf XP NULL zurück, weshalb ich auf GetMenu() zurückgegriffen habe.
Hier sicherheitshalber nochmal der getestete Code. (AlertMain (Wrapper für MessageBox) und GetLastErrorString sind anwendungseigene Funktionen.)
#ifndef MN_GETHMENU #define MN_GETHMENU 0x01E1 #endif HWND hWnd2; HMENU hMenu; hWnd2 = FindWindow("MDIMAINWZMdi0.1.0.0", NULL); if(hWnd2 == NULL) AlertMain("hWnd2 ist NULL"); else { //hMenu = (HMENU)SendMessage (hWnd2, MN_GETHMENU, 0, 0); // hWnd2 stimmt, hMenu stimmt hMenu = GetMenu (hWnd2); // hWnd2 stimmt, hMenu stimmt if(hMenu == NULL) AlertMain("hMenu ist NULL"); else if(!IsMenu(hMenu)) AlertMain("hMenu kein Menu"); else { UCHAR cBuffer1[4096]; UINT iCount, i; MENUITEMINFO mii; iCount = GetMenuItemCount (hMenu); for (i = 0; i < iCount; i++) { memset(&mii, 0, sizeof(mii)); mii.cbSize = sizeof(mii); mii.fMask = MIIM_STRING | MIIM_ID; mii.dwTypeData = cBuffer1; // TCHAR cBuffer1[4096] mii.cch = sizeof(cBuffer1) / sizeof(UCHAR); if (!GetMenuItemInfo (hMenu, i, TRUE, &mii)) { if(GetLastErrorString(cBuffer1, sizeof(cBuffer1)-1)) AlertMain(cBuffer1); else AlertMain("GetMenuItemInfo() und GetLastErrorString() fehlgeschlagen"); continue; } // GetLastError() ist hier 0 - kein Fehler also // Problem: mii.cch ist 0 und cBuffer1 wurde nicht geändert if (mii.fType & MF_SEPARATOR || !mii.cch /* || mii.wID < 60000 || mii.wID > 69999 */ ) continue; MessageBox (0, cBuffer1, 0, 0); // nie erreicht } } }Walter Zorn
-
Hast du zufällig ICQ und könntest es damit probieren? Vielleicht haben die die MFC-Menüklasse überladen und die Strings sind wirklich leer?
Dann müsste ich mich ja von meinem Prozess in den ICQ-Prozess hacken und aus dem Speicher lesen, was ich suche
GetMenu() funktioniert beim ICQ-Fenster gar nicht. Liegt vielleicht daran, dass es ein Popup-Menü ist?
-
Soweit ich weiß, kommt man sowohl mit GetMenu als auch mit MN_GETHMENU nur an Menus heran, die explizit dem Fenster (per SetMenu) bzw. der Fensterklasse zugewiesen wurden.
Bei Popup-Menus ist das normalerweise nicht der Fall, sie haben lediglich ein bestimmtes Fenster als Parent, an das sie zwar die Menu-Kommandos senden, mit dem sie aber, soweit ich weiß, nicht direkt assoziiert sind (per Zeiger in der windowsinternen Datenstruktur für jedes Fenster).
Ob man mit EnumChildWindows() an Popupmenus eines Fensters herankommt, habe ich nicht ausprobiert, glaube aber eher nicht, dass das funktioniert. Der Name der Menu-Fensterklasse ist übrigens "#32768", vielleicht hilft das irgendwie weiter - oder das Abfangen von WM_INITMENUPOPUP per Hooking...
Walter Zorn
-
Walter Z schrieb:
Der Name der Menu-Fensterklasse ist übrigens "#32768", vielleicht hilft das irgendwie weiter - oder das Abfangen von WM_INITMENUPOPUP per Hooking...
Über die Fensterklasse komme ich bereits an das Fenster des Popup-Menüs, an das ich MN_GETHMENU sende, um den HMENU zu erhalten. Die anderen Daten, die GetMenuItemInfo liefert, sind ja auch korrekt, nur die Strings eben falsch bzw. leer

-
Kann es sein, dass es sich um ein Ownerdraw-Menu handelt? Dann sollten die Flags
MIIM_DATA | MIIM_STATE | MIIM_TYPE
für mii.fMask
und die Verwendung von mii.dwItemData statt mii.dwTypeData weiterhelfen.Problematisch wird's halt nur, wenn dwItemData auf eine Struktur mit Unterelementen statt direkt auf einen String zeigt...
Walter Zorn
-
dwItemData wollte ich zuerst verwenden. Allerdings zeigt der Pointer ja auf einen Speicherbereich von ICQ.
Ich muss mir mal anschauen was OwnerDraw-Menüs sind und wie ich auf den Speicher fremder Programme direkt zugreife.
Danke so weit für deine Hilfe. Falls dir noch etwas einfällt - immer her damit
-
Allerdings zeigt der Pointer ja auf einen Speicherbereich von ICQ.
Ups, stimmt eigentlich.
und wie ich auf den Speicher fremder Programme direkt zugreife
GetWindowThreadProcessId(),
OpenProcess(),
ReadProcessMemory()und dann den geschriebenen Puffer auf einen plausiblen Menustring validieren

Walter Zorn
-
Yeah, per dwItemData und ReadProcessMemory komme ich an die IDs, die ich brauche

Danke vielmals für deine Hilfe!