This is an improved fix for menu tracking problems in IDA. My first solution, which was to use GetCursorPos() was rejected because it didn't use the position of the mouse cursor at the time the menu message was received, among other reasons. Mike Jackson suggested another possible solution using ClientToScreen(). I investigated this as well. Unfortunately, it doesn't work either. The problem is, for most menus, the coordinates are already in screen coordinates.. so calling ClientToScreen() again throws everything off. I wrote a program in windows which had owner drawn menu items. Whenever I received the WM_DRAWITEM message: 1) I called GetCapture(), and compared it with the hwnd of main window containing the menu. It pops up a message box if they are different. 2) I then called SetCapture() with the HWND of the menu item itself. This approximately simulates what IDA is doing. The message box never popped up. This shows that even though the capture was changed in one WM_DRAWITEM, windows had reset the capture to the window containing the menu by the time of the next one. I also checked the messages _were_ being sent using Spy++ (in case of a programming error). This patch attempts to replicate this functionality. It resets the captured window immediately after issuing the WM_DRAWITEM message, in case the application has changed it. Note this code only occurs on WM_OWNERDRAW menu items, as this should be the only situation where this problem can occur.
Index: controls/menu.c =================================================================== RCS file: /home/wine/wine/controls/menu.c,v retrieving revision 1.171 diff -u -r1.171 menu.c --- controls/menu.c 26 Nov 2003 05:08:48 -0000 1.171 +++ controls/menu.c 6 Dec 2003 17:16:56 -0000 @@ -178,6 +178,8 @@ DWORD WINAPI DrawMenuBarTemp(HWND hwnd, HDC hDC, LPRECT lprect, HMENU hMenu, HFONT hFont); +static void MENU_SetCapture( HWND hwnd ); + /********************************************************************* * menu class descriptor */ @@ -1176,6 +1178,7 @@ dis.hDC, dis.rcItem.left, dis.rcItem.top, dis.rcItem.right, dis.rcItem.bottom); SendMessageW( hwndOwner, WM_DRAWITEM, 0, (LPARAM)&dis ); + MENU_SetCapture(hwndOwner); /* Fall through to draw popup-menu arrow */ }