News:

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

Main Menu

Using DLGTEMPLATEEX structure

Started by zedd151, March 28, 2025, 03:00:06 PM

Previous topic - Next topic

zedd151

Continuing my work in shunning resource files...

Using hutch's macros from "\masm32\include\dialogs.inc" to create an 'in memory' dialog box, the code looks like this:
Dialog "Dialog Template", "MS Sans Serif", 8, WS_OVERLAPPEDWINDOW, 0, 50, 50, 185, 120, 1024
CallModalDialog iinstance, 0, DlgProc, 0

Hutch's macros:
      Dialog MACRO quoted_text_title,quoted_font,fsize,dstyle,ctlcnt,tx,ty,wd,ht,bsize
        push esi
        push edi
        invoke GlobalAlloc,GMEM_FIXED or GMEM_ZEROINIT,bsize
        mov esi, eax
        mov edi, esi
        mov DWORD PTR [edi+0],  DS_SETFONT or dstyle
        mov WORD  PTR [edi+8],  ctlcnt
        mov WORD  PTR [edi+10], tx
        mov WORD  PTR [edi+12], ty
        mov WORD  PTR [edi+14], wd
        mov WORD  PTR [edi+16], ht
        add edi, 22
        ustring quoted_text_title
        mov WORD PTR [edi], fsize
        add edi, 2
        ustring quoted_font
      ENDM

      CallModalDialog MACRO Instance,Parent,DlgProc,lpExtra
        invoke DialogBoxIndirectParam,Instance,esi,Parent,
                                      ADDR DlgProc,lpExtra
        push eax                ;; preserve return value
        invoke GlobalFree,esi  ;; free memory
        pop eax                ;; restore return value
        pop edi
        pop esi
      ENDM

The resulting disassembly:
push esi
push edi
push 0400h
push 040h
call GlobalAlloc
mov esi, eax
mov edi, esi
mov dword ptr [edi], 080840h
mov word ptr [edi+8], 0
mov word ptr [edi+0Ah], 032h
mov word ptr [edi+0Ch], 032h
mov word ptr [edi+0Eh], 096h
mov word ptr [edi+010h], 050h
add edi, 016h
push 0Eh
push edi
push -1
push 0403000h ; ASCII "Simple Dialog"
push 1
push 0
call MultiByteToWideChar
add edi, 01Ch
mov word ptr [edi], 0Ah
add edi, 2
push 0Eh
push edi
push -1
push 040300Eh ; ASCII "MS Sans Serif"
push 1
push 0
call MultiByteToWideChar
add edi, 01Ch
push 0
push 040109Eh
push 0
push esi
push dword ptr [0403020h] ; simple.00400000
call DialogBoxIndirectParamA
push eax
push esi
call GlobalFree
pop eax
pop edi
pop esi

Yuck. Looks awful messy. Surely there has got to be a better way.

Has anyone done any work using the DLGTEMPLATEEX structure the way it is supposed to be used (using proper structure member names) ?

DLGTEMPLATEEX in C:
typedef struct {
  WORD      dlgVer;
  WORD      signature;
  DWORD    helpID;
  DWORD    exStyle;
  DWORD    style;
  WORD      cDlgItems;
  short    x;
  short    y;
  short    cx;
  short    cy;
  sz_Or_Ord menu;
  sz_Or_Ord windowClass;
  WCHAR    title[titleLen];
  WORD      pointsize;
  WORD      weight;
  BYTE      italic;
  BYTE      charset;
  WCHAR    typeface[stringLen];
}  DLGTEMPLATEEX
;
I could probably cobble together working code, but I want to do it properly.

Obviously the two Unicode strings have a variable length. How does Windows know the size of the structure for instance, or the length of those strings?
¯\_(ツ)_/¯   :azn:

'As we don't do "requests", show us your code first.'  -  hutch—

sinsi

That code doesn't look like it uses DLGTEMPLATEEX, the offsets are all wrong.

typedef struct {
  DWORD style;
  DWORD dwExtendedStyle;
  WORD  cdit;
  short x;
  short y;
  short cx;
  short cy;
} DLGTEMPLATE;

zedd151

Quote from: sinsi on March 28, 2025, 03:11:43 PMThat code doesn't look like it uses DLGTEMPLATEEX, the offsets are all wrong.
I figured as much. But I would like to use the DLGTEMPLATEEX structure, and properly.
But I would use my own ascii to unicorn routine.
I'm fiddling with some code...
¯\_(ツ)_/¯   :azn:

'As we don't do "requests", show us your code first.'  -  hutch—

sinsi

Quote from: zedd151 on March 28, 2025, 03:14:08 PMI'm fiddling with some code...
Simple, load a byte and write a word  :biggrin:
Now where have I seen that before...

zedd151

Quote from: sinsi on March 28, 2025, 03:26:53 PM
Quote from: zedd151 on March 28, 2025, 03:14:08 PMI'm fiddling with some code...
Simple, load a byte and write a word  :biggrin:
Now where have I seen that before...
No. I have that code already, I'm fiddling with the structure.   :eusa_boohoo:  :eusa_boohoo:
¯\_(ツ)_/¯   :azn:

