Hello everyone,
I am trying to make the cration of my owner-draw menus easier, thus I am trying to use structs like this:


MyMenuItem struct
MenuID DWORD ?
IconID DWORD ?
IconHandle HICON ?
MenuText BYTE 32 dup (?)
MyMenuItem ends


My first problem is: How can I declare the null character in the MenuText string in the .data section? I tried this but didn't work:


.data
MenuActivate MyMenuItem <21,21,0,("&Activate",0)>


Another problem is that I am trying to make an array of MyMenuItem structs (only the adresses).
I use this:


.data?
TrayMenu dd 8 dup (?)


Then, I would loop this array in my code to create the menu. I made this code to test it, but it is not working very well:


push offset MenuActivate
pop TrayMenu[0]
push offset MenuDeactivate
pop TrayMenu[1]
push offset MenuExecute
pop TrayMenu[2]
push offset MenuConfig
pop TrayMenu[3]
push offset MenuAbout
pop TrayMenu[4]
push offset MenuExit
pop TrayMenu[5]
push ebx
push ecx
mov ebx, 0
menuloop:
mov ecx, TrayMenu[ebx]
assume ecx:ptr MyMenuItem
pushad
invoke MessageBox, 0, addr [ecx].MenuText, addr [ecx].MenuText, 0
popad
inc ebx
cmp ebx, 6
jne menuloop
pop ecx
pop ebx

This is not working. I get only two MessageBoxes one with "<<<" and another with "Ex&it" (this one is correct). That's it.

What I am doing wrong? I've never played with structs before.
Can anyone help? Please give me some suggestions on this.
Thanks in advance.
Posted on 2002-01-28 21:15:50 by dilau
; this handy macro help condense code

m2m TrayMenu[0*4], offset MenuActivate
m2m TrayMenu[1*4], offset MenuDeactivate
m2m TrayMenu[2*4], offset MenuExecute
m2m TrayMenu[3*4], offset MenuConfig
m2m TrayMenu[4*4], offset MenuAbout
m2m TrayMenu[5*4], offset MenuExit

push ebx
push ecx
mov ebx,-6 ; no cmp needed
menuloop:
mov ecx,TrayMenu[ebx*4 + 4*6]
assume ecx:ptr MyMenuItem
invoke MessageBox, 0, addr [ecx].MenuText, addr [ecx].MenuText, 0
assume ecx:NOTHING
inc ebx
jne menuloop
pop ecx
pop ebx
You could fix your code by multipling EBX by 4 (the size of a DWORD).
Posted on 2002-01-28 22:02:41 by bitRAKE
dilau,

I don't know how to initialize a byte field of struct in .data section. But You can use my macro FillString to initialize it in run-time.
Example:


.386
.model flat, stdcall
option casemap: none

include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
include \masm32\include\user32.inc
include \masm32\include\masm32.inc
include \masm32\include\debug.inc

includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\user32.lib
includelib \masm32\lib\masm32.lib
includelib \masm32\lib\debug.lib

.data
MyMenuItem struct
MenuID DWORD ?
IconID DWORD ?
IconHandle HICON ?
MenuText BYTE 32 dup (?)
MyMenuItem ends

MenuActivate MyMenuItem <21,21,0>
MenuDeactivate MyMenuItem <21,21,0>
MenuConfig MyMenuItem <21,21,0>
MenuAbout MyMenuItem <21,21,0>
MenuExit MyMenuItem <21,21,0>
TrayMenu dword 8 dup(?)

.code
start:
FillString MenuActivate.MenuText, "Activate"
FillString MenuDeactivate.MenuText, "Dectivate"
FillString MenuConfig.MenuText, "Config"
FillString MenuAbout.MenuText, "About"
FillString MenuExit.MenuText, "Exit"
mov TrayMenu[0], offset MenuActivate
mov TrayMenu[1*4], offset MenuDeactivate ;multiple index by 4
mov TrayMenu[2*4], offset MenuConfig
mov TrayMenu[3*4], offset MenuAbout
mov TrayMenu[4*4], offset MenuExit
xor ebx, ebx
.while TRUE
mov eax, TrayMenu[ebx*4]
add eax, 12
PrintStringByAddr eax
inc ebx
.break .if ebx > 4
.endw
ret
end start

Macro FillString is in the debug.inc file of MASM32 v7.0 package. Its text is


FillString macro Arr, Text
local i
i = 0
forc var, <&Text>
mov Arr[i], '&var'
i = i + 1
endm
mov Arr[i], 0
endm
Posted on 2002-01-28 22:43:15 by vkim
Theres actually a very simple solution to the string declaration problem.

Change the struct to:
MyMenuItem struct

MenuID DWORD ?
IconID DWORD ?
IconHandle HICON ?
MenuText BYTE 32 dup ([COLOR=darkred]0[/COLOR])
MyMenuItem ends

Note the 0 and not ?.

Then you can declare the items as
MenuActivate MyMenuItem {21,21,0,"&Activate}
Posted on 2002-01-29 04:53:36 by Eóin
Bravo, Eyin! :alright:
Posted on 2002-01-29 07:38:49 by vkim
There's no need to use "m2m" - an offset is a static value, so you
can MOV it directly.
Posted on 2002-01-29 09:24:22 by f0dder
Thanks guys, I solved my problem using this:


push ebx
push ecx
mov ebx, 0
mov ecx, offset MenuActivate
assume ecx:ptr MyMenu
menuloop:
add ecx, SIZEOF MyMenu
pushad
invoke MessageBox, 0, addr [ecx].MenuText, addr [ecx].MenuText, 0
popad
inc ebx
cmp ebx, 8
jne menuloop
assume ecx:nothing
pop ecx
pop ebx

Is this right? It's working ok.
I had used E?in's solution before, but with it, I was unable to declare my struct in the .data? section. I got an error saying that it wasn't possible to use already initialized data (because of the 0 instead of ?). So, I guess I will have to move the strings to the structs at run-time.

Thanks again guys! :)
Posted on 2002-01-29 23:55:00 by dilau