The MASM Forum

General => The Campus => Topic started by: xandaz on February 16, 2022, 04:12:36 AM

Title: Problems with OWNERDRAW menu
Post by: xandaz on February 16, 2022, 04:12:36 AM
   Hi guys. I've dealing with this strange issue where the dwTypeData member appears empty. I'm posting the code so you can see what i'm doint wrong.    .elseif uMsg==WM_DRAWITEM
mov edi,lParam
assume edi:PTR DRAWITEMSTRUCT
invoke GetMenuItemInfoA,[edi].hwndItem,[edi].itemID,FALSE,addr tmii
invoke MessageBoxA,0,tmii.dwTypeData,0,MB_OK
invoke SHGetFileInfoA,tmii.dwItemData,0,addr shfi,sizeof shfi,SHGFI_SMALLICON
invoke SelectObject,[edi].hdc,shfi.hIcon
invoke DeleteObject,eax
invoke DrawIcon,[edi].hdc,[edi].rcItem.left,[edi].rcItem.top,shfi.hIcon
invoke DrawTextA,[edi].hdc,tmii.dwTypeData,-1,addr [edi].rcItem,DT_LEFT
Title: Re: Problems with OWNERDRAW menu
Post by: xandaz on February 16, 2022, 09:46:41 PM
    After reading a bit od msdn information i found out that to retirieve the dwTypeData member of MENUITEMINFO there's little protocol for it, it's described in the following lines of code.  .elseif uMsg==WM_DRAWITEM
mov edi,lParam
assume edi:PTR DRAWITEMSTRUCT
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

Still the dwTypeData member appears empty. does MFT_STRING combine with MFT_OWNERDRAW? or can't they be mixed?
Title: Re: Problems with OWNERDRAW menu
Post by: Greenhorn on February 17, 2022, 12:57:46 AM
You don't need to call GetMenuItemInfo in the WM_DRAWITEM.
If you've stored a pointer in dwItemData of the MENUITEMINFO structure (MIIM_DATA) you'll find it in the DRAWITEMSTRUCT member itemData.
Just have a look at the MSDN example for ownerdrawn menus.
Title: Re: Problems with OWNERDRAW menu
Post by: xandaz on February 17, 2022, 01:41:36 AM
   Hi Greenhorn. The problem is the dwTypeData member. It appears empty. Ty
