News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests
NB: Posting URL's See here: Posted URL Change

Main Menu

Problems with OWNERDRAW menu

Started by xandaz, February 16, 2022, 04:12:36 AM

Previous topic - Next topic

jj2007

Quote from: mikeburr on February 19, 2022, 08:46:31 AM
2) i suspect the invoke ... API ...might well alter  edi .. you cd test this by displaying edi before and after .. i know quite a few of them do and esi

Mike, that's quite unlikely, it would violate the Windows x86 ABI

Greenhorn

xandaz,

Quote from: xandaz on February 19, 2022, 04:41:09 AM
   Thanks all for help me out. Now i'm facing a new problem. Only the first dwTypeData gets Drawn.The other members of the menu seem to be overwritten by the others members. the code is as follows.    .elseif uMsg==WM_DRAWITEM
mov edi,lParam
assume edi:PTR DRAWITEMSTRUCT
.if [edi].itemAction==ODA_DRAWENTIRE
invoke Beep,1000,100
mov tmii.cbSize,sizeof MENUITEMINFO
mov tmii.fMask,MIIM_FTYPE or MIIM_ID or MIIM_STRING or MIIM_DATA
mov tmii.dwTypeData,0
mov tmii.cch,0
invoke GetMenuItemInfoA,[edi].hwndItem,[edi].itemID,FALSE,addr tmii
inc tmii.cch
invoke LocalAlloc,LPTR,tmii.cch
mov tmii.dwTypeData,eax
invoke GetMenuItemInfoA,[edi].hwndItem,[edi].itemID,FALSE,addr tmii
invoke DrawTextA,[edi].hdc,tmii.dwTypeData,-1,addr [edi].rcItem,DT_LEFT
mov eax,TRUE
ret
.endif

   The dwTypeData members seem to have a height that overfills the other members.

by providing this little peace of code, one just can guess what's wrong with your code.

However, in your snippet of the WM_DRAWITEM you always allocate memory when the menu pops up (ODA_DRAWENTIRE) but you never free the memory => memory leak. But that's not the problem for displaying the strings. Either your calculation in the WM_MEASUREITEM is buggy or the menu DC is corrupted, but if this is all what you're doing in the WM_DRAWITEM the latter should not be the case.
Check in the debugger DRAWITEMSTRUCT.rcItem for every menu item. And check your code in WM_MEASUREITEM.
Kole Feut un Nordenwind gift en krusen Büdel un en lütten Pint.

xandaz

   Thanks y'all. The problem doesn't presist if i use dwItemData when drawing the text. So, the DC isn't corrupt.

xandaz

the complete code is here:CreateToolsMenu PROC

invoke LocalFree,lpMemTools
mov idToolsItem,5000h
invoke CreateFile,addr ToolsMenuBuffer,GENERIC_READ,\
FILE_SHARE_READ,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0
mov hToolsFile,eax
cmp eax,INVALID_HANDLE_VALUE
je _end
invoke GetFileSize,eax,addr SizeHigh
inc eax
push eax
invoke LocalAlloc,LPTR,eax
mov lpMemTools,eax
pop eax
invoke ClearMemory,lpMemTools,eax
sub esp,4
pop eax
invoke ReadFile,hToolsFile,lpMemTools,eax,addr noBytesRead,0
invoke CloseHandle,hToolsFile
invoke RtlZeroMemory,addr ToolsMenuItemInfo,sizeof ToolsMenuItemInfo
mov esi,lpMemTools
mov edi,esi
cld
loop_0:
lodsb
cmp al,','
jne loop_0
dec esi
mov byte ptr [esi],0
inc esi
mov [ToolsMenuItemInfo.MENUITEMINFO].cbSize,sizeof MENUITEMINFO
mov [ToolsMenuItemInfo.MENUITEMINFO].fMask,MIIM_FTYPE or MIIM_STRING or MIIM_ID or MIIM_DATA
mov [ToolsMenuItemInfo.MENUITEMINFO].fType,  MFT_OWNERDRAW
invoke lstrlenA,edi
inc eax
mov [ToolsMenuItemInfo.MENUITEMINFO].cch,eax
mov [ToolsMenuItemInfo.MENUITEMINFO].dwTypeData,edi
push idToolsItem
pop [ToolsMenuItemInfo.MENUITEMINFO].wID
inc idToolsItem
  mov edi,esi
