News:

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

Hide and ReShow Main Menu Items

Started by Jimg, January 21, 2009, 06:39:02 PM

Previous topic - Next topic

Jimg

Here's some procs I just whipped together to replace my former method of using a bunch of macro and macro strings.

It copies the menu contents to the heap so that menu items can be removed and restored to emulate the VB capability of setting the .visible property which doesn't seem to exist in regular windows.

Call the first proc once to set up the menu in the heap.  Call the other whenever.

There's probably a much better way to do this, if so, please let me know  :P

; --------------- Hide Show Menu Items   by JimG ---------------
.data?
hsmMnus   dd ?  ; start of menu buffer in heap
hsmMenuStuff Struct
    MENUITEMINFO <?>
    next    dword ? ; address of next item
    visible dword ? ; 1=visible, 0=not
    menuh   dword ? ; the handle of the menu this item belongs to
    cap     dword ? ; start of the variable length caption
hsmMenuStuff ends
hmsmnu textequ <[edi].hsmMenuStuff>
.code

hsmGetMenuInfo proc hWindow
    ; call once with handle of window, usually from WM_INITDIALOG, to get the full info for the menu
    local rcnt,curmenu,mcount,hsmMenu,tempm[256 + sizeof hsmMenuStuff]:byte
    pushad
    invoke GetMenu,hWindow
    or eax,eax
    jz hmsGetMenuInfoWrap
    mov hsmMenu,eax
    lea edi,tempm   ; first time through, just use scratch on stack
    mov rcnt,1
    mov ebx,sizeof hsmMenuStuff   ; cumulative size.  Need one extra for end flag and last try
    .repeat ; twice, once to get size of memory needed, once to copy to heap
        push 0      ; the flag that we have finished all menus/sub menus
        mov esi,hsmMenu ; the starting point. esi will contain current menu throughout
again:  mov mcount,0    ; menu item count for GetMenuItemInfo api
        .repeat
            mov hmsmnu.cbSize,sizeof MENUITEMINFO
            mov hmsmnu.cch,255
            mov hmsmnu.fMask,3Fh ; get everything
            mov hmsmnu.visible,1
            mov hmsmnu.menuh,esi
            lea eax,hmsmnu.cap  ; address of caption
            mov hmsmnu.dwTypeData,eax
            invoke GetMenuItemInfo,esi,mcount,TRUE,edi
            .if eax==0
                pop esi ; we ran out of this menu, move to next if any
                or esi,esi  ; is there any submenus stored up?
                jnz again   ; yes, go do next sub menu
                .break .if rcnt != 0    ; all done with first pass, go set up for second pass
                mov hmsmnu.next,0       ; we are totally done, flag end of data
                jmp hmsGetMenuInfoWrap  ; go wrap up
            .endif
            .if hmsmnu.hSubMenu         ; see if there is a submenu to do later
                push hmsmnu.hSubMenu    ; save for later
            .endif
            .if rcnt==1
                add ebx,sizeof hsmMenuStuff ; amount needed for everything but string
                add ebx,hmsmnu.cch          ; add in size of string
            .else
                mov ebx,edi     ; compute address of next block
                add ebx,sizeof hsmMenuStuff
                add ebx,hmsmnu.cch
                and ebx,0FFFFFFFCh  ; mask off last two bits to keep on even dword alignment
                mov hmsmnu.next,ebx ; save next address
                mov edi,ebx         ; and continue
            .endif
            inc mcount ; setup for next one
        .until 0
        invoke GetProcessHeap  ; done with first pass
        invoke HeapAlloc,eax,HEAP_ZERO_MEMORY,ebx  ; allocate memory needed
        mov hsmMnus,eax     
        mov edi,eax         ; go back and save all in heap
        mov eax,hWindow     ; save window handle for HideShowMenus
        stosd
        dec rcnt
    .until 0
hmsGetMenuInfoWrap:
    popad
ret
hsmGetMenuInfo endp

HideShowMenus proc HideShow:dword,MenuIds:dword
; HideShow is 0 to hide, anything else to show
; MenuIds is the address of a list of Menu Ids to do, terminated with a zero ID.
    local previous
    pushad
    mov edi,hsmMnus
    add edi,4           ; skip window handle
    mov previous,0      ; check for change
    .repeat ; step through menu items
        mov edx,hmsmnu.menuh
        .if edx != previous ; submenu change, reset
            mov ebx,0       ; restart running count
            mov previous,edx
        .endif               
        mov esi,MenuIds ; items to hide or show
        .repeat ; step thought item to change
            mov eax,[esi]       ; id of the menu item we want
            .break .if eax==0   ; all done
            .if eax==hmsmnu.wID
                .if HideShow    ; if so, show
                    .if hmsmnu.visible==0   ; only make a change if it's not visible
                        mov hmsmnu.visible,1
                        invoke InsertMenuItem,edx,ebx,TRUE,edi
                    .endif
                .else  ; hide
                    .if hmsmnu.visible
                        mov hmsmnu.visible,0
                        invoke RemoveMenu,edx,ebx,MF_BYPOSITION
                    .endif
                .endif
                .break  ; all done with this loop
            .endif
            add esi,4   ; go do next one
        .until 0
        add ebx,hmsmnu.visible  ; count visible items
        mov edi,hmsmnu.next     ; location of menu item block
    .until hmsmnu.next==0
    mov edi,hsmMnus
    invoke DrawMenuBar,[edi]
    popad
ret
HideShowMenus endp


Unable to upload file, upload folder is full.

File and test program available here - http://www.winasm.net/forum/index.php?act=Attach&type=post&id=14593

Edit:  uploaded source here



[attachment deleted by admin]

PBrennick

Jim,
That's very useful stuff.

The upload folder is full!?! Haven't run into that one yet. Was that a temporary condition? I just uploaded Suduko...

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

Jimg

Okay, I uploaded here for those that didn't want to hassle with winasm.net