Title: Re: Problems with OWNERDRAW menu
Post by: Greenhorn on February 17, 2022, 02:37:42 AM
Did you stored a value in dwItemData ? You also have to set the corresponding flags in the fMask member of the MENUITEMINFO. What do you see in the itenData member of the DRAWITEMSTRUCT?
Did you had a look at the example on MSDN (https://docs.microsoft.com/en-us/windows/win32/menurc/using-menus#creating-owner-drawn-menu-items) ?
Title: Re: Problems with OWNERDRAW menu
Post by: Greenhorn on February 17, 2022, 03:00:59 AM
Attached my old version of ownerdrawn menus.
Title: Re: Problems with OWNERDRAW menu
Post by: xandaz on February 17, 2022, 04:08:19 AM
   The menu looks terrific but the code is kinda complex. I'll see what I can get out of it. Thanks Greenhorn
Title: Re: Problems with OWNERDRAW menu
Post by: xandaz on February 17, 2022, 11:52:04 PM
   Hi Guys. The following lines of cpde should work but dont. It's in accoordance with MSDN documentation. It gives invalid handle eorror. Can anyone tell me why?    .elseif uMsg==WM_DRAWITEM
mov edi,lParam
assume edi:PTR DRAWITEMSTRUCT
mov tmii.cbSize,sizeof MENUITEMINFO
mov tmii.fMask,MIIM_ID or MIIM_STRING or MIIM_TYPE OR MIIM_DATA
mov tmii.fType,MFT_STRING
mov tmii.dwTypeData,NULL
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.TypeData,-1,addr [edi].rcItem,DT_LEFT
mov eax,TRUE
ret
Title: Re: Problems with OWNERDRAW menu
Post by: jj2007 on February 18, 2022, 12:01:40 AM
It would be much easier to read with spaces after the comma:
GetMenuItemInfoA,[edi].hwndItem,[edi].itemID,FALSE,addr tmii
GetMenuItemInfoA, [edi].hwndItem, [edi].itemID, FALSE, addr tmii

So have you checked whether [edi].hwndItem has a valid value?
Title: Re: Problems with OWNERDRAW menu
Post by: xandaz on February 18, 2022, 02:38:28 AM
   Yeah JJ. I've actually changed it to the original Menu Handle. Nothing seems to work. And i've tried to retrieve the dwItemData ( although its present in DRAWITEM Struct) and it worked. I've seen the same problem in StackOverflow and the solution presented is the same. Ty
Title: Re: Problems with OWNERDRAW menu
Post by: TimoVJL on February 18, 2022, 05:17:38 AM
This C code is from working example:
void OnMeasureItem(HWND hwnd, MEASUREITEMSTRUCT * lpMeasureItem)
{
if (lpMeasureItem) {
// if (lpMeasureItem->itemHeight < 16)
// lpMeasureItem->itemHeight = 16;
lpMeasureItem->itemHeight = 24;
lpMeasureItem->itemWidth = 24;
}
return;
}

void OnDrawItem(HWND hwnd, const DRAWITEMSTRUCT * lpDrawItem)
{
if (lpDrawItem->CtlType == ODT_MENU) {
if (lpDrawItem->itemID < 10000) {
if (lpDrawItem->itemData) {
ImageList_Draw(g_hIml, lpDrawItem->itemData, lpDrawItem->hDC, 2, 2, ILD_NORMAL );
}
} else {
//FillRect(lpDrawItem->hDC, &lpDrawItem->rcItem, hBkBrush);
SetBkMode(lpDrawItem->hDC, TRANSPARENT);
char *p = (char*)lpDrawItem->itemData;
DrawText(lpDrawItem->hDC, (char*)lpDrawItem->itemData, -1, (RECT*)&lpDrawItem->rcItem, 0);
}
}
return;
}
Title: Re: Problems with OWNERDRAW menu
Post by: xandaz on February 18, 2022, 06:34:33 AM
    Sorry man. That doesn't help me much. ty anyway
Title: Re: Problems with OWNERDRAW menu
Post by: TimoVJL on February 19, 2022, 12:10:47 AM
If we don't know what you are after, it's hard to help :sad:
Title: Re: Problems with OWNERDRAW menu
Post by: 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.
Title: Re: Problems with OWNERDRAW menu
Post by: mikeburr on February 19, 2022, 08:46:31 AM
1) dont use assume .. you keep forgetting to assume nothing ...also its not compatible with 64 bit afaik shd you wish to convert later
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
regards mike b
Title: Re: Problems with OWNERDRAW menu
Post by: jj2007 on February 19, 2022, 09:07:51 AM
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
Title: Re: Problems with OWNERDRAW menu
Post by: Greenhorn on February 19, 2022, 11:09:40 AM
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.
Title: Re: Problems with OWNERDRAW menu
Post by: xandaz on February 19, 2022, 08:28:12 PM
   Thanks y'all. The problem doesn't presist if i use dwItemData when drawing the text. So, the DC isn't corrupt.
Title: Re: Problems with OWNERDRAW menu
Post by: xandaz on February 19, 2022, 08:45:59 PM
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
Title: Re: Problems with OWNERDRAW menu
Post by: TimoVJL on February 19, 2022, 09:08:34 PM
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
Title: Re: Problems with OWNERDRAW menu
Post by: xandaz on February 19, 2022, 10:07:24 PM
    So i've  read in MSDN.
Title: Re: Problems with OWNERDRAW menu
Post by: NoCforMe on February 20, 2022, 03:51:48 PM
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.
Title: Re: Problems with OWNERDRAW menu
Post by: xandaz on February 20, 2022, 08:17:46 PM
   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?
