News:

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

Menu Item Visibility

Started by Jimg, August 29, 2005, 01:24:21 AM

Previous topic - Next topic

Jimg

In VB (and .net) one can set the visibility of any menu item just by setting .visible to true or false.  I'm trying to temporarily hide a menu item but I can't find anything similar in assembly.  I don't want to delete and recreate if I can avoid it as there are many I want to hide with large submenu structures.  Anyone know how to hide a menu item and show it again later?

Darrel

Hi Jimg,

Use RemoveMenu and InsertMenuItem.

Regards,

Darrel

PBrennick

Remember that in VB you are setting the state of a menu that does not yet exist when you use the .visible setting in the properties area.  If .visible is false, the menu item is not created when you compile the program so you are not controlling an exsiting menu like you do in assembly.  So, as a result, you need to do the same thing that VB does, create or not create, if you are comparing the two.  To 'hide' a memu item would not be the same thing at all and in this case there is no mechanism beyond removing it and then recreating it.  When you use the .visible option 'in your code,' this is what you are actually doing.  In this case, the menu already exists so VB just handles the removal or insertion for you.

Paul
The GeneSys Project is available from:
The Repository or My crappy website

Jimg

Hi Paul-

Actually, you can repeatedly hide and show the menu item at execution time in VB just by setting the property.  I have several programs that do just that.

Anyways, if I have to do it the hard way ::)  Do you see what's wrong with this?

.486
.model Flat, Stdcall
option Casemap :None   ; case sensitive

.nolist
include Windows.inc

uselib MACRO libname:req
    include    libname.inc
    includelib libname.lib
ENDM

uselib user32
uselib kernel32
uselib shell32
uselib comctl32
uselib comdlg32
uselib gdi32
uselib masm32   ; for debug
;uselib debug   ; for debug

soff Macro QuotedText:Vararg    ; returns offset to a string
Local LocalText
.data
LocalText db QuotedText,0
.code
EXITM <offset LocalText>
Endm

.listall

DlgProc Proto :DWord,:DWord,:DWord,:DWord
inv equ INVOKE

HideTheMenu     equ 2005
ShowTheMenu     equ 2006

.data?
align 4
hWin        dd ?  ; dialog handle
hMenu       dd ?    ; the menu
mi MENUITEMINFO <?>

.code
Program:
    inv InitCommonControls
    inv GetModuleHandle,NULL
    inv DialogBoxParam,eax,101,0,ADDR DlgProc,0
    inv ExitProcess,eax
; -----------------------------------------------------------------------

DlgProc proc uses edi esi ebx hWnd:DWord,uMsg:DWord,wParam:DWord,lParam:DWord
    .if uMsg == WM_COMMAND
        mov eax,wParam
        .if ax==HideTheMenu
            mov mi.cbSize,sizeof mi
            mov mi.fMask,MIIM_ID+MIIM_SUBMENU+MIIM_TYPE+MIIM_STATE 
            inv GetMenuItemInfo,hMenu,10001,FALSE,addr mi  ; 10001 is identifier of File menu
            .if eax==0
                inv GetErrDescription,eax   
            .endif
            inv RemoveMenu,hMenu,10001,MF_BYCOMMAND
            inv DrawMenuBar,hWin
        .elseif ax==ShowTheMenu
            ;inv MessageBox,hWin,soff("showing"),0,0
            mov mi.cbSize,sizeof mi
            mov mi.fMask,MIIM_ID+MIIM_SUBMENU+MIIM_TYPE+MIIM_STATE
            inv InsertMenuItem,hMenu,0,TRUE,addr mi
            .if eax==0
                inv GetErrDescription,eax   
            .endif
            inv DrawMenuBar,hWin
        .endif
    .elseif uMsg== WM_INITDIALOG
        mov eax,hWnd    ; save handle for everyone
        mov hWin,eax
        inv GetMenu,hWin
        mov hMenu,eax   
    .elseif uMsg == WM_CLOSE
        inv EndDialog,hWin,0
    .endif
    xor eax,eax
    ret
DlgProc Endp

end Program


It hides the menu item (removes it) ok, but I can't seem to get it back.

[attachment deleted by admin]

Jimg

Oops, forgot a part

        .elseif ax==ShowTheMenu
            mov mi.fMask,miflags
            mov mi.fType,MFT_STRING
            mov mi.dwTypeData,soff("&File")
            inv InsertMenuItem,hMenu,0,TRUE,addr mi


Now it seems to work.  Thanks.

Jimg

And here's the final solution to hiding and reshowing three menu items:
.data?
mi MENUITEMINFO <?> ; for zzFile   10001
mi2 MENUITEMINFO <?> ; for zzReset  10002
mi3 MENUITEMINFO <?> ; for zzHelp   10003
.code
DlgProc proc uses edi esi ebx hWnd:DWord,uMsg:DWord,wParam:DWord,lParam:DWord
    .if uMsg == WM_COMMAND
        mov eax,wParam
        .if ax==HideTheMenu
            mov mi.cbSize,sizeof mi
            miflags equ MIIM_ID+MIIM_SUBMENU+MIIM_STATE
            mov mi.fMask, miflags
            inv GetMenuItemInfo,hMenu,10001,FALSE,addr mi  ; 10001 is identifier of File menu
            inv RemoveMenu,hMenu,10001,MF_BYCOMMAND

            mov mi2.cbSize,sizeof mi2
            mov mi2.fMask, miflags
            inv GetMenuItemInfo,hMenu,10002,FALSE,addr mi2 ; 10002 is identifier of Reset menu
            inv RemoveMenu,hMenu,10002,MF_BYCOMMAND

            mov mi3.cbSize,sizeof mi3
            mov mi3.fMask, miflags
            inv GetMenuItemInfo,hMenu,10003,FALSE,addr mi3 ; 10003 is identifier of Help menu
            inv RemoveMenu,hMenu,10003,MF_BYCOMMAND

            inv DrawMenuBar,hWin
        .elseif ax==ShowTheMenu
            mov mi.fMask,miflags+MIIM_TYPE
            mov mi.fType,MFT_STRING
            mov mi.dwTypeData,soff("&File")
            inv InsertMenuItem,hMenu,0,TRUE,addr mi

            mov mi2.fMask,miflags+MIIM_TYPE
            mov mi2.fType,MFT_STRING
            mov mi2.dwTypeData,soff("&Reset")
            inv InsertMenuItem,hMenu,1,TRUE,addr mi2

            mov mi3.fMask,miflags+MIIM_TYPE
            mov mi3.fType,MFT_STRING
            mov mi3.dwTypeData,soff("&Help")
            inv InsertMenuItem,hMenu,2,TRUE,addr mi3

            inv DrawMenuBar,hWin
        .endif


