First of all, is this the right place to post this? I would've thought that the MASM forum would be appropriate, but the description says "Please post technical questions in the general forum", so here goes:
I got an error trying to use the MENUITEMINFO structure. While the MSDN documentation (https://msdn.microsoft.com/en-us/library/ms647578(v=vs.85).aspx) shows 12 members, the MASM include file only has 11 (it's missing the last item, HBITMAP hbmpItem). Is this an error? should I just go ahead and fix my copy of the file?
:t good find
Hutch is a little slow getting around to things, sometimes
it's probably on his "to do" list
http://www.masmforum.com/board/index.php?topic=660.0 (http://www.masmforum.com/board/index.php?topic=660.0)
Microsoft keep adding bits to structures so an item that was correct can be missing an addition made later. Usually structures that change over time use the SIZEOF or similar to specify which version they are using.
it does have a cbSize member
Quote from: dedndave on March 23, 2015, 11:05:37 AM
it does have a cbSize member
Right, so does that mean that if you use an earlier (i.e., smaller) structure that it'll know to truncate it at the end? Not sure, since I was getting other errors before I fixed the structure.
Anyhoo, I patched my local copy. You might want to update the master copy someday ...
Quote from: dedndave on March 23, 2015, 10:58:12 AM
:t good find
Hutch is a little slow getting around to things, sometimes
it's probably on his "to do" list
http://www.masmforum.com/board/index.php?topic=660.0 (http://www.masmforum.com/board/index.php?topic=660.0)
Wow, 2005: a "little slow"?
Isn't there a corps of volunteers somewhere to do this stuff?
well, can't release a new masm32 package every time someone finds a flaw
of course, you can modify your own INC file
but, that makes you incompatible with other forum members
so - i usually create my own structure definition - and hopefully it gets fixed in a later rev
_MENUITEMINFO STRUCT
or something similar
NoCforMe,
Dave's solution is the right one but don't let me stop you from creating an up to date set of includes for Windows. These things are a genuine joy to maintain and if you get it slightly wrong it explodes in your face.
Quote from: NoCforMe on March 23, 2015, 10:44:47 AMI got an error trying to use the MENUITEMINFO structure.
What kind of error? If the size member is set, Windows shouldn't complain.
Re 2005: There was not a single reply to this post, so it probably went unnoticed. Go for the "genuine joy" ;-)
Quote from: jj2007 on March 23, 2015, 09:24:26 PM
Quote from: NoCforMe on March 23, 2015, 10:44:47 AMI got an error trying to use the MENUITEMINFO structure.
What kind of error? If the size member is set, Windows shouldn't complain.
Windows didn't complain; MASM did (too many initializers for a structure).
Heh; I ended up abandoning this project anyhow (I learned it's too big a pain in the ass to try to construct menus programmatically rather than as a linked resource.)
Quote from: NoCforMe on March 24, 2015, 12:29:46 PM(I learned it's too big a pain in the ass to try to construct menus programmatically rather than as a linked resource.)
Depends on your libraries ;-)
GuiParas equ "Hello jj2007", x650, y20, w200, h200, sWS_CAPTION OR WS_POPUPWINDOW, cblack, b00FFFFD0h
GuiMenu equ @File, &Open, &Save, -, E&xit, @Edit, Undo, Copy, Paste
include \masm32\MasmBasic\Res\MbGui.asm
Event Menu
Switch MenuID
Case IDM0
MsgBox 0, "Open", "Hi", MB_OK
Case IDM1
MsgBox 0, "Save", "Hi", MB_OK
Default
MsgBox 0, Str$("Menu #%i", MenuID), "Hi", MB_OK
Endsw
GuiEnd
i don't know that you need the functions that use that structure to create menus
this is a proc i use at initialization to create context menus
not much different from menu bar type menus
IDM_??? are menu id constants (equates)
sz???? are menu strings
;***********************************************************************************************
CreateContextMenus PROC
push ebx
push esi
INVOKE CreateMenu
xchg eax,ebx
;hmenuHiRes
INVOKE CreatePopupMenu
xchg eax,esi
mov hmenuContext,ebx
INVOKE AppendMenu,ebx,MF_POPUP,esi,NULL
mov hmenuHiRes,esi
INVOKE AppendMenu,esi,MF_STRING or MF_ENABLED,IDM_HRSETREF1,offset szMenuHR01
INVOKE AppendMenu,esi,MF_STRING or MF_ENABLED,IDM_HRSETREF2,offset szMenuHR02
INVOKE AppendMenu,esi,MF_STRING or MF_ENABLED,IDM_HRSETREF3,offset szMenuHR03
INVOKE AppendMenu,esi,MF_SEPARATOR,NULL,NULL
INVOKE AppendMenu,esi,MF_STRING or MF_ENABLED,IDM_HRADDSWLOW,offset szMenuHR04
INVOKE AppendMenu,esi,MF_STRING or MF_ENABLED,IDM_HRDELMARK,offset szMenuHR05
INVOKE AppendMenu,esi,MF_SEPARATOR,NULL,NULL
INVOKE AppendMenu,esi,MF_STRING or MF_GRAYED,IDM_HRENHANCE,offset szMenuHR06
INVOKE AppendMenu,esi,MF_SEPARATOR,NULL,NULL
INVOKE AppendMenu,esi,MF_STRING or MF_ENABLED,IDM_HIDECURS,offset szMenuHR08
;hmenuVblank
INVOKE CreatePopupMenu
xchg eax,esi
INVOKE AppendMenu,ebx,MF_POPUP,esi,NULL
mov hmenuVblank,esi
INVOKE AppendMenu,esi,MF_STRING or MF_ENABLED,IDM_HIDECURS,offset szMenuVP06
;hmenuVesoph
INVOKE CreatePopupMenu
xchg eax,esi
INVOKE AppendMenu,ebx,MF_POPUP,esi,NULL
mov hmenuVesoph,esi
INVOKE AppendMenu,esi,MF_STRING or MF_ENABLED,IDM_VEGRPHAUX,offset szMenuVP01
INVOKE AppendMenu,esi,MF_STRING or MF_ENABLED,IDM_VEGRPHREF1,offset szMenuVP02
INVOKE AppendMenu,esi,MF_STRING or MF_ENABLED,IDM_VEGRPHREF2,offset szMenuVP03
INVOKE AppendMenu,esi,MF_STRING or MF_ENABLED,IDM_VEGRPHREF3,offset szMenuVP04
INVOKE AppendMenu,esi,MF_SEPARATOR,NULL,NULL
INVOKE AppendMenu,esi,MF_STRING or MF_ENABLED,IDM_HIDECURS,offset szMenuVP06
mov eax,IDM_VEGRPHAUX
INVOKE CheckMenuRadioItem,esi,eax,IDM_VEGRPHREF3,eax,MF_BYCOMMAND
;hmenuVgraph
INVOKE CreatePopupMenu
xchg eax,esi
INVOKE AppendMenu,ebx,MF_POPUP,esi,NULL
mov hmenuVgraph,esi
INVOKE AppendMenu,esi,MF_STRING or MF_ENABLED,IDM_VGGRPHAUX,offset szMenuVP01
INVOKE AppendMenu,esi,MF_STRING or MF_ENABLED,IDM_VGGRPHREF1,offset szMenuVP02
INVOKE AppendMenu,esi,MF_STRING or MF_ENABLED,IDM_VGGRPHREF2,offset szMenuVP03
INVOKE AppendMenu,esi,MF_STRING or MF_ENABLED,IDM_VGGRPHREF3,offset szMenuVP04
INVOKE AppendMenu,esi,MF_SEPARATOR,NULL,NULL
INVOKE AppendMenu,esi,MF_STRING or MF_ENABLED,IDM_HIDECURS,offset szMenuVP06
mov eax,IDM_VGGRPHAUX
INVOKE CheckMenuRadioItem,esi,eax,IDM_VGGRPHREF3,eax,MF_BYCOMMAND
;hmenuHblank
INVOKE CreatePopupMenu
xchg eax,esi
INVOKE AppendMenu,ebx,MF_POPUP,esi,NULL
mov hmenuHblank,esi
INVOKE AppendMenu,esi,MF_STRING or MF_ENABLED,IDM_HIDECURS,offset szMenuHP11
;hmenuHupper
INVOKE CreatePopupMenu
xchg eax,esi
INVOKE AppendMenu,ebx,MF_POPUP,esi,NULL
mov hmenuHupper,esi
INVOKE AppendMenu,esi,MF_STRING or MF_ENABLED,IDM_HGRPHUSUP,offset szMenuHP01
INVOKE AppendMenu,esi,MF_STRING or MF_ENABLED,IDM_HGRPHUES,offset szMenuHP02
INVOKE AppendMenu,esi,MF_STRING or MF_ENABLED,IDM_HGRPHUINF,offset szMenuHP03
INVOKE AppendMenu,esi,MF_STRING or MF_ENABLED,IDM_HGRPHPIP,offset szMenuHP04
INVOKE AppendMenu,esi,MF_STRING or MF_ENABLED,IDM_HGRPHLSUP,offset szMenuHP05
INVOKE AppendMenu,esi,MF_STRING or MF_ENABLED,IDM_HGRPHLES,offset szMenuHP06
INVOKE AppendMenu,esi,MF_STRING or MF_ENABLED,IDM_HGRPHLINF,offset szMenuHP07
INVOKE AppendMenu,esi,MF_STRING or MF_ENABLED,IDM_HGRPHAUX1,offset szMenuHP08
INVOKE AppendMenu,esi,MF_STRING or MF_ENABLED,IDM_HGRPHAUX2,offset szMenuHP09
INVOKE AppendMenu,esi,MF_SEPARATOR,NULL,NULL
INVOKE AppendMenu,esi,MF_STRING or MF_ENABLED,IDM_HIDECURS,offset szMenuHP11
INVOKE CheckMenuRadioItem,esi,IDM_HGRPHUSUP,IDM_HGRPHAUX2,IDM_HGRPHAUX1,MF_BYCOMMAND
;hmenuHlower
INVOKE CreatePopupMenu
xchg eax,esi
INVOKE AppendMenu,ebx,MF_POPUP,esi,NULL
mov hmenuHlower,esi
INVOKE AppendMenu,esi,MF_STRING or MF_ENABLED,IDM_HGRPHUSUP,offset szMenuHP01
INVOKE AppendMenu,esi,MF_STRING or MF_ENABLED,IDM_HGRPHUES,offset szMenuHP02
INVOKE AppendMenu,esi,MF_STRING or MF_ENABLED,IDM_HGRPHUINF,offset szMenuHP03
INVOKE AppendMenu,esi,MF_STRING or MF_ENABLED,IDM_HGRPHPIP,offset szMenuHP04
INVOKE AppendMenu,esi,MF_STRING or MF_ENABLED,IDM_HGRPHLSUP,offset szMenuHP05
INVOKE AppendMenu,esi,MF_STRING or MF_ENABLED,IDM_HGRPHLES,offset szMenuHP06
INVOKE AppendMenu,esi,MF_STRING or MF_ENABLED,IDM_HGRPHLINF,offset szMenuHP07
INVOKE AppendMenu,esi,MF_STRING or MF_ENABLED,IDM_HGRPHAUX1,offset szMenuHP08
INVOKE AppendMenu,esi,MF_STRING or MF_ENABLED,IDM_HGRPHAUX2,offset szMenuHP09
INVOKE AppendMenu,esi,MF_SEPARATOR,NULL,NULL
INVOKE AppendMenu,esi,MF_STRING or MF_ENABLED,IDM_HIDECURS,offset szMenuHP11
INVOKE CheckMenuRadioItem,esi,IDM_HGRPHUSUP,IDM_HGRPHAUX2,IDM_HGRPHAUX2,MF_BYCOMMAND
pop esi
pop ebx
ret
CreateContextMenus ENDP
;***********************************************************************************************
it's actually the same thing the OS does if you create it in resource :P
Um, no, not the same thing as regular old menu-bar menus. But yep, context menus are real easy to create.
To create (bar) menus you have to go through a lot of nonsense with InsertMenuItem() (that's the function that uses the structure being discussed here), with what seems like a kajillion flags and type descriptors and whatnot that have to be set. Not worth it; I can just make a copy of a resource file for another project, change some names, add the resource compile and link steps in my batch file and off I go.
Too bad I'm not a MasmBasic user ...
i think you only need to use InsertMenuItem if you are doing an owner-drawn menu
if you like, i can post an example
i will add this....
i once thought there was an advantage to writing menus in code - and, in some cases, there is
when you write a menu in the resource, all the strings are stored as UNICODE
that makes the EXE a little larger
as time goes on, i am realizing that any "real" app should start out as UNICODE, anyways - lol
if it's worth publishing, it's worth supporting multiple languages
and - here's the lesson learned....
it's a lot easier to start out writing an app with UNICODE windows
than it is to write it with ANSI windows, then go back and change it to UNICODE :P
all that kind of negates any advantage in reducing EXE size
Quote from: dedndave on March 24, 2015, 09:24:03 PM
i think you only need to use InsertMenuItem if you are doing an owner-drawn menu
if you like, i can post an example
Thanks, but why would I want an owner-draw menu? I just want a simple, regular ol' menu, like File (Open, Save, Close), Edit (Copy, Paste), etc. Can you post a (simple) example of how to do this? Again, no bitmaps, nothing fancy.
It looks to me from the MSDN docs (and I could be wrong) that one needs to first
CreateMenu(), then use
InsertMenuItem() for each item one wants.
Standard template:
CASE WM_CREATE
mov esi, rv(CreateMenu) ; create the main menu
mov edi, rv(CreateMenu) ; create a sub-menu
invoke AppendMenu, esi, MF_POPUP, edi, chr$("&File") ; add it to the main menu
invoke AppendMenu, edi, MF_STRING, 101, chr$("&Dir") ; and add
invoke AppendMenu, edi, MF_STRING, 102, chr$("&Save") ; two items
invoke SetMenu, hWnd, esi ; attach menu to main window
i use CreatePopupMenu to create sub-menus
i only use CreateMenu one time - for the main menu handle
other than that, Jochen has the right idea
Quote from: dedndave on March 25, 2015, 05:51:40 AM
i use CreatePopupMenu to create sub-menus
Interesting:
QuoteIf you get the two confused, you can get strange menu behavior. Windows on rare occasions detects that you confused the two and converts as appropriate, but I wouldn't count on Windows successfully reading your mind. (http://blogs.msdn.com/b/oldnewthing/archive/2003/12/30/46594.aspx)
Has anybody ever seen strange menu behaviour?
this example demonstrates a few things
first, it has a sub-sub-menu - you may want one
second, the sub-menu handles are saved in global data
this is optional
at some point, you may want to modify a menu - the handle is nice to have
(check marks, disable items, etc)
finally, it demonstrates another of several ways to attach a menu to a window
you can put the HMENU in the WNDCLASSEX structure
you can pass the HMENU to the CreateWindowEx call (this example uses this method)
or, you can use SetMenu, as Jochen mentioned
i also added appropriate code for File-Exit and Help-About (and, i added a seperator to the file menu)
all other items give you a message box with the ID number
One more:
CASE WM_CREATE ; this message serves to initialise your application
mov esi, rv(CreateMenu) ; create the main menu
mov edi, rv(CreatePopupMenu) ; create a sub-menu
invoke AppendMenu, esi, MF_POPUP, edi, chr$("&File") ; add it to the main menu
mov ebx, rv(CreatePopupMenu) ; create a sub-menu
invoke AppendMenu, ebx, MF_STRING, 121, chr$("&asm") ; fill it
invoke AppendMenu, ebx, MF_STRING, 122, chr$("&inc") ; with various
invoke AppendMenu, ebx, MF_STRING, 123, chr$("&rc") ; options
invoke AppendMenu, edi, MF_POPUP, ebx, chr$("&Dir") ; and add it to the main menu as "Dir"
invoke AppendMenu, edi, MF_STRING, 102, chr$("&Save") ; one more main item
invoke SetMenu, hWnd, esi ; attach menu to main window
OK, I'm totally confused. I tried this, taking Dave's suggestion to use InsertMenu():
CALL CreateMenu
MOV hMenu, EAX
INVOKE InsertMenu, hMenu, -1, MF_BYPOSITION, 1111, OFFSET FileStr
INVOKE InsertMenu, hMenu, -1, MF_BYPOSITION, 1112, OFFSET EditStr
INVOKE InsertMenu, hMenu, 1, MF_BYPOSITION, 1113, OFFSET OpenStr
INVOKE SetMenu, hWin, hMenu
but no matter what I do, I can only create more menu headings (i.e., more things on the menu bar), not any items within any menu. (With this code, I get 3 menu headings--File, Open and Edit.)
How, for instance, do I add that "Open" item to the File menu?
Dave's suggestion is NOT to use InsertMenuItem
did you download my example in Reply #19
oh, guess not - lol
EDIT: try using AppendMenu
https://msdn.microsoft.com/en-us/library/windows/desktop/ms647616%28v=vs.85%29.aspx
probably our fault for not being clear enough.....
use CreateMenu to create the main menu
use CreatePopupMenu to create sub-menus (File, Edit, View, Help, etc)
use AppendMenu to add items to a menu or sub-menu
items may include sub-menus, clickable items, non-clickable seperators
use the appropriate flags
so, for example
CreateMenu - create the main menu (hmenuMain, let's call it)
CreatePopupMenu - to create a sub-menu (hmenuFile)
AppendMenu is then used to add hmenuFile to hmenuMain (MF_POPUP flag)
after that, you use AppendMenu to add items to that sub-menu
most items will be "MF_STRING or'ed with MF_ENABLED"
as it happens, both MF_STRING and MF_ENABLED are the defaults, so their values are 0
use MF_SEPERATOR for a seperator
once you get the hang of it, you can use checked and/or radio-checked items
That works like a charm. And it's actually easier than creating a menu resource.
I'll use this from now on.
:t