'As we don't do "requests", show us your code first.'  -  hutch—

sinsi

Quote from: zedd151 on March 28, 2025, 03:35:31 PMI'm fiddling with the structure.  :eusa_boohoo:  :eusa_boohoo:
Good luck with that, there are variable-length fields in the middle  :nie:
Putting the data in should be straightforward but you can't use the "structure" to do it.
Once you hit sz_Or_Ord the structure doesn't apply.

As Microsoft warn,
QuoteThe DLGTEMPLATEEX structure is not defined in any standard header file. The structure definition is provided here to explain the format of an extended template for a dialog box.

zedd151

Seems like a real fustercluck.  :undecided:
I'll use hutch's code as a guide, but I'll try to do it a slightly better way.

Else I'll just bite the bullet and keep using a resource dialog box.  :eusa_boohoo:  :eusa_boohoo:
It's almost midnight here.... I will resume tomorrow.
¯\_(ツ)_/¯   :azn:

'As we don't do "requests", show us your code first.'  -  hutch—

NoCforMe

I know all about creating in-memory dialog templates, since I have a utility I wrote that I use all the time that creates them as include (.inc) files, like so:
;********  Memory Dialog Template for "EdAsm editor" Project ********
;********  Created by DialogGen on 7/28/2023 at 9:15 pm  ********

$lineNumEdit EQU 1201

;====== Dialog header: ======
DD WS_BORDER or WS_CLIPCHILDREN or WS_CLIPSIBLINGS or WS_DLGFRAME or WS_POPUP or WS_SYSMENU or WS_VISIBLE or DS_SETFONT
DD WS_EX_CLIENTEDGE
DW 4 ;# items
DW 22 ;X
DW 5 ;Y
DW 105 ;Width
DW 46 ;Height
DW 0 ;Menu ID
DW 0 ;Class array
DB 'G',0, 'o',0, ' ',0, 'T',0, 'o',0, ' ',0, 'L',0, 'i',0, 'n',0, 'e',0
DW 0 ;Unicode terminator
DW 9 ;Font size
DB 'S',0, 'e',0, 'g',0, 'o',0, 'e',0, ' ',0, 'U',0, 'I',0
DW 0 ;Unicode terminator

;====== Dialog item (Static): ======
DD WS_CHILD or WS_VISIBLE
DD 0
DW 24 ;X
DW 10 ;Y
DW 22 ;Width
DW 8 ;Height
DW 100 ;Control ID
DW 0FFFFh ;Std. ctl. ID
DW 82h ;Std. ctl. type
DB 'L',0, 'i',0, 'n',0, 'e',0, ' ',0, '#',0, ':',0
DW 0 ;Unicode terminator
DW 0 ;Creation data

;====== Dialog item (Edit): ======
DD WS_BORDER or WS_CHILD or WS_TABSTOP or WS_VISIBLE
DD 0
DW 47 ;X
DW 9 ;Y
DW 28 ;Width
DW 10 ;Height
DW 1201 ;Control ID
DW 0FFFFh ;Std. ctl. ID
DW 81h ;Std. ctl. type
DW 0 ;Unicode terminator
DW 0 ;Creation data
DW 0 ;align to DWORD

;====== Dialog item (Button): ======
DD BS_CENTER or WS_CHILD or WS_TABSTOP or WS_VISIBLE
DD 0
DW 10 ;X
DW 28 ;Y
DW 34 ;Width
DW 12 ;Height
DW IDOK ;Control ID
DW 0FFFFh ;Std. ctl. ID
DW 80h ;Std. ctl. type
DB 'O',0, 'K',0
DW 0 ;Unicode terminator
DW 0 ;Creation data
DW 0 ;align to DWORD

;====== Dialog item (Button): ======
DD BS_CENTER or WS_CHILD or WS_TABSTOP or WS_VISIBLE
DD 0
DW 60 ;X
DW 28 ;Y
DW 34 ;Width
DW 12 ;Height
DW IDCANCEL ;Control ID
DW 0FFFFh ;Std. ctl. ID
DW 80h ;Std. ctl. type
DB 'C',0, 'a',0, 'n',0, 'c',0, 'e',0, 'l',0
DW 0 ;Unicode terminator
DW 0 ;Creation data
(And this is a really simple little dialog with only 4 controls in it.)

One thing I can tell you is that it will be a gigantic pain in the ass to try to create such a thing programmatically, main reason being what sinsi pointed out, that there are variable-length fields.

Plus all the text has to be Unicode (but you already know how to deal with that).
Plus the fields have to be DWORD aligned, so you have to provide for that.

I don't know any easy way to create such a template, except using my program, which is kind of peculiar to me. (I'd be happy to share it if anyone's interested, but it's somewhat incomplete and has ... bugs that I've learned to live with.)

Lemme scratch my head a bit and see if there's some easier way to deal with this.
Assembly language programming should be fun. That's why I do it.

