flat assembler
Message board for the users of flat assembler.

Index > Windows > [solved] custom draw texhnology

Author
Thread Post new topic Reply to topic
ProMiNick



Joined: 24 Mar 2012
Posts: 817
Location: Russian Federation, Sochi
ProMiNick 29 Jan 2025, 21:22
I tryed to reproduce MS example(whole sources & binary are located in \EXAMPLES\DIALOG\DONOR\custdtv) grabbed from page https://learn.microsoft.com/en-us/windows/win32/controls/about-custom-draw from link "SAMPLE: CustDTv Illustrates Custom Draw in a TreeView (Q248496)" (no matter link is broken for now) at bottom of that page

my reproduction is completely working example on the path \EXAMPLES\DIALOG named custdtv.ASM of {https://drive.google.com/file/d/16lk2kgwM7hb89WolM_f4WufgeyBIUiFo/view?usp=sharing}, its source:
Code:
; DialogBox example

format PE GUI 4.0
entry start

include 'win32a.inc'

PE_IMAGE_BASE = $-rva $

IDD_DIALOG = 101
IDC_TREE   = 1000

macro HANDLE value:? { dd value }
struc HANDLE value:? { . dd value }
sizeof.HANDLE=4
macro CItemData arg0:?,arg1:?,arg2:? { dd arg0,arg1,arg2 }
struc CItemData arg0:?,arg1:?,arg2:? { . dd arg0,arg1,arg2 }
sizeof.CItemData = 12
arrayoverload CItemData
ITEM_COLORS  = 1
ITEM_FONTS   = 2
ITEM_UNKNOWN = 3
CItemData.type          equ 0+symbolicasPTR
CItemData.clr           equ 4+symbolicasPTR
CItemData.clrTag        equ 8+symbolicasPTR
CItemData.hFont         equ 4+symbolicasPTR
CItemData.fontTag       equ 8+symbolicasPTR

section '.text' code readable executable

  start: RTL_C

        invoke  DialogBoxParam,PE_IMAGE_BASE,101,HWND_DESKTOP,DialogProc,0
        invoke  ExitProcess,0
flush_locals

DialogProc: RTL_C hwnddlg,msg,wparam,lparam
        cmp     [msg],WM_INITDIALOG
        je      .wminitdialog
        cmp     [msg],WM_COMMAND
        je      .wmcommand
        cmp     [msg],WM_NOTIFY
        je      .wmnotify
        cmp     [msg],WM_DESTROY
        je      .wmdestroy
  .unprocessed:
        xor     eax,eax
        jmp     .finish
  .wminitdialog:
        mov     eax,[hwnddlg]
        mov     [hwnd],eax
        invoke  GetDlgItem,[hwnddlg],IDC_TREE
        mov     [hWndTreeView],eax
        invoke  SetFocus,eax
        stdcall insertItems;,[hWndTreeView]
        jmp     .processed
  .wmcommand:
        mov     eax,[wparam]
        sub     eax,BN_CLICKED shl 16
        jz      .finish
        cmp     eax,IDCANCEL
        ja      .unprocessed
        invoke  EndDialog,[hwnddlg],eax
        jmp     .unprocessed
  .wmdestroy:
        jmp     .unprocessed
  .wmnotify:
        cmp     [wparam],IDC_TREE
        jnz     .unprocessed
        mov     eax,[lparam]
        test    eax,eax
        jz      .finish
        cmp     [eax+NMHDR.code],NM_CUSTOMDRAW
        jnz     .unprocessed
        stdcall handleCustomDraw,[eax+NMHDR.hwndFrom],[lparam]
  .handled:
        invoke  SetWindowLong,[hwnddlg],DWL_MSGRESULT,eax
  .processed:
        mov     eax,1
  .finish:
        ;exitf
        stack_cleanup callee
flush_locals

handleCustomDraw: RTL_C hwndtv,pNMTVCD
        mov     eax,[pNMTVCD]
        mov     eax,[eax+NMCUSTOMDRAWINFO.dwDrawStage]
        cmp     eax,CDDS_PREPAINT
        jz      .onprepaint
        cmp     eax,CDDS_ITEMPREPAINT
        jz      .onitemprepaint
        cmp     eax,CDDS_ITEMPOSTPAINT
        jz      .itempostpaint
        jmp     .defaault
  .onprepaint:
        mov     eax,CDRF_NOTIFYPOSTPAINT or CDRF_NOTIFYITEMDRAW
        jmp     .finish
  .onitemprepaint:
        mov     [tvis.item.mask],TVIF_HANDLE or TVIF_PARAM
        mov     eax,[pNMTVCD]
        mov     eax,[eax+NMCUSTOMDRAWINFO.dwItemSpec]
        mov     [tvis.item.hItem],eax
        invoke  SendMessage,[hwndtv],TVM_GETITEM,0,tvis.item
        mov     eax,[tvis.item.lParam]
        test    eax,eax
        jz      .retpostpaintnewfont
        cmp     [eax+CItemData.type],ITEM_COLORS
        jnz     .onfontsprepaint
        mov     eax,[pNMTVCD]
        test    [eax+NMCUSTOMDRAWINFO.uItemState],CDIS_FOCUS
        jz      .prepaintunfocus
  .prepaintfocus:
        or      [lfTreeView.lfWeight],FW_BOLD
        invoke  CreateFontIndirect,lfTreeView
        push    eax
        mov     eax,[pNMTVCD]
        push    [eax+NMCUSTOMDRAWINFO.hdc]
        invoke  SelectObject,?,?
        sub     esp,4
        invoke  DeleteObject,?
        jmp     .retpostpaintnewfont
  .prepaintunfocus:
        mov     edx,[tvis.item.lParam]
        mov     edx,[edx+CItemData.clr]
        mov     [eax+NMCUSTOMDRAW.clrText],edx
        jmp     .retpostpaintnewfont
  .onfontsprepaint:
        ;mov     eax,[pNMTVCD]
        ;invoke  SelectObject,[eax+NMCUSTOMDRAWINFO.hdc],hFont
  .retpostpaintnewfont:
        mov     eax,CDRF_NOTIFYPOSTPAINT or CDRF_NEWFONT
        jmp     .finish
  .itempostpaint:
        mov     eax,[pNMTVCD]
        cmp     eax,$100 ; WHAT A HELL? Number instead of ptr to NMCUSTOMDRAW structure for all ITEM_FONTS subitems
        jb      .defaault
        mov     eax,[eax+NMCUSTOMDRAWINFO.dwItemSpec]
        mov     [tvis.item.hItem],eax
        mov     [rc.left],eax
        invoke  SendMessage,[hwndtv],TVM_GETITEMRECT,0,rc
        mov     eax,[rc.left]
        xchg    eax,[rc.right]
        add     eax,5
        mov     [rc.left],eax
        add     [rc.right],eax
        mov     [tvis.item.mask],TVIF_HANDLE + TVIF_PARAM + TVIF_TEXT
        mov     [tvis.item.pszText],szFace
        mov     [tvis.item.cchTextMax],32
        invoke  SendMessage,[hWndTreeView],TVM_GETITEM,0,tvis.item
        mov     eax,[tvis.item.lParam]
        test    eax,eax
        jz      .finish
        cmp     [eax+CItemData.type],ITEM_COLORS
        jnz     .onfontspostpaint
        mov     eax,[pNMTVCD]
        test    [eax+NMCUSTOMDRAWINFO.uItemState],CDIS_FOCUS
        jz      .postpaintunfocus
  .postpaintfocus:
        invoke  SetTextColor,[eax+NMCUSTOMDRAWINFO.hdc],$0000FF
        push    eax
        sub     esp,4
        mov     eax,[esp]
        invoke  DrawText,eax,_szColorNames,-1,rc, DT_LEFT
        invoke  SetTextColor,?,?
  .postpaintunfocus:
        invoke  FillRect,[eax+NMCUSTOMDRAWINFO.hdc],rc,COLOR_WINDOW+1
        jmp     .defaault
  .onfontspostpaint:
        jmp     .defaault
  .defaault:
        xor     eax,eax ; CDRF_DODEFAULT
  .finish:
        ;exitf
        stack_cleanup callee
flush_locals

insertItems: RTL_C ;hWndTreeView
        mov     [tvis.item.mask],TVIF_TEXT or TVIF_PARAM
        mov     [tvis.item.lParam],CItemArray
        mov     [tvis.item.pszText],szColors
        mov     [tvis.item.cchTextMax],szColors.length
        invoke  SendMessage,[hWndTreeView],TVM_INSERTITEM,0,tvis
        mov     [tvis.hParent],eax
        invoke  SendMessage,[hWndTreeView],TVM_SELECTITEM,TVGN_CARET,eax
        mov     [Counter],8
      @@:
        add     [tvis.item.lParam],sizeof.CItemData
        mov     ecx,8
        sub     ecx,[Counter]
        mov     eax,8
        mul     ecx
        add     eax,_szColorSet
        mov     [tvis.item.pszText],eax
        invoke  SendMessage,[hWndTreeView],TVM_INSERTITEM,0,tvis
        dec     [Counter]
        jne      @B
        mov     [tvis.hParent],TVI_ROOT
        add     [tvis.item.lParam],sizeof.CItemData
        mov     [tvis.item.pszText],szFonts
        mov     [tvis.item.cchTextMax],szFonts.length
        invoke  SendMessage,[hWndTreeView],TVM_INSERTITEM,0,tvis
        mov     [tvis.hParent],eax
        push    eax
        mov     [tvis.item.mask],TVIF_TEXT
        mov     [tvis.item.pszText],_szCharSets
        mov     [tvis.item.cchTextMax],20
        mov     [Counter],9
      @@:
        invoke  SendMessage,[hWndTreeView],TVM_INSERTITEM,0,tvis
        mov     [tvis.hParent],eax
        stdcall enumFonts;,[hWndTreeView],eax,[Counter]
        mov     ecx,9
        sub     ecx,[Counter]
        mov     eax,20
        mul     ecx
        add     eax,_szCharSets+20
        mov     [tvis.item.pszText],eax
        mov     eax,[esp]
        mov     [tvis.hParent],eax
        mov     [tvis.item.cchTextMax],20
        mov     [tvis.item.mask],TVIF_TEXT
        dec     [Counter]
        jne      @B
        pop     eax
  .finish:
        ;exitf
        stack_cleanup callee
flush_locals


enumFonts: RTL_C ;hWndTreeView
        invoke  SendMessage,[hWndTreeView],WM_GETFONT,0,0
        mov     [hFont],eax
        invoke  GetObject,eax,sizeof.LOGFONT,lfTreeView
        invoke  GetDC,NULL
        push    eax

        push    edi
        mov     edi,lfTempItem
        xor     eax,eax
        mov     ecx,sizeof.LOGFONT/4
        rep     stosd
        pop     edi

        mov     eax,9+_baCharSets
        sub     eax,[Counter]
        mov     al,[eax]
        mov     [lfTempItem.lfCharSet],al
        invoke  EnumFontFamiliesEx,[esp+16],lfTempItem,enumFontFamilyProc,0,0
        invoke  ReleaseDC,0,?
  .finish:
        ;exitf
        stack_cleanup callee
flush_locals


enumFontFamilyProc: RTL_C lpelfe, lpntme, FontType, lParam
        cmp     [lpelfe],0
        jz      .finish
        mov     [tvis.item.mask],TVIF_TEXT or TVIF_PARAM
        mov     eax,[lpelfe]
        add     eax,ENUMLOGFONTEX.elfFullName
        mov     [tvis.item.lParam],CItemArray+10*sizeof.CItemData
        mov     [tvis.item.pszText],eax
        mov     [tvis.item.cchTextMax],64
        invoke  SendMessage,[hWndTreeView],TVM_INSERTITEM,0,tvis
  .finish:
        mov     eax,1
        ;exitf
        stack_cleanup callee
flush_locals

section '.data' data readable writeable

        hWndTreeView    HANDLE
        hwnd            HANDLE
        hFont           HANDLE
        lfTreeView      LOGFONT
        lfTempItem      LOGFONT
        Counter         dd ?
        rc              RECT
        tvis            TV_INSERTSTRUCT TVI_ROOT,0
        CItemArray      CItemData ITEM_UNKNOWN
                        CItemData ITEM_COLORS,$FFFFFF,0
                        CItemData ITEM_COLORS,$FF0000,1
                        CItemData ITEM_COLORS,$00FF00,2
                        CItemData ITEM_COLORS,$0000FF,3
                        CItemData ITEM_COLORS,$FF00FF,4
                        CItemData ITEM_COLORS,$00FFFF,5
                        CItemData ITEM_COLORS,$FFFF00,6
                        CItemData ITEM_COLORS,$000000,7
                        CItemData ITEM_UNKNOWN
                        CItemData ITEM_FONTS,0,0
        szColors        db 'Some Colors and their (HTML) names',0
                        .length = $-szColors-1
        szFonts        db 'Fonts installed in the system',0
                        .length = $-szFonts-1
        _szColorSet     TCHAR[8] '$FFFFFF',0
                        TCHAR[8] '$FF0000',0
                        TCHAR[8] '$00FF00',0
                        TCHAR[8] '$0000FF',0
                        TCHAR[8] '$FF00FF',0
                        TCHAR[8] '$00FFFF',0
                        TCHAR[8] '$FFFF00',0
                        TCHAR[8] '$000000',0
        _szCharSets     TCHAR[20] 'ANSI_CHARSET',0
                        TCHAR[20] 'BALTIC_CHARSET',0
                        TCHAR[20] 'CHINESEBIG5_CHARSET',0
                        TCHAR[20] 'DEFAULT_CHARSET',0
                        TCHAR[20] 'EASTEUROPE_CHARSET',0
                        TCHAR[20] 'GB2312_CHARSET',0
                        TCHAR[20] 'GREEK_CHARSET',0
                        TCHAR[20] 'HANGUL_CHARSET',0
                        TCHAR[20] 'MAC_CHARSET',0
                        TCHAR[20] 'OEM_CHARSET',0
                        TCHAR[20] 'RUSSIAN_CHARSET',0
                        TCHAR[20] 'SHIFTJIS_CHARSET',0
                        TCHAR[20] 'SYMBOL_CHARSET',0
                        TCHAR[20] 'TURKISH_CHARSET',0
        _szColorNames   TCHAR[10] 'White',0
        _baCharSets     db ANSI_CHARSET,\
                           BALTIC_CHARSET,\
                           CHINESEBIG5_CHARSET,\
                           DEFAULT_CHARSET,\
                           EASTEUROPE_CHARSET,\
                           GB2312_CHARSET,\
                           GREEK_CHARSET,\
                           HANGEUL_CHARSET,\
                           MAC_CHARSET,\
                           OEM_CHARSET,\
                           RUSSIAN_CHARSET,\
                           SHIFTJIS_CHARSET,\
                           SYMBOL_CHARSET,\
                           TURKISH_CHARSET,\
                           $FF
        szFace          TCHAR[33]

section '.idata' import data readable writeable

  library kernel,'KERNEL32.DLL',\
          user,'USER32.DLL',\
          gdi,'GDI32.DLL',\
          comctl,'COMCTL32.DLL'

  import kernel,\
         GetModuleHandle,'GetModuleHandleA',\
         ExitProcess,'ExitProcess'

  import user,\
         DialogBoxParam,'DialogBoxParamA',\
         DrawText,'DrawTextA',\
         CreateWindowEx,'CreateWindowExA',\
         CallWindowProc,'CallWindowProcA',\
         CheckRadioButton,'CheckRadioButton',\
         FillRect,'FillRect',\
         GetClientRect,'GetClientRect',\
         GetDC,'GetDC',\
         GetDlgItem,'GetDlgItem',\
         GetDlgItemText,'GetDlgItemTextA',\
         IsDlgButtonChecked,'IsDlgButtonChecked',\
         MessageBox,'MessageBoxA',\
         ReleaseDC,'ReleaseDC',\
         SetFocus,'SetFocus',\
         SetWindowLong,'SetWindowLongA',\
         SetWindowText,'SetWindowTextA',\
         SetProp,'SetPropA',\
         SendMessage,'SendMessageA',\
         EndDialog,'EndDialog'

  import gdi,\
         CreateFontIndirect,'CreateFontIndirectA',\
         DeleteObject,'DeleteObject',\
         GetObject,'GetObjectA',\
         EnumFontFamiliesEx,'EnumFontFamiliesExA',\
         SelectObject,'SelectObject',\
         SetTextColor,'SetTextColor'

  import comctl,\
         InitCommonControls,'InitCommonControls'
         virtual
         dd InitCommonControls
         end virtual

section '.rsrc' resource data readable

  directory RT_DIALOG,dialogs

  resource dialogs,\
           IDD_DIALOG,LANG_ENGLISH+SUBLANG_DEFAULT,demonstration

  dialog demonstration,'Custom Draw TreeView',0, 0, 318, 262,DS_SETFONT or DS_MODALFRAME or DS_CENTER or WS_POPUPWINDOW or WS_CAPTION
    dialogitem 'SysTreeView32','Tree1',IDC_TREE, 22, 19, 200, 224,WS_VISIBLE+TVS_HASBUTTONS + TVS_HASLINES + TVS_LINESATROOT + WS_BORDER + WS_TABSTOP
    dialogitem 'BUTTON','OK',IDOK,261, 7, 50, 14,WS_VISIBLE+WS_TABSTOP+BS_DEFPUSHBUTTON
    dialogitem 'BUTTON','C&ancel',IDCANCEL,261, 24, 50, 14,WS_VISIBLE+WS_TABSTOP+BS_PUSHBUTTON
    dialogitem 'BUTTON',' Colors && Fonts ',-1,7,7,230,248,WS_VISIBLE+BS_GROUPBOX
  enddialog    

the most interesting part OS return usual notify message structure for first half of treeview items (where custom drawed color) and return regular integer values(less than 255) insted of ptr to notify message structure for rest of treeview items (where custom drawed font)
Code:
  .itempostpaint:
        mov     eax,[pNMTVCD]
        cmp     eax,$100 ; WHAT A HELL? Number instead of ptr to NMCUSTOMDRAW structure for all ITEM_FONTS subitems
        jb      .defaault
        mov     eax,[eax+NMCUSTOMDRAWINFO.dwItemSpec]    
that is my workaround to force application do not crash
Code:
        cmp     eax,$100 ; WHAT A HELL? Number instead of ptr to NMCUSTOMDRAW structure for all ITEM_FONTS subitems
        jb      .defaault    
Why in item pre paint state notify message structure was accessible for all items, but for item post paint state - only for half of items

I`m understand that my syntax is bit different from official fasm so I attach full environment for compile
{https://drive.google.com/file/d/16lk2kgwM7hb89WolM_f4WufgeyBIUiFo/view?usp=sharing}.

due to absence of post point state my reproduction not completely reproduce all custom drawing from example

P.S. in \EXAMPLES\DIALOG\DONOR there another example of custom draw technology of author (email:rouse79@yandex.ru)(delphi programmer) its reproduction on more early state on the path \EXAMPLES\DIALOG named [strikeout]TreeList.ASM[/strikeout] DIALOG__.ASM

What result I get for now? - I found difference in bool DialogProc(...) & int WndProc(...) - Dialog Box procedure is realy boolean and for cases of returning to OS other values than handled(aka True) or not(aka False) exist DWL_MSGRESULT property of dialog (so all notify reactions must be passed this way)
Code:
        invoke  SetWindowLong,[hwnddlg],DWL_MSGRESULT,eax ; where in eax passed return code    

_________________
I don`t like to refer by "you" to one person.
My soul requires acronim "thou" instead.
Post 29 Jan 2025, 21:22
View user's profile Send private message Send e-mail Reply with quote
bitRAKE



Joined: 21 Jul 2003
Posts: 4225
Location: vpcmpistri
bitRAKE 30 Jan 2025, 04:58
Unable to build your source code, but I did find a copy of the original C++.

There are several subtleties resulting from your bypassing handleNotify function that is present in the original code.
Code:
   case WM_NOTIFY:
      {
         long lResult = handleNotify(hWndDlg, (int) wParam, (LPNMHDR) lParam);
         SetWindowLong(hWndDlg, DWL_MSGRESULT, lResult); 
         return TRUE;
      }
      break;    
... WM_NOTIFY always sets the dialog result value and returns TRUE. Your WM_NOTIFY does something different. Since the code is relying on the state-machine within the control, it's important to trigger the transitions.

I wasn't able to get the type of error you outline regarding the items. So, I'm unsure if this change would solve the problem.

_________________
¯\(°_o)/¯ “languages are not safe - uses can be” Bjarne Stroustrup
Post 30 Jan 2025, 04:58
View user's profile Send private message Visit poster's website Reply with quote
ProMiNick



Joined: 24 Mar 2012
Posts: 817
Location: Russian Federation, Sochi
ProMiNick 30 Jan 2025, 07:19
bitRAKE wrote:
Unable to build your source code
because of that
ProMiNick wrote:
I attach full environment for compile
{https://drive.google.com/file/d/16lk2kgwM7hb89WolM_f4WufgeyBIUiFo/view?usp=sharing}.
with patched fasm inside & with includes tree to allow my syntax. Everething is still selfhosted.
bitRAKE wrote:
Your WM_NOTIFY does something different

Actualy no.
handleNotify is only wrapper around of handleCustomDraw, where filtered from processing messages from other controls than IDC_TREE, where lParam of message is valid ptr to NMHDR structure, and where field of that structure notify code is NM_CUSTOMDRAW - this wrapping I moved to internal of Dialog Box handling because it is dosn`t relate to custom draw handling, but relate to filtering custom draw from other messages (because we couldn`t handle other notifies there is no matter we say to OS that we couldn`t handle them via boolean result (Handled|or not) or via integer property DWL_MSGRESULT saying 0 - not handled)
And of course I probe thour variant. I changed this:
Code:
  .wmnotify:
        cmp     [wparam],IDC_TREE
        jnz     .unprocessed
        mov     eax,[lparam]
        test    eax,eax
        jz      .finish
        cmp     [eax+NMHDR.code],NM_CUSTOMDRAW
        jnz     .unprocessed
        stdcall handleCustomDraw,[eax+NMHDR.hwndFrom],[lparam]
  .handled:
        invoke  SetWindowLong,[hwnddlg],DWL_MSGRESULT,eax    
to this
Code:
  .wmnotify:
        cmp     [wparam],IDC_TREE
        jnz     .handled
        mov     eax,[lparam]
        test    eax,eax
        jz      .handled
        cmp     [eax+NMHDR.code],NM_CUSTOMDRAW
        jnz     .handled
        stdcall handleCustomDraw,[eax+NMHDR.hwndFrom],[lparam]
  .handled:
        invoke  SetWindowLong,[hwnddlg],DWL_MSGRESULT,eax    
so result to OS goes via DWL_MSGRESULT parameter. that not solves the problem. As I sad - this only filtering of unhandled states. No matter how to say to OS about such filtering

_________________
I don`t like to refer by "you" to one person.
My soul requires acronim "thou" instead.
Post 30 Jan 2025, 07:19
View user's profile Send private message Send e-mail Reply with quote
macomics



Joined: 26 Jan 2021
Posts: 1146
Location: Russia
macomics 30 Jan 2025, 07:49
ProMiNick wrote:
my reproduction is completely working example on the path \EXAMPLES\DIALOG named custdtv.ASM of {https://drive.google.com/file/d/16lk2kgwM7hb89WolM_f4WufgeyBIUiFo/view?usp=sharing}, its source:

...

I`m understand that my syntax is bit different from official fasm so I attach full environment for compile
{https://drive.google.com/file/d/16lk2kgwM7hb89WolM_f4WufgeyBIUiFo/view?usp=sharing}.

due to absence of post point state my reproduction not completely reproduce all custom drawing from example
Upload it to yandex disk or somewhere else. Google deleted everything.
Post 30 Jan 2025, 07:49
View user's profile Send private message Reply with quote
ProMiNick



Joined: 24 Mar 2012
Posts: 817
Location: Russian Federation, Sochi
ProMiNick 30 Jan 2025, 08:27
Post 30 Jan 2025, 08:27
View user's profile Send private message Send e-mail Reply with quote
ProMiNick



Joined: 24 Mar 2012
Posts: 817
Location: Russian Federation, Sochi
ProMiNick 30 Jan 2025, 09:26
I found my bug - stack was corrupted.
I add feature to pass parameters to procedure when they already at stack & modified macro pushd, but I forgot invoke internals that counts amount of realy pushed args
pushd modification
Code:
macro pushd value {
        match :=? any,%deny?:value: \{
        rept 0 \{\} rept 1 \{ pushd value \} }

macro pushd value {
        match =??,value \{ define %deny?
        rept 0 \{\} rept 1 \{ pushd value \} }      

and
Code:
macro %call32 proc,toeax:eax,toedx:edx,toecx:ecx,C:0,args& {
        local s
        s=%s
        if ~args eq
                pushRTL args,?? ; add ?? to allow pass ? as values already in stack
        end if
        s= %s-s
        initreg eax,toeax, edx,toedx, ecx,toecx
        call proc
        irpv v,managed_calls \{ \common \}
        if C & s
                add esp,s
        else
                stackorg %s-s
        end if }
macro invoke proc,args& { %call32 dword [proc],,,,,args }    
but this pushd ? doesn`t effect on %s so stack not properly restored from invoke
I add
Code:
macro fixcounter s,[arg] {
        match =?,arg \{ s=s-4 \}
        match =?:qword,arg \{ s=s-8 \}
        match =?:tword,arg \{ s=s-12 \}
        match =?:dqword,arg \{ s=s-16 \} }     
and count that fix in invoke internals
Code:
macro %call32 proc,toeax:eax,toedx:edx,toecx:ecx,C:0,args& {
        local s
        s=%s
        if ~args eq
                pushRTL args,??
        end if
        fixcounter s,args
        s= %s-s
        initreg eax,toeax, edx,toedx, ecx,toecx
        call proc
        irpv v,managed_calls \{ \common \}
        if C & s
                add esp,s
        else
                stackorg %s-s
        end if }    
that solves corrupted [pNMTVCD]

app stop to crash. cut of unneededs
Code:
        cmp     eax,$100 ; WHAT A HELL? Number instead of ptr to NMCUSTOMDRAW structure for all ITEM_FONTS subitems
        jb      .defaault     
and uncomment
Code:
  .onfontsprepaint:
        ;mov     eax,[pNMTVCD]
        ;invoke  SelectObject,[eax+NMCUSTOMDRAWINFO.hdc],hFont    
add "jmp .defaault" between
Code:
        invoke  SetTextColor,?,?
        jmp     .defaault
  .postpaintunfocus:    
behavior still not exactly as in MS example but stack now is OK.
current state of custdtv.ASM
Code:
; DialogBox example

format PE GUI 4.0
entry start

include 'win32a.inc'

PE_IMAGE_BASE = $-rva $

IDD_DIALOG = 101
IDC_TREE   = 1000

macro HANDLE value:? { dd value }
struc HANDLE value:? { . dd value }
sizeof.HANDLE=4
macro CItemData arg0:?,arg1:?,arg2:? { dd arg0,arg1,arg2 }
struc CItemData arg0:?,arg1:?,arg2:? { . dd arg0,arg1,arg2 }
sizeof.CItemData = 12
arrayoverload CItemData
ITEM_COLORS  = 1
ITEM_FONTS   = 2
ITEM_UNKNOWN = 3
CItemData.type          equ 0+symbolicasPTR
CItemData.clr           equ 4+symbolicasPTR
CItemData.clrTag        equ 8+symbolicasPTR
CItemData.hFont         equ 4+symbolicasPTR
CItemData.fontTag       equ 8+symbolicasPTR

section '.text' code readable executable

  start: RTL_C

        invoke  DialogBoxParam,PE_IMAGE_BASE,101,HWND_DESKTOP,DialogProc,0
        invoke  ExitProcess,0
flush_locals

DialogProc: RTL_C hwnddlg,msg,wparam,lparam
        cmp     [msg],WM_INITDIALOG
        je      .wminitdialog
        cmp     [msg],WM_COMMAND
        je      .wmcommand
        cmp     [msg],WM_NOTIFY
        je      .wmnotify
        cmp     [msg],WM_DESTROY
        je      .wmdestroy
  .unprocessed:
        xor     eax,eax
        jmp     .finish
  .wminitdialog:
        mov     eax,[hwnddlg]
        mov     [hwnd],eax
        invoke  GetDlgItem,[hwnddlg],IDC_TREE
        mov     [hWndTreeView],eax
        invoke  SetFocus,eax
        stdcall insertItems;,[hWndTreeView]
        jmp     .processed
  .wmcommand:
        mov     eax,[wparam]
        sub     eax,BN_CLICKED shl 16
        jz      .finish
        cmp     eax,IDCANCEL
        ja      .unprocessed
        invoke  EndDialog,[hwnddlg],eax
        jmp     .unprocessed
  .wmdestroy:
        jmp     .unprocessed
  .wmnotify:
        cmp     [wparam],IDC_TREE
        jnz     .unprocessed
        mov     eax,[lparam]
        test    eax,eax
        jz      .finish
        cmp     [eax+NMHDR.code],NM_CUSTOMDRAW
        jnz     .unprocessed
        stdcall handleCustomDraw,[eax+NMHDR.hwndFrom],[lparam]
  .handled:
        invoke  SetWindowLong,[hwnddlg],DWL_MSGRESULT,eax
  .processed:
        mov     eax,1
  .finish:
        ;exitf
        stack_cleanup callee
flush_locals

handleCustomDraw: RTL_C hwndtv,pNMTVCD
        mov     eax,[pNMTVCD]
        mov     eax,[eax+NMCUSTOMDRAWINFO.dwDrawStage]
        cmp     eax,CDDS_PREPAINT
        jz      .onprepaint
        cmp     eax,CDDS_ITEMPREPAINT
        jz      .onitemprepaint
        cmp     eax,CDDS_ITEMPOSTPAINT
        jz      .itempostpaint
        jmp     .defaault
  .onprepaint:
        mov     eax,CDRF_NOTIFYPOSTPAINT or CDRF_NOTIFYITEMDRAW
        jmp     .finish
  .onitemprepaint:
        mov     [tvis.item.mask],TVIF_HANDLE or TVIF_PARAM
        mov     eax,[pNMTVCD]
        mov     eax,[eax+NMCUSTOMDRAWINFO.dwItemSpec]
        mov     [tvis.item.hItem],eax
        invoke  SendMessage,[hwndtv],TVM_GETITEM,0,tvis.item
        mov     eax,[tvis.item.lParam]
        test    eax,eax
        jz      .retpostpaintnewfont
        cmp     [eax+CItemData.type],ITEM_COLORS
        jnz     .onfontsprepaint
        mov     eax,[pNMTVCD]
        test    [eax+NMCUSTOMDRAWINFO.uItemState],CDIS_FOCUS
        jz      .prepaintunfocus
  .prepaintfocus:
        or      [lfTreeView.lfWeight],FW_BOLD
        invoke  CreateFontIndirect,lfTreeView
        push    eax
        mov     eax,[pNMTVCD]
        push    [eax+NMCUSTOMDRAWINFO.hdc]
        invoke  SelectObject,?,?
        sub     esp,4
        invoke  DeleteObject,?
        jmp     .retpostpaintnewfont
  .prepaintunfocus:
        mov     edx,[tvis.item.lParam]
        mov     edx,[edx+CItemData.clr]
        mov     [eax+NMCUSTOMDRAW.clrText],edx
        jmp     .retpostpaintnewfont
  .onfontsprepaint:
        mov     eax,[pNMTVCD]
        invoke  SelectObject,[eax+NMCUSTOMDRAWINFO.hdc],hFont
  .retpostpaintnewfont:
        mov     eax,CDRF_NOTIFYPOSTPAINT or CDRF_NEWFONT
        jmp     .finish
  .itempostpaint:
        mov     eax,[pNMTVCD]
        mov     eax,[eax+NMCUSTOMDRAWINFO.dwItemSpec]
        mov     [tvis.item.hItem],eax
        mov     [rc.left],eax
        invoke  SendMessage,[hwndtv],TVM_GETITEMRECT,0,rc
        mov     eax,[rc.left]
        xchg    eax,[rc.right]
        add     eax,5
        mov     [rc.left],eax
        add     [rc.right],eax
        mov     [tvis.item.mask],TVIF_HANDLE + TVIF_PARAM + TVIF_TEXT
        mov     [tvis.item.pszText],szFace
        mov     [tvis.item.cchTextMax],32
        invoke  SendMessage,[hWndTreeView],TVM_GETITEM,0,tvis.item
        mov     eax,[tvis.item.lParam]
        test    eax,eax
        jz      .finish
        cmp     [eax+CItemData.type],ITEM_COLORS
        jnz     .onfontspostpaint
        mov     eax,[pNMTVCD]
        test    [eax+NMCUSTOMDRAWINFO.uItemState],CDIS_FOCUS
        jz      .postpaintunfocus
  .postpaintfocus:
        invoke  SetTextColor,[eax+NMCUSTOMDRAWINFO.hdc],$0000FF
        push    eax
        sub     esp,4
        mov     eax,[esp]
        invoke  DrawText,eax,_szColorNames,-1,rc, DT_LEFT
        invoke  SetTextColor,?,?
        jmp     .defaault
  .postpaintunfocus:
        invoke  FillRect,[eax+NMCUSTOMDRAWINFO.hdc],rc,COLOR_WINDOW+1
        jmp     .defaault
  .onfontspostpaint:
        jmp     .defaault
  .defaault:
        xor     eax,eax ; CDRF_DODEFAULT
  .finish:
        ;exitf
        stack_cleanup callee
flush_locals

insertItems: RTL_C ;hWndTreeView
        mov     [tvis.item.mask],TVIF_TEXT or TVIF_PARAM
        mov     [tvis.item.lParam],CItemArray
        mov     [tvis.item.pszText],szColors
        mov     [tvis.item.cchTextMax],szColors.length
        invoke  SendMessage,[hWndTreeView],TVM_INSERTITEM,0,tvis
        mov     [tvis.hParent],eax
        invoke  SendMessage,[hWndTreeView],TVM_SELECTITEM,TVGN_CARET,eax
        mov     [Counter],8
      @@:
        add     [tvis.item.lParam],sizeof.CItemData
        mov     ecx,8
        sub     ecx,[Counter]
        mov     eax,8
        mul     ecx
        add     eax,_szColorSet
        mov     [tvis.item.pszText],eax
        invoke  SendMessage,[hWndTreeView],TVM_INSERTITEM,0,tvis
        dec     [Counter]
        jne      @B
        mov     [tvis.hParent],TVI_ROOT
        add     [tvis.item.lParam],sizeof.CItemData
        mov     [tvis.item.pszText],szFonts
        mov     [tvis.item.cchTextMax],szFonts.length
        invoke  SendMessage,[hWndTreeView],TVM_INSERTITEM,0,tvis
        mov     [tvis.hParent],eax
        push    eax
        mov     [tvis.item.mask],TVIF_TEXT
        mov     [tvis.item.pszText],_szCharSets
        mov     [tvis.item.cchTextMax],20
        mov     [Counter],9
      @@:
        invoke  SendMessage,[hWndTreeView],TVM_INSERTITEM,0,tvis
        mov     [tvis.hParent],eax
        stdcall enumFonts;,[hWndTreeView],eax,[Counter]
        mov     ecx,9
        sub     ecx,[Counter]
        mov     eax,20
        mul     ecx
        add     eax,_szCharSets+20
        mov     [tvis.item.pszText],eax
        mov     eax,[esp]
        mov     [tvis.hParent],eax
        mov     [tvis.item.cchTextMax],20
        mov     [tvis.item.mask],TVIF_TEXT
        dec     [Counter]
        jne      @B
        pop     eax
  .finish:
        ;exitf
        stack_cleanup callee
flush_locals


enumFonts: RTL_C ;hWndTreeView
        invoke  SendMessage,[hWndTreeView],WM_GETFONT,0,0
        mov     [hFont],eax
        invoke  GetObject,eax,sizeof.LOGFONT,lfTreeView
        invoke  GetDC,NULL
        push    eax

        push    edi
        mov     edi,lfTempItem
        xor     eax,eax
        mov     ecx,sizeof.LOGFONT/4
        rep     stosd
        pop     edi

        mov     eax,9+_baCharSets
        sub     eax,[Counter]
        mov     al,[eax]
        mov     [lfTempItem.lfCharSet],al
        invoke  EnumFontFamiliesEx,[esp+16],lfTempItem,enumFontFamilyProc,0,CItemArray+10*sizeof.CItemData
        invoke  ReleaseDC,0,?
  .finish:
        ;exitf
        stack_cleanup callee
flush_locals


enumFontFamilyProc: RTL_C lpelfe, lpntme, FontType, lParam
        cmp     [lpelfe],0
        jz      .finish
        mov     [tvis.item.mask],TVIF_TEXT or TVIF_PARAM
        mov     eax,[lpelfe]
        add     eax,ENUMLOGFONTEX.elfFullName
        mov     [tvis.item.lParam],CItemArray+10*sizeof.CItemData
        mov     [tvis.item.pszText],eax
        mov     [tvis.item.cchTextMax],64
        invoke  SendMessage,[hWndTreeView],TVM_INSERTITEM,0,tvis
  .finish:
        mov     eax,1
        ;exitf
        stack_cleanup callee
flush_locals

section '.data' data readable writeable

        hWndTreeView    HANDLE
        hwnd            HANDLE
        hFont           HANDLE
        lfTreeView      LOGFONT
        lfTempItem      LOGFONT
        Counter         dd ?
        rc              RECT
        tvis            TV_INSERTSTRUCT TVI_ROOT,0
        CItemArray      CItemData ITEM_UNKNOWN
                        CItemData ITEM_COLORS,$FFFFFF,0
                        CItemData ITEM_COLORS,$FF0000,1
                        CItemData ITEM_COLORS,$00FF00,2
                        CItemData ITEM_COLORS,$0000FF,3
                        CItemData ITEM_COLORS,$FF00FF,4
                        CItemData ITEM_COLORS,$00FFFF,5
                        CItemData ITEM_COLORS,$FFFF00,6
                        CItemData ITEM_COLORS,$000000,7
                        CItemData ITEM_UNKNOWN
                        CItemData ITEM_FONTS,0,0
        szColors        db 'Some Colors and their (HTML) names',0
                        .length = $-szColors-1
        szFonts        db 'Fonts installed in the system',0
                        .length = $-szFonts-1
        _szColorSet     TCHAR[8] '$FFFFFF',0
                        TCHAR[8] '$FF0000',0
                        TCHAR[8] '$00FF00',0
                        TCHAR[8] '$0000FF',0
                        TCHAR[8] '$FF00FF',0
                        TCHAR[8] '$00FFFF',0
                        TCHAR[8] '$FFFF00',0
                        TCHAR[8] '$000000',0
        _szCharSets     TCHAR[20] 'ANSI_CHARSET',0
                        TCHAR[20] 'BALTIC_CHARSET',0
                        TCHAR[20] 'CHINESEBIG5_CHARSET',0
                        TCHAR[20] 'DEFAULT_CHARSET',0
                        TCHAR[20] 'EASTEUROPE_CHARSET',0
                        TCHAR[20] 'GB2312_CHARSET',0
                        TCHAR[20] 'GREEK_CHARSET',0
                        TCHAR[20] 'HANGUL_CHARSET',0
                        TCHAR[20] 'MAC_CHARSET',0
                        TCHAR[20] 'OEM_CHARSET',0
                        TCHAR[20] 'RUSSIAN_CHARSET',0
                        TCHAR[20] 'SHIFTJIS_CHARSET',0
                        TCHAR[20] 'SYMBOL_CHARSET',0
                        TCHAR[20] 'TURKISH_CHARSET',0
        _szColorNames   TCHAR[10] 'White',0
        _baCharSets     db ANSI_CHARSET,\
                           BALTIC_CHARSET,\
                           CHINESEBIG5_CHARSET,\
                           DEFAULT_CHARSET,\
                           EASTEUROPE_CHARSET,\
                           GB2312_CHARSET,\
                           GREEK_CHARSET,\
                           HANGEUL_CHARSET,\
                           MAC_CHARSET,\
                           OEM_CHARSET,\
                           RUSSIAN_CHARSET,\
                           SHIFTJIS_CHARSET,\
                           SYMBOL_CHARSET,\
                           TURKISH_CHARSET,\
                           $FF
        szFace          TCHAR[33]

section '.idata' import data readable writeable

  library kernel,'KERNEL32.DLL',\
          user,'USER32.DLL',\
          gdi,'GDI32.DLL',\
          comctl,'COMCTL32.DLL'

  import kernel,\
         GetModuleHandle,'GetModuleHandleA',\
         ExitProcess,'ExitProcess'

  import user,\
         DialogBoxParam,'DialogBoxParamA',\
         DrawText,'DrawTextA',\
         CreateWindowEx,'CreateWindowExA',\
         CallWindowProc,'CallWindowProcA',\
         CheckRadioButton,'CheckRadioButton',\
         FillRect,'FillRect',\
         GetClientRect,'GetClientRect',\
         GetDC,'GetDC',\
         GetDlgItem,'GetDlgItem',\
         GetDlgItemText,'GetDlgItemTextA',\
         IsDlgButtonChecked,'IsDlgButtonChecked',\
         MessageBox,'MessageBoxA',\
         ReleaseDC,'ReleaseDC',\
         SetFocus,'SetFocus',\
         SetWindowLong,'SetWindowLongA',\
         SetWindowText,'SetWindowTextA',\
         SetProp,'SetPropA',\
         SendMessage,'SendMessageA',\
         EndDialog,'EndDialog'

  import gdi,\
         CreateFontIndirect,'CreateFontIndirectA',\
         DeleteObject,'DeleteObject',\
         GetObject,'GetObjectA',\
         EnumFontFamiliesEx,'EnumFontFamiliesExA',\
         SelectObject,'SelectObject',\
         SetTextColor,'SetTextColor'

  import comctl,\
         InitCommonControls,'InitCommonControls'
         virtual
         dd InitCommonControls
         end virtual

section '.rsrc' resource data readable

  directory RT_DIALOG,dialogs

  resource dialogs,\
           IDD_DIALOG,LANG_ENGLISH+SUBLANG_DEFAULT,demonstration

  dialog demonstration,'Custom Draw TreeView',0, 0, 318, 262,DS_SETFONT or DS_MODALFRAME or DS_CENTER or WS_POPUPWINDOW or WS_CAPTION
    dialogitem 'SysTreeView32','Tree1',IDC_TREE, 22, 19, 200, 224,WS_VISIBLE+TVS_HASBUTTONS + TVS_HASLINES + TVS_LINESATROOT + WS_BORDER + WS_TABSTOP
    dialogitem 'BUTTON','OK',IDOK,261, 7, 50, 14,WS_VISIBLE+WS_TABSTOP+BS_DEFPUSHBUTTON
    dialogitem 'BUTTON','C&ancel',IDCANCEL,261, 24, 50, 14,WS_VISIBLE+WS_TABSTOP+BS_PUSHBUTTON
    dialogitem 'BUTTON',' Colors && Fonts ',-1,7,7,230,248,WS_VISIBLE+BS_GROUPBOX
  enddialog    
modificated compile environment(patched fasm & includes tree) https://www.dropbox.com/scl/fi/yxir1keop3d71x85rrl6d/fasmw17332mx.zip?rlkey=vhbgdzaws322rv81eujkjj241&st=5cj3u7j4&dl=0


Description:
Filesize: 11.14 KB
Viewed: 706 Time(s)

custdtv.png



_________________
I don`t like to refer by "you" to one person.
My soul requires acronim "thou" instead.
Post 30 Jan 2025, 09:26
View user's profile Send private message Send e-mail Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2025, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.