cld
loop_1:
lodsb
or al,al
jz          final_item
cmp al,13
jne loop_1
dec esi
mov byte ptr [esi],0
inc esi
mov [ToolsMenuItemInfo.MENUITEMINFO].dwItemData,edi
invoke InsertMenuItemA,hMenuMdiTools,-1,TRUE,addr ToolsMenuItemInfo
mov edi,esi
jmp loop_0
final_item:
  mov [ToolsMenuItemInfo.MENUITEMINFO].dwItemData,edi
invoke InsertMenuItemA,hMenuMdiTools,-1,TRUE,addr ToolsMenuItemInfo
_end:
ret

CreateToolsMenu endp

    .elseif uMsg==WM_DRAWITEM
mov edi,lParam
assume edi:PTR DRAWITEMSTRUCT
.if [edi].itemAction==ODA_DRAWENTIRE
invoke RtlZeroMemory,addr tmii,sizeof tmii
mov tmii.cbSize,sizeof MENUITEMINFO
mov tmii.fMask, MIIM_STRING or MIIM_DATA or MIIM_FTYPE
mov tmii.fType,MFT_STRING
invoke GetMenuItemInfoA,[edi].hwndItem,[edi].itemID,FALSE,addr tmii
inc tmii.cch
invoke LocalAlloc,LPTR,tmii.cch
mov tmii.dwTypeData,eax
invoke GetMenuItemInfoA,[edi].hwndItem,[edi].itemID,FALSE,addr tmii
;invoke MessageBoxA,0,tmii.dwTypeData,0,MB_OK
; invoke SendMessage,hWnd,WM_GETFONT,0,0
; invoke SelectObject,[edi].hdc,eax
; invoke DeleteObject,eax
; ; invoke lstrlenA,tmii.dwTypeData
; ; mov ebx,eax
invoke DrawTextA,[edi].hdc,tmii.dwTypeData,-1,addr [edi].rcItem,DT_LEFT
invoke LocalFree,tmii.dwTypeData
mov eax,TRUE
ret
assume edi:NOTHING

TimoVJL

#19
QuotedwItemData

Type: ULONG_PTR

An application-defined value associated with the menu item. Set fMask to MIIM_DATA to use dwItemData.

dwTypeData

Type: LPTSTR

The contents of the menu item. The meaning of this member depends on the value of fType and is used only if the MIIM_TYPE flag is set in the fMask member.

To retrieve a menu item of type MFT_STRING, first find the size of the string by setting the dwTypeData member of MENUITEMINFO to NULL and then calling GetMenuItemInfo. The value of cch+1 is the size needed. Then allocate a buffer of this size, place the pointer to the buffer in dwTypeData, increment cch, and call GetMenuItemInfo once again to fill the buffer with the string. If the retrieved menu item is of some other type, then GetMenuItemInfo sets the dwTypeData member to a value whose type is specified by the fType member.

When using with the SetMenuItemInfo function, this member should contain a value whose type is specified by the fType member.

dwTypeData is used only if the MIIM_STRING flag is set in the fMask member
May the source be with you

xandaz


NoCforMe

Quote from: mikeburr on February 19, 2022, 08:46:31 AM
2) i suspect the invoke ... API ...might well alter  edi .. you cd test this by displaying edi before and after .. i know quite a few of them do and esi
Are you sure about that? I thought EBX, ESI and EDI were "sacred", always. There shouldn't be any exceptions to this rule.
Assembly language programming should be fun. That's why I do it.