sinsi

You might as well use a resource since it's just the structures
QuoteA dialog box is also one resource entry in the resource file. It consists of one DLGTEMPLATE dialog box header structure plus one DLGITEMTEMPLATE structure for each control in the dialog box. The DLGTEMPLATEEX and the DLGITEMTEMPLATEEX structures describe the format of extended dialog box resources.
Of cource, you could generate the .res file then insert it into your code using hutch's bin2db.
Same thing really  :biggrin:

zedd151

Quote from: NoCforMe on March 28, 2025, 04:23:11 PMthat there are variable-length fields.
Yes, I noticed

QuotePlus all the text has to be Unicode (but you already know how to deal with that).
easy peezy  :thumbsup:

QuotePlus the fields have to be DWORD aligned, so you have to provide for that.
Okay, that info will be helpful...

I always wondered why hutch's dialog box macros looked rather untidy.  :smiley:
¯\_(ツ)_/¯   :azn:

'As we don't do "requests", show us your code first.'  -  hutch—

NoCforMe

OK, looking at this a bit more, if a guy wanted to create a memory dialog template entirely programmatically, he'd probably want to do it this way:

1. Create the dialog header (sorry, can't think of the Micro$oft official term for this at the moment, but it's the first thing in the template). Could be done with a macro that wouldn't be too messy. Needs to include the following things:
  • The dialog styles (WS_xxxx values)
  • The dialog "extended" styles (WS_EX_xxxx values)
  • The # of items (controls) in the dialog
  • X, Y, width & height of the dialog (and remember, these are in dialog units, which aren't the same as normal screen units)
  • The text for the dialog title
  • The font size, assuming you're not using the default font
  • The font name

Then for each item (control), you'll need the following, in another macro:
  • The styles (WS_xxxx) for the control
  • X, Y, width & height (again, in dialog units)
  • The control's ID
  • The "standard control identifier" (0FFFFh) if it's a standard control type
  • The actual control type if it's a standard control
  • The control's text, if it has any

And of course the "control" macro would have to DWORD align the data.

Could be done, probably not too ugly.

In Suede-o-code:
DIALOG_HEADER WS_BORDER or WS_VISIBLE or DS_SETFONT, \
    WS_EX_CLIENTEDGE, \
    4, \
    <x, y, w, h>, \
    "Dialog Title Here", \
    9, \
    "Segoe UI"

DIALOG_ITEM WS_CHILD or WS_VISIBLE, \
    <x, y, w, h>, \
    <ctrl ID>, \
    <std. ctrl. type>, \
    "Control text"

Etc., etc.
Assembly language programming should be fun. That's why I do it.

NoCforMe

That "dialog units" thing is a real killer, which makes it really hard to line things up unless you have something like a resource editor to do it visually. My memory-template dialog creator almost gets it right: things line up, but the actual size of the dialog always needs a little tweaking (I have a preview feature that shows me what the dialog will actually look like).
Assembly language programming should be fun. That's why I do it.


zedd151

Quote from: NoCforMe on March 28, 2025, 05:23:12 PMThat "dialog units" thing is a real killer, which makes it really hard to line things up unless you have something like a resource editor to do it visually.
I wouldn't be using dilaog units at all.  :eusa_naughty:  Even using a dialog box editor, at certain intervals there seems to be some rounding. Take a column of controls for example. Either buttons or edit boxes. They are all specified to have the same size and spacing (in dialog units).
But every few controls would be off by a pixel in vertical alignment. Been there and done that.
Repositioning/resizing the controls in code would negate using a dialog box in the first place, since a considerable amount of code would be needed to perfectly align the controls.

The dialog box size would be determined by the desired client area in pixel dimensions, as in my last few posted examples.

Any controls can then be added the usual way using CreateWindowEx (as if we were working with a 'window') with byte alignment not dialog unit alignment, if I am not mistaken.
But, I will not be using any controls at first, only a menu. This is for a specific project that I am working on, to both minimize the code, and not use any resources.

I have some of that done already in that I have replaced the bitmaps with a coded alternative.
Just working on the dilaog box at this point.

If the in memory dialog box will tend to be code heavy, I will probably revert to using a resource dialog... since the in memory dilaog box code would probably use as much code as creating and using a registered window, if not more due to having to manually align any controls used and the extra steps needed in converting ascii to unicorn, etc.
In that case a resource dialog might be the best alternative, code wise... especially if no controls are needed.

I will, when time permits, create 3 versions of a test program with several controls.
One using RegisterWindow and CreateWindowEx i.e., a normal window.
Another using a resource dilaog box.
Another using an in memory dialog box.

For the dialog boxes, will add code to perfectly align the controls.

The version using less code (and very few macros), and smallest executable file size overall will be the victor.

:biggrin:

As I have more yard work to finish, this may have to wait...
I could probably put off the yard chores til tomorrow.  I frequent do.  :tongue:
¯\_(ツ)_/¯   :azn:

'As we don't do "requests", show us your code first.'  -  hutch—

jj2007