News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

Dynamic Menu

Started by jbullard, August 25, 2006, 05:37:50 AM

Previous topic - Next topic

jbullard

Alright.  So I have a tray icon, a menu, and then another submenu.  However, the submenu is dynamic which means I don't have a ID for it.  So how would you go about getting the text of the menu item that was clicked.  Here is what I tried but for some reason it just gives me an error.  Maybe someone can show me what I am doing wrong.


                    invoke GetCursorPos, ADDR itemPT
                    invoke MenuItemFromPoint, NULL, hwndDeskMenu, itemPT.x, itemPT.y
                    invoke GetMenuString, hwndDeskMenu, eax, NULL, 512, MF_BYPOSITION
                    invoke MessageBox, hWnd, eax, ADDR appName, MB_OK


Thanks for any help.

Jason

Tedd

GetCursorPos ==> the screen coordinates of the cursor
MenuItemFromPoint ==> If hMenu specifies a menu bar, this parameter is in window coordinates. Otherwise, it is in client coordinates.

Hint: ScreenToClient :wink
No snowflake in an avalanche feels responsible.

jbullard

Will this work eventhough it is a tray menu?

Thanks,
Jason

zooba

The ID is either returned or set (can't remember which) when you create the menu. Perhaps you could post the code from where you are creating the menu.

AFAICT, Tedd's solution will work, but let's be honest, it's a bit of a hack :wink

Cheers,

Zooba :U

jbullard

After taking a look at the ScreenToClient and MenuFromPoint I realized that I do not need the handle to the window, and to leave that null cause then it automatically defaults to a popup menu.  However, I am still getting -1 when I call MenuFromPoint after calling ScreenToClient or not.  Here is what I have so far.


LOCAL pt1:POINT

.ELSEIF uMsg == WM_COMMAND
.IF lParam == 0
mov eax, wParam

.IF ax == IDM_EXIT
.ELSEIF ax == IDM_CNTRL1
.ELSEIF ax == IDM_CNTRL2
.ELSE
invoke GetCursorPos, ADDR pt1
.IF eax != 0
;invoke ScreenToClient, hWin, ADDR pt1
;.IF eax != 0
invoke MenuItemFromPoint, NULL, hwndDeskMenu, ADDR pt1.x, ADDR pt1.y
.IF eax != -1
invoke GetMenuString, hwndDeskMenu, eax, ADDR buffer, 512, MF_BYPOSITION
invoke MessageBox, hWin, ADDR buffer, ADDR appName, MB_OK
.ELSE
invoke MessageBox, hWin, ADDR appName, ADDR appName, MB_OK
.ENDIF
;.ENDIF
.ENDIF
.ENDIF
.ENDIF
.ELSEIF


I just don't know what I am missing here.  Cause if I replace eax in GetMenuString with 1 then it returns the menu string for that position.  The MenuItemFromPoint does not seem to be working for me.

Jason

zooba

Having thought a little bit more, MenuItemFromPoint probably will not work, since by the time you receive the message it's already disappeared.

As part of the MENUITEMINFO structure passed with InsertMenuItem you can set the wID parameter to whatever value you like (remember to set MIIM_ID in fMask) and this will be in AX on the WM_COMMAND message (the uIDNewItem parameter for InsertMenu is the same thing).

Cheers,

Zooba :U

Edit: Just noticed that you're passing the address of pt1.x and pt1.y - try passing the values instead

drizz

you wanted dyn menu and custom font? see this example.


[attachment deleted by admin]
The truth cannot be learned ... it can only be recognized.

ToutEnMasm


Good sample on how to create a dynamic menu and how make a list of the active process.
       
                                             ToutEnMasm

drizz

thanks, i wrote it long ago when i was on win98 (it used to show file icons too).
It needs a few adjustments (like: elevate priviledge for process list, better WM_MEASUREITEM handling)
to be of any (frequent) use.
The truth cannot be learned ... it can only be recognized.

jbullard

Thanks for the example.  It sorta helped out.  Mostly just rampaged through it looking for the parts.  However, I noticed that you were using ebx where as I was trying to use ax.  So this is what I did.


        .IF ax == IDM_EXIT
        .ELSE
          invoke GetMenuString, hwndDeskMenu, ebx, ADDR buffer, 512, MF_BYPOSITION
          invoke MessageBox, hWin, ADDR buffer, ADDR appName, MB_OK


Now that works to a degree.  In my menu (dynamic) I currently have three values (Default, Register, Unregister).  No matter which spot I click on it always returns Default as the string.  I am sure someone will be able to spot where I have messed up.  Thanks for all the help guys/gals.

Jason

Tedd

Quick thought..

I presume your aim for this is to react to which menu item is selected.
But your 'problem' is that the menu is dynamic, and so you don't know the position each item will be in.
However, when constructing the menu (using AppendMenu or InsertMenu?) you get to specify an ID for each inserted menu-item, along with the associated text, etc. So couldn't oyu simply give the same ID to the individual items each time (according to their action, rather than position)?? Then when the given item is clicked, the resulting identifier will be passed-on in the same way as any other menu-id. And identifying the menu-item is implicit.

invoke AppendMenu, hMenu,MF_STRING,IDM_DEFAULT,ADDR str_default
.IF (want_register_item)
    invoke AppendMenu, hMenu,MF_STRING,IDM_REGISTER,ADDR str_register
.ENDIF
.IF (want_unregister_item)
    invoke AppendMenu, hMenu,MF_STRING,IDM_UNREGISTER,ADDR str_unregister
.ENDIF

If you receive IDM_REGISTER, then you know the "Register" item has been selected.

Is there a reason you can't do it like this?
No snowflake in an avalanche feels responsible.