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

kkurkiewicz

So how to explain that the only way to get it to work is to call DefWindowProc? (Please note that the WndProc procedure I included in my question comes from fearless' CD utility, which is also "just" a dialog with a custom window class.)
Kamil

NoCforMe

Quote from: kkurkiewicz on December 03, 2023, 12:32:51 AM[...] I'd like to rewrite PROG2.ASM to define a custom icon, but, after registering a custom dialog box class and rewriting my dialog procedure to make it look more like the WndProc function shown below, I cannot get anything to work because – depending on whether I call DefDlgProc – my main window is now either not displayed at all, or the program doesn't even start. [...]

Question for you: why are you registering a custom dialog box class? I think that may be the source of your problems.

Unless you have some legitimate need to do this, I would try just creating a standard dialog and seeing if that works.

I don't know if it's related or not, but I do know from experience working with dialogs that if I have a child window (control) in the dialog that's user-defined (i.e., not one of the standard Windows classes), the dialog won't work if I don't register the class for that control before invoking the dialog. I wonder if this is the same problem you might be having.
Assembly language programming should be fun. That's why I do it.

jj2007

Quote from: NoCforMe on December 03, 2023, 08:53:58 AMMy programs (dialog-based) never handle WM_DESTROY and yet they never get "stuck". They work just fine.

Unless I'm missing something here.

My typical message handling for closing time is this:
Code Select Expand
    MOV    EAX, uMsg
    CMP    EAX, WM_CLOSE
    JE    do_close
 . . . . .
do_close:
    INVOKE    PostQuitMessage, NULL
    MOV    EAX, TRUE
    RET

which works in all cases.

You can send the PostQuitMessage also in the WM_CREATE handler, and it will work fine :thumbsup:

Quote from: NoCforMe on December 03, 2023, 10:06:15 AMAnd of course it should process all those dialog-related messages, like WM_INITDIALOG. As well as any other message you need handled, like any messages from child windows (controls) (and certainly WM_CLOSE).

Handling WM_CLOSE is optional, handling WM_DESTROY isn't.

NoCforMe

Quote from: jj2007 on December 03, 2023, 11:18:58 AMHandling WM_CLOSE is optional, handling WM_DESTROY isn't.
Hate to argue the point w/you, but how is it that none of my dialog-based programs even mention WM_DESTROY and yet they work fine?

So far as I know, if you don't handle it and if you pass it back to the dialog manager, they'll take care of it for you with its default processing.

Experiment: try commenting out your WM_DESTROY handler in one of your programs and see if it still works (assuming that your handler for that message doesn't do something crucial to your program).
Assembly language programming should be fun. That's why I do it.

jj2007

Quote from: NoCforMe on December 03, 2023, 12:31:17 PMnone of my dialog-based programs even mention WM_DESTROY and yet they work fine

These are the subtle differences between dialogs and real windows.

P.S., Raymond Chen: Sending a window a WM_DESTROY message is like prank calling somebody pretending to be the police

NoCforMe

But none of my non-dialog windowed programs mention WM_DESTROY either, and they too work fine ...

As usual, excellent explanation by R. Chen in that article you linked to. What he writes at the end convinces me that you do not need to handle WM_DESTROY explicitly:

QuoteYou can invent a private message for this, or you can take advantage of the fact that the default behavior of the WM_CLOSE message is to destroy the window. Since our window procedure doesn't override WM_CLOSE, the message will fall through to DefWindowProc which will convert the WM_CLOSE into a DestroyWindow.

This tells me that you can just let WM_CLOSE take care of WM_DESTROY by dropping through to DefXXXProc().
Assembly language programming should be fun. That's why I do it.

jj2007

#96
Quote from: NoCforMe on December 03, 2023, 12:39:43 PMBut none of my non-dialog windowed programs mention WM_DESTROY either, and they too work fine ...

Sure :thumbsup:

Quote from: jj2007 on December 03, 2023, 11:18:58 AMYou can send the PostQuitMessage also in the WM_CREATE handler, and it will work fine :thumbsup:

Btw you can also use invoke ExitProcess, 0 in your WM_CLOSE handler, and it will work fine :thumbsup:

P.S. this is what happens after the WM_CLOSE message:
        #    wParam   lParam      uMsg
msg     476  A080F060 0001038B  WM_MENUSELECT
msg     490  0001038B 20000000  WM_UNINITMENUPOPUP
msg     491  00000000 00000000  WM_CAPTURECHANGED
msg     492  FFFF0000 00000000  WM_MENUSELECT
msg     493  00000000 00000000  WM_EXITMENULOOP
msg     494  0000F060 013B029E  WM_SYSCOMMAND
msg     495  00000000 00000000  WM_CLOSE   <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
msg     496  00000000 00000000  WM_UAHDESTROYWINDOW
msg     497  00000000 0019F8C4  WM_WINDOWPOSCHANGING
msg     498  00000000 0019F8C4  WM_WINDOWPOSCHANGED
msg     499  00000000 00000000  WM_NCACTIVATE
msg     500  00000000 0019F1D4  WM_UAHINITMENU
msg     501  00000000 0019F4EC  WM_UAHINITMENU
msg     502  00000000 0019F4EC  WM_UAHDRAWMENU
msg     503  00000000 0019F484  WM_UAHDRAWMENUITEM
msg     504  00000000 00000000  WM_ACTIVATE
msg     505  00000000 00001DAC  WM_ACTIVATEAPP
msg     506  02000067 0070026C  WM_COMMAND: 00000200h   ID 103
msg     507  00000000 00000000  WM_DESTROY
msg     508  00000000 00000000  WM_NCDESTROY

Lots of totally useless stuff ;-)

kkurkiewicz

Quote from: NoCforMe on December 03, 2023, 11:08:39 AM[W]hy are you registering a custom dialog box class?

I know that in order to define a custom icon, I could simply load the icon from my exe file and set it by then sending WM_SETICON to the dialog, but I'd still like to understand what the purpose of DefDlgProc is. At the time when I was typing my new question, I was still convinced that it is necessary for my callback function to invoke DefDlgProc, and I only realized that fearless' WndProc uses DefWindowProc when I included it in my question, but is solved my problem right away.
Kamil

NoCforMe

#98
So you're using DefWindowProc() in your dialog procedure, is that correct? You're not supposed to do that; you should use DefDlgProc() instead (the different flavor is on account of the dialog manager). But did you try that and it didn't work? That probably points to some other problem with your code. At least that's my guess ...

I don't use either of those in my dialog procedures; I just return zero for any unhandled messages. Seems to work fine. Have you tried that?

Sorry: what I just told you about using DefDlgProc() was wrong. From Microsoft Learn:
QuoteThe DefDlgProc function must not be called by a dialog box procedure; doing so results in recursive execution.

(I just discovered this the hard way: stack overflow.)

Fearless was 100% right. I just put DefWindowProc() in another program where I was having severe problems with a listbox in a dialog, and it solved them.
Assembly language programming should be fun. That's why I do it.

kkurkiewicz

So, 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.
Kamil

HSE

Hi Kamil

Can you post some test project? to know where you are.

HSE
Equations in Assembly: SmplMath

kkurkiewicz

prog--without class
prog (2)--with class
Kamil

NoCforMe

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.

I do not understand this at all, as it's completely contradictory with the statement I posted which tells us not to ever use DefDlgProc() in a dialog procedure.

So don't use it. I don't think you need it. I'm still unclear as to why you're creating a custom dialog class here.

DefWindowProc() works well in a dialog procedure. Use it.

Which one of the programs you posted works?
Assembly language programming should be fun. That's why I do it.

jj2007

Quote from: NoCforMe on December 05, 2023, 08:31:22 AMWhich one of the programs you posted works?

They both work.

Wow :cool:
DLGPROC PROC
    PUSH  EBP
    MOV  EBP, ESP
    PUSH  EBX
    PUSH  ESI
    PUSH  EDI
;-----------------------------------
    CMP  DWORD PTR [EBP+0CH], WM_CLOSE
    JE    WMCLOSE
    CMP  DWORD PTR [EBP+0CH], WM_INITDIALOG
    JE    WMINITDIALOG

HSE

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.

You must try with DialogBox variations (don't needed any additional message loop).
Equations in Assembly: SmplMath