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?
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;
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...
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...
Quote from: sinsi on March 28, 2025, 03:26:53 PMQuote 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:
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.
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.
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.
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:
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:
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.
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).
https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getdialogbaseunits (https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getdialogbaseunits)
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:
;-)
Quote from: jj2007 on March 29, 2025, 12:58:35 AM;-)
Ha ha. How much code do your macros expand to? :toothy:
Anyway what I have learned here, is that the DLGTEMPLATEEX structure is not a structure to be used per se, but only to be used as a guide when creating in memory dialogs. Meaning it is not an actual usable structure as-is.
Seems that 'in memory' dialog boxes are not the way to go, in some instances. Especially if numerous controls will be added to it.
I used to use a registered window for most of my projects (going back several years), but have been looking to use dialog boxes more often lately.
Seems that using a resource based dialog box might be the best option. If numerous controls are needed however, maybe a registered window is the best way to go. Especially true if many controls are needed, and the controls need to be perfectly byte (pixel) aligned.
:smiley:
I have scratched the idea of writing the three versions of a test program as mentioned above. I would rather concentrate on finishing the project already started. It is almost ready. And I am no longer considering using in memory dialog boxes at this point. And certainly not going to mess with DLGTEMPLATEEX any further.
DLGTEMPLATE(EX) have been always a dynamic struct, just a hint, how Windows OS read it.
Many languages have their own way to use it.
Those who bother to read an old books for Windows programming knows that.
Quote from: zedd151 on March 29, 2025, 01:01:43 AMHow much code do your macros expand to?
It's a bit over 500 lines around DialogBoxIndirectParamW (https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-dialogboxindirectparamw): :cool:
QuoteCreates a modal dialog box from a dialog box template in memory.
It was hard work, and it works fine, but I rarely use the dialogs. I prefer event-driven programming (https://masm32.com/board/index.php?topic=5976.0) with "real" windows :cool:
Quote from: jj2007 on March 29, 2025, 02:50:45 AMI prefer event-driven programming (https://masm32.com/board/index.php?topic=5976.0) with "real" windows :cool:
I usually do use real windows too. But I have been working with dialog boxes recently, and am converting some old code, switching from using windows to dialog boxes, and eliminating butmaps. I wanted to eliminate the .rc file altogether, but in memory dialogs seem more trouble than they are worth. (without using macros to do it)
Anyway here are two versions of 4x4, that I am currently working on.
They both use a resource dialog box in place of a 'real' window.
One uses bitmaps, the other no bitmaps. The bitmaps look like crap. Originally they were 32x32 and looked okay, but I had doubled their size to display larger. :rolleyes:
Changing from a window to dialog box only yielded a slight reduction in code size.
Removing the bitmaps was of course a much greater reduction in size.
I still have to clean up the code, use loops where possible to further reduce the code, other minor details, etc., and a couple of other changes still need to be made before I post the source code.
Once finished, I will post the source in the Game Development board.
Quote from: zedd151 on March 29, 2025, 12:18:55 AMAny controls can then be added the usual way using CreateWindowEx (as if we were working with a 'window')
A dialog
is a window.
But yeah, once you have a dialog you can add whatever you want to it using
CreateWindowEx(). But if you know what controls you want to add at the get-go, probably easier to put them into the memory template and let the dialog manager populate the dialog. That way you need zero code to add them, just some data.
Quote from: NoCforMe on March 29, 2025, 05:44:27 AMA dialog is a window.
Of course.
I have decided not to use 'in memory' dialog boxes after all.
I opted for keeping the simple resource dialog box. :smiley: at least for now.
Hello,
I propose a very pracical method to use binary resource templates : extract the binary data from compiled resource scripts ( .res files ) with a tool. Employing this technique, you don't even need to know about the layout of the structure DLGTEMPLATEEX.
I modified the resource script below to remove the line referring to the menu defined with MENU IDR_MENU
#include "\masm32\include\resource.h"
#define IDR_MENU 10000
#define IDM_ABOUT 10
#define IDM_MNMIZE 20
#define IDM_EXIT 30
MYDIALOG DIALOGEX DISCARDABLE 20, 10, 186, 100, 18481280
STYLE DS_3DLOOK|DS_CENTER|WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX|WS_VISIBLE
CAPTION "Dialog box"
FONT 12, "System", 700, 0, 1
{
CONTROL "&About", 110, "Button", WS_TABSTOP, 116, 8, 50, 20, 0, 1234049503
CONTROL "&Minimize",120, "Button", WS_TABSTOP, 116, 36, 50, 20, 0, 1234049503
CONTROL "&Exit",130, "Button", WS_TABSTOP, 116, 64, 50, 20
CONTROL " Masm Dialog Box", 4000, "Edit", ES_AUTOHSCROLL|WS_BORDER|WS_TABSTOP, 16, 8, 72, 20
}
IDR_MENU MENU
{
POPUP "&File"
{
MENUITEM "&About", IDM_ABOUT
MENUITEM "&Minimize", IDM_MNMIZE
MENUITEM "&Exit", IDM_EXIT
}
}
Running Resource Hacker, load the .res file and save the two components ( the dialog box and the menu ) to .bin files. Convert the bin files to text files with Hutch's Bin2db tool.
You can obtain Resource Hacker from this address :
https://www.angusj.com/resourcehacker/ (https://www.angusj.com/resourcehacker/)
Here is how the code should look :
.data
include Dialog.inc
include Menu.inc
invoke GetModuleHandle,0
xor ecx,ecx
invoke DialogBoxIndirectParam,eax,ADDR Dialog,\
ecx,ADDR DlgProc,ecx
invoke ExitProcess,eax
DlgProc PROC USES ebx hWnd:HWND,uMsg:UINT,wParam:WPARAM,lParam:LPARAM
.IF uMsg==WM_INITDIALOG
invoke LoadMenuIndirect,ADDR Menu
invoke SetMenu,hWnd,eax
Quote from: zedd151 on March 29, 2025, 03:17:22 AMI wanted to eliminate the .rc file altogether, but in memory dialogs seem more trouble than they are worth. (without using macros to do it)
Thinking about this some more, you could create memory dialog templates without using macros, using a function or two.
I'm not suggesting this in my usual anti-macro mode: clearly this is a case where you either need to use a macro (or two), or else some code to construct the memory template. And I honestly don't know which one would be easier.
Actually, once you write either the macro or the template-constructing code, it'd probably be equally easy. (But I think the macro would be more complex to write. JJ's 500 lines sounds about right.)
Anyhow, a function would need to take all the info necessary to create the memory template and lay it out in memory. Rather than a function with a zillion parameters, probably best to put the info in a structure, then pass that structure to the function.
I could probably cobble something like this together, if there's any interest.