Title: Re: Problems with OWNERDRAW menu
Post by: TimoVJL on February 21, 2022, 04:36:17 AM
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
Title: Re: Problems with OWNERDRAW menu
Post by: 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
Title: Re: Problems with OWNERDRAW menu
Post by: jj2007 on February 21, 2022, 10:24:55 AM
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:
Title: Re: Problems with OWNERDRAW menu
Post by: xandaz on February 22, 2022, 08:16:14 PM
   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?
Title: Re: Problems with OWNERDRAW menu
Post by: HSE on February 22, 2022, 11:22:33 PM
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.
Title: Re: Problems with OWNERDRAW menu
Post by: jj2007 on February 23, 2022, 12:29:52 AM
https://devblogs.microsoft.com/oldnewthing/20141211-00/?p=43423

I doubt that you'll get a good answer without complete code.
Title: Re: Problems with OWNERDRAW menu
Post by: xandaz on March 02, 2022, 06:23:34 AM
    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!
Title: Re: Problems with OWNERDRAW menu
Post by: xandaz on March 04, 2022, 06:20:25 AM
   Hey guys. It's still not crash free but it's working. The ownerdrawn menus are a bit ugly but it'll get better. Thanks all for the help!
Title: Re: Problems with OWNERDRAW menu
Post by: mikeburr on March 04, 2022, 11:03:07 PM
jj .. thats because youre not doing the same thing

         invoke GetDlgItemInt, hWnd, 103, esi, -1
         invoke GetDlgItemInt, hWnd, esi, ...
... blackboard eraser whisles through the air ... ouch
cummon pay attention in class ...
Title: Re: Problems with OWNERDRAW menu
Post by: jj2007 on March 04, 2022, 11:33:30 PM
Quote from: mikeburr on March 04, 2022, 11:03:07 PM
jj .. thats because youre not doing the same thing

         invoke GetDlgItemInt, hWnd, 103, esi, -1
         invoke GetDlgItemInt, hWnd, esi, ...
... blackboard eraser whisles through the air ... ouch
cummon pay attention in class ...

Post complete code, please. I bet the reason is a different one. And btw why should one use esi to pass a control ID? It's a constant.
Title: Re: Problems with OWNERDRAW menu
Post by: mikeburr on March 05, 2022, 09:51:30 AM
jj running out a load of boxes !!! .. bet all you like but try it first
regards mikeb
Title: Re: Problems with OWNERDRAW menu
Post by: jj2007 on March 05, 2022, 11:20:02 AM
Quote from: mikeburr on March 05, 2022, 09:51:30 AM
jj running out a load of boxes !!! .. bet all you like but try it first
regards mikeb

Mike,

Your claim is wrong unless you prove the contrary with a complete piece of code. End of story, sorry.
Title: Re: Problems with OWNERDRAW menu
Post by: mikeburr on March 08, 2022, 01:09:15 AM
wrong jj try it
mike b
Title: Re: Problems with OWNERDRAW menu
Post by: jj2007 on March 08, 2022, 01:27:04 AM
Quote from: mikeburr on March 08, 2022, 01:09:15 AM
wrong jj try it
mike b

Try what?? Give me a piece of code that makes sense. You can modify the code that I posted for you (http://masm32.com/board/index.php?topic=9856.msg108234#msg108234). I told you already that your  invoke GetDlgItemInt, hWnd, esi, ... makes no sense because no sane programmer would pass the ID (a constant) after hWnd in a register.
Title: Re: Problems with OWNERDRAW menu
Post by: hutch-- on March 08, 2022, 04:11:52 AM
Come on guys, don't use the Campus as a debating area, it only makes it more difficult for the folks asking questions.
Title: Re: Problems with OWNERDRAW menu
Post by: jj2007 on March 08, 2022, 05:21:22 AM
Agreed, Hutch. Move this nonsense to the colosseum.