xandaz

   So.... the problem is solved and now i'm facing a new problem. Only the last icon of the Tools menu gets drawn. i have the code here:    .elseif uMsg==WM_DRAWITEM
mov edi,lParam
assume edi:PTR DRAWITEMSTRUCT
.if [edi].itemAction==ODA_DRAWENTIRE
invoke RtlZeroMemory,addr tmii,sizeof tmii
mov tmii.cbSize,sizeof MENUITEMINFO
mov tmii.fMask, MIIM_STRING or MIIM_DATA or MIIM_ID or MIIM_FTYPE
mov tmii.fType,MFT_STRING
invoke GetMenuItemInfoA,[edi].hwndItem,[edi].itemID,FALSE,addr tmii
inc tmii.cch
invoke LocalAlloc,LPTR,tmii.cch
mov tmii.dwTypeData,eax
invoke GetMenuItemInfoA,[edi].hwndItem,[edi].itemID,FALSE,addr tmii
invoke CopyBufferA,tmii.dwItemData,addr TextBuffer
invoke ExtractAssociatedIconA,hInstance,addr TextBuffer,addr lpIcon
invoke DrawIconEx,[edi].hdc,[edi].rcItem.left,[edi].rcItem.top,eax,16,16,0,0,DI_NORMAL
add [edi].rcItem.left,22
invoke DrawTextA,[edi].hdc,tmii.dwTypeData,-1,addr [edi].rcItem,DT_LEFT
invoke LocalFree,tmii.dwTypeData
mov eax,TRUE
ret
assume edi:NOTHING
.endif

    Can you tell me what's wrong with this?

TimoVJL

In my test i saw same problem if (GetMenuItemInfo((HMENU)lpDrawItem->hwndItem, IDM_TOOL, FALSE, &mii)) {
//if (GetMenuItemInfo((HMENU)lpDrawItem->itemID, 0, TRUE, &mii)) {
wsprintf(szTmp, TEXT("mii.cch: %Xh"), mii.cch);
OutputDebugString(szTmp);
GetMenuString((HMENU)lpDrawItem->itemID, 0, szTmp, 256, MF_BYPOSITION);
OutputDebugString(szTmp);
}

My was IDM_TOOL 1B58h and it wasn't itemID
lpDrawItem->hwndItem is main menu handle
lpDrawItem->itemID is Tool menu handle
May the source be with you

mikeburr

invoke GetGlgItemint, hwnd , esi , 0 , FALSE  .... screws esi althopugh it is only supposed to be a passive input
try it
regards mikeb

jj2007

Quote from: mikeburr on February 21, 2022, 07:13:12 AM
invoke GetGlgItemint, hwnd , esi , 0 , FALSE  .... screws esi althopugh it is only supposed to be a passive input
try it
regards mikeb

Not on my machine, see attachment (pure Masm32 SDK) :cool:

xandaz

   Hi guys. I just want to say that most problems with the ownerdraw menu have been solved. It needed MIIM_FTYPE or MIIM_STRING to retrieve the dwTypeData member.
   Now I'm facing a new problem: DRAWITEMRUCT doesn't return itemState properlly. is was trying:test [edi].itemState,ODS_SELECTED
jz  no_sel
invoke SetBkColor,0ffffh
no_sel:

... it doesn't work. Returns 256. Does anybody know how to fix this?

HSE

Quote from: xandaz on February 22, 2022, 08:16:14 PM
... it doesn't work. Returns 256. Does anybody know how to fix this?
It's not a number. It's an arrange of bits.
Equations in Assembly: SmplMath

jj2007

https://devblogs.microsoft.com/oldnewthing/20141211-00/?p=43423

I doubt that you'll get a good answer without complete code.

xandaz

    Well... MIIM_STRING was missing from MENUITEMINFO.fMask. Once i got that i fixed. Still looks a little bad. I'm going to go around the WM_DRAWITEM message for a while. Thanks everyone!