News:

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

Main Menu

Dialog box programming considerations

Started by kkurkiewicz, October 23, 2023, 02:18:34 AM

Previous topic - Next topic

NoCforMe

Quote from: HSE on December 05, 2023, 09:22:02 AM
Quote from: kkurkiewicz on December 05, 2023, 07:42:26 AMprog--without class
prog (2)--with class

So far I understand you cant' use CreateDialog variations without a parent window.
Well, he's using CreateDialogParam() with no parent window, and JJ says the programs work, so ...
QuoteYou must try with DialogBox variations (don't needed any additional message loop).
That's what I use (DialogBoxIndirectParam() ).

Is it true that the CreateDialogXXX() functions require a message loop and the DialogBoxXXX() ones don't?

Damn Micro$oft for so poorly naming the dialog functions. The CreateXXX ones are non-modal while the DialogXXX ones are modal. Why couldn't they have used the term "modal" and "nonModal" to distinguish the two?

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

HSE

Quote from: NoCforMe on December 05, 2023, 09:32:59 AMWell, he's using CreateDialogParam() with no parent window, and JJ says the programs work, so ...

Yes, my mistake, is working  :eusa_boohoo:
Equations in Assembly: SmplMath

NoCforMe

OK. The confusion level here is decreasing! Nice.
Assembly language programming should be fun. That's why I do it.

HSE

Apparently DefDlgProc is very specific for DialogBox variations, not for CreateDialog variations.

Or is used when Dialog have a parent window ¿?
Equations in Assembly: SmplMath

jj2007

Quote from: NoCforMe on December 05, 2023, 10:25:38 AMThe confusion level here is decreasing!

Just read the remarks section of DefDlgProc, and your confusion level will rise to record highs :cool:

NoCforMe

Yes, indeed, Jochen. Guiness-book-of-world record highs.

Does anyone here know when (and where) one should use DefDlgProc()? For sure?

All that they (Microsoft Learn) write implies that it's to be used (only?) with custom dialog classes. But it should be emphasized again that they write
QuoteThe DefDlgProc function must not be called by a dialog box procedure; doing so results in recursive execution.

So if you can't use it an a dialog procedure (including, I'm assuming, a custom dialog proc), then where the hell would you use it?

Raymond Chen addresses this issue here, here, here, and here. I haven't had time to go through all these and digest them, but I'm sure the answer to our confusion is in there somewhere ...

Check out that first linked article. I'm pretty sure the answers to our questions are all in there. (A 20-year old post!)
Assembly language programming should be fun. That's why I do it.

jj2007

Quote from: NoCforMe on December 05, 2023, 11:33:12 AMDoes anyone here know when (and where) one should use DefDlgProc()

Actually, I don't know. What I do know is that under the hood of my dialog macros there is not a trace of DefDlgProc, DefWndProc or CallWindowProc. They just return (and have done so successfully for many years).
invoke DialogBoxIndirectParamW, rv(GetModuleHandle, 0), [esi], DlgOwner, MbDlgP, esi
...
MbDlgP proc hDlg, uMsg, wParam, lParam
  ...
    xor eax, eax
    xchg eax, [esi.MbDLG.dlgRetEax]
    pop ebx    ; uses esi edi ebx
    pop edi
    pop esi
    leave
    retn 4*4  ; no DefWindowProc, DefDlgPoc or CallWindowProc...
MbDlgP endp

See DialogBoxIndirectParam and DlgProc:
QuoteTypically, the dialog box procedure should return TRUE if it processed the message, and FALSE if it did not. If the dialog box procedure returns FALSE, the dialog manager performs the default dialog operation in response to the message.

If the dialog box procedure processes a message that requires a specific return value, the dialog box procedure should set the desired return value by calling SetWindowLong(hwndDlg, DWL_MSGRESULT, lResult) immediately before returning TRUE. Note that you must call SetWindowLong immediately before returning TRUE; doing so earlier may result in the DWL_MSGRESULT value being overwritten by a nested dialog box message.

NoCforMe

JJ, I can't tell from that fragment whether that code is for a handled message or an unhandled one.

I think we established (maybe in my other thread about listbox problems) that one should use DefWindowProc() for unhandled messages, correct? After all, that's exactly what cured the problem I was having with that listbox not working correctly.
Assembly language programming should be fun. That's why I do it.

jj2007

Quote from: NoCforMe on December 05, 2023, 02:33:58 PMI think we established (maybe in my other thread about listbox problems) that one should use DefWindowProc() for unhandled messages, correct?

I don't know what "we" established, but Microsoft says (see above) you should return zero if you don't handle the message.

Quote from: NoCforMe on December 05, 2023, 02:33:58 PMI can't tell from that fragment whether that code is for a handled message or an unhandled one