There has got to be an easier way!

Darrel

set up your MENUITEMINFO structures on dialog box initialization.

DlgProc proc uses edi esi ebx hWnd:DWord,uMsg:DWord,wParam:DWord,lParam:DWord
    .if uMsg == WM_COMMAND
        mov eax,wParam
        .if ax==HideTheMenu
            inv RemoveMenu,hMenu,10001,MF_BYCOMMAND
            inv RemoveMenu,hMenu,10002,MF_BYCOMMAND
            inv RemoveMenu,hMenu,10003,MF_BYCOMMAND
            inv DrawMenuBar,hWin
        .elseif ax==ShowTheMenu
            inv InsertMenuItem,hMenu,0,TRUE,addr mi
            inv InsertMenuItem,hMenu,1,TRUE,addr mi2
            inv InsertMenuItem,hMenu,2,TRUE,addr mi3
            inv DrawMenuBar,hWin
        .endif
    .elseif uMsg== WM_INITDIALOG
        mov eax,hWnd    ; save handle for everyone
        mov hWin,eax
        inv GetMenu,hWin
        mov hMenu,eax
        mov mi.cbSize,sizeof mi
        mov mi.fMask,MIIM_ID+MIIM_SUBMENU+MIIM_TYPE
        mov mi.fType,MFT_STRING
        mov mi.dwTypeData,soff("&File")
        mov mi.wID,10001
        inv GetSubMenu,hMenu,0
mov mi.hSubMenu,eax 
        mov mi2.cbSize,sizeof mi
        mov mi2.fMask,MIIM_ID+MIIM_SUBMENU+MIIM_TYPE
        mov mi2.fType,MFT_STRING
        mov mi2.dwTypeData,soff("&Reset")
        mov mi2.wID,10002
        inv GetSubMenu,hMenu,1
mov mi2.hSubMenu,eax 
        mov mi3.cbSize,sizeof mi
        mov mi3.fMask,MIIM_ID+MIIM_SUBMENU+MIIM_TYPE
        mov mi3.fType,MFT_STRING
        mov mi3.dwTypeData,soff("&Help")
        mov mi3.wID,10003
        inv GetSubMenu,hMenu,2
mov mi3.hSubMenu,eax 
    .elseif uMsg == WM_CLOSE
        inv EndDialog,hWin,0
    .endif
    xor eax,eax
    ret
DlgProc Endp

Jimg


PBrennick

Jimg,
Very nicely done!  By the way, I know you can set the properties of the menu at execution time and said so at the end of my post.  I think you did not read it all...

Paul
The GeneSys Project is available from:
The Repository or My crappy website

Jimg

Sorry Paul, thinking of too many things at the same time :eek

Still seems like this is a great lot of work.  I'll bet there's some hidden api somewhere that doe this.

Jimg

And for the finale  (drum roll) --  The totally generic version:
.data?
MenusToRemove textequ <0,1,2>

%for MenuNum,<MenusToRemove>
    mi&MenuNum& MENUITEMINFO <?>
    mi&MenuNum&Caption db 20 dup (?)
endm

.code
DlgProc proc uses edi esi ebx hWnd:DWord,uMsg:DWord,wParam:DWord,lParam:DWord
    .if uMsg == WM_COMMAND
        mov eax,wParam
        .if ax==HideTheMenu
            %for MenuNum,<MenusToRemove>
                inv RemoveMenu,hMenu,mi&MenuNum&.wID,MF_BYCOMMAND
            endm
            inv DrawMenuBar,hWin
        .elseif ax==ShowTheMenu
            %for MenuNum,<MenusToRemove>
                inv InsertMenuItem,hMenu,&MenuNum&,TRUE,addr mi&MenuNum&
            endm
            inv DrawMenuBar,hWin
        .endif
    .elseif uMsg== WM_INITDIALOG
        mov eax,hWnd    ; save handle for everyone
        mov hWin,eax
        inv GetMenu,hWin
        mov hMenu,eax

        %for MenuNum,<MenusToRemove>
            mov mi&MenuNum&.cbSize,sizeof MENUITEMINFO
            mov mi&MenuNum&.cch,20
            mov mi&MenuNum&.fMask,MIIM_ID+MIIM_SUBMENU+MIIM_TYPE+MIIM_DATA
            mov mi&MenuNum&.dwTypeData,offset mi&MenuNum&Caption
            inv GetMenuItemInfo,hMenu,&MenuNum&,TRUE,addr mi&MenuNum&
        endm

    .elseif uMsg == WM_CLOSE
        inv EndDialog,hWin,0
    .endif
    xor eax,eax
    ret
DlgProc Endp