See dlgRetEax

NoCforMe

Not being a MasmBasic user, I have no idea what [esi.MbDLG.dlgRetEax] means.
Assembly language programming should be fun. That's why I do it.

jj2007

Quote from: NoCforMe on December 05, 2023, 06:11:37 PMNot being a MasmBasic user, I have no idea what [esi.MbDLG.dlgRetEax] means.

While I am an avid MasmBasic user, I also had no idea what [esi.MbDLG.dlgRetEax] means (I wrote this code over 10 years ago). My best guess would be that dlgRetEax has something to do with Microsoft's idea on how to handle dialog messages :cool:

Quote from: jj2007 on December 05, 2023, 02:12:27 PMSee DialogBoxIndirectParam and DlgProc:
QuoteTypically, the dialog box procedure should return TRUE if it processed the message, and FALSE if it did not. If the dialog box procedure returns FALSE, the dialog manager performs the default dialog operation in response to the message.

_japheth

Quote from: kkurkiewicz on December 05, 2023, 05:50:47 AMSo, now, how on earth should we adjust our programs to make them conform with this? From paragraph 4:

QuoteThe window procedure for the custom dialog box has the same parameters and requirements as any other window procedure. Unlike other window procedures, however, the window procedure for this dialog box should call the DefDlgProc function instead of the DefWindowProc function for any messages it does not process. DefDlgProc carries out the same default message processing as the window procedure for the predefined dialog box, which includes calling the dialog box procedure.


There's quite a bit confusion here. Actually, it's quite simple - that's why I remember this stuff although I didn't do any serious Windows programming in the last 10 years.

If you're defining a custom dialog box window class, you'll have to provide a window proc for it. This proc is NOT to be confused with a "dialog proc" - you still have to provide such a dialog proc as a parameter for the DialogBoxXXX() or CreateDialogXXX() functions. Instead, the address of your window proc ( of your custom dialog box window class ) is delivered in the WNDCLASS.lpfnWndProc struct member, and the struct itself is - of course - the parameter for a RegisterClass() function call.

In the simplest case, your custom dialog box window proc does nothing but calling DefDlgProc():

MyPreciousCustomDialogWndProc PROC hWnd:dword, uMsg:dword, wParam:dword, lParam:dword
    invoke DefDlgProc, hWnd, uMsg, wParam, lParam
    ret
MyPreciousCustomDialogWndProc ENDP

Of course you can handle some messages in this proc - but, for example, you cannot handle WM_INITDIALOG here, because that message is created inside DefDlgProc() and then routed to YOUR dialog proc.
Dummheit, gepaart mit Dreistigkeit - eine furchtbare Macht.

HSE

 :thumbsup:

It's working with DefWindowProc (and all messages process) in the CLASS proc, and DefDlgProc (alone) in the DLG proc.
Equations in Assembly: SmplMath

jj2007

I know this isn't easy to understand. Microsoft says "DLGPROC callback function: Application-defined callback function used with the CreateDialog and DialogBox families of functions".

"Family" includes the CALL CreateDialogParamA@20 used by the OP.

DLGPROC Dlgproc;
INT_PTR Dlgproc(
  HWND unnamedParam1,
  UINT unnamedParam2,
  WPARAM unnamedParam3,
  LPARAM unnamedParam4
)

Looks like an ordinary WndProc, right? But it isn't. You get the params but you are not supposed to pass them on to DefDlgProc, DefWindowProc or CallWindowProc.

If you want to react to a message, there are two ways to do so:

1. tell Windows that you did your own processing:
QuoteTypically, the dialog box procedure should return TRUE if it processed the message, and FALSE if it did not. If the dialog box procedure returns FALSE, the dialog manager performs the default dialog operation in response to the message.

2. tell Windows that you did your own processing and want to return a value:
QuoteIf the dialog box procedure processes a message that requires a specific return value, the dialog box procedure should set the desired return value by calling SetWindowLong(hwndDlg, DWL_MSGRESULT, lResult) immediately before returning TRUE.

See Remarks:
QuoteAlthough the dialog box procedure is similar to a window procedure, it must not call the DefWindowProc function to process unwanted messages. Unwanted messages are processed internally by the dialog box window procedure.

Meaning that dialogs do have their own WndProc, but you won't see them, and you shouldn't use them. On entry to that invisible WndProc, Windows calls your DLGPROC, and if it returns FALSE (eax==0), it jumps straight to its own, private invoke DefWindowProc. You are not supposed to intervene.

kkurkiewicz

It just struck me—DefDlgProc must be the system predefined procedure for the standard dialog box class, as alluded to in the last paragraph of When to Use a Dialog Box and clearly [sic] stated here. _japheth—I think you are right :thumbsup:
Kamil