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

lingo

#75
I understand your memories of youth which are so far away from today's dynamics. :undecided:

https://www.youtube.com/watch?v=mrvuLFTRlVA
https://www.youtube.com/watch?v=med9jOQ3j-w
Quid sit futurum cras fuge quaerere.

NoCforMe

Nothing like a backhanded insult, eh? But no problemo, I don't take it personally.

BTW, that second video you posted was the first time I ever saw an actual Wang word processor. We just made the conversion stuff--8" diskette drive, PC adapter board and software.

If I were a betting man I'd wager that 32-bit Windows programming will survive well into the 2030s (assuming there's anything resembling a planet by then).
Assembly language programming should be fun. That's why I do it.

kkurkiewicz

Hello

I hope I don't bother you too much, but I have one more problem. When creating a new dialog box class, when should my window procedure call the function DefDlgProc? If it mustn't be called by a dialog box procedure, how can it be fine to use it to provide default processing for any messages that a custom dialog box does not process, which Microsoft suggests here (paragraph 4, sentence 2)? 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. When the function is not called, it looks like the program processes only the messages WM_GETMINMAXINFO, WM_NCCRERATE, WM_NCCALCSIZE, WM_CREATE, and then enters an infinite loop trying to process the message WM_SETFONT. When the function is invoked, however, the whole program simply crashes with the error "A new guard page for the stack cannot be created", which seems to prove that the function really is run recursively until it overflows the stack. However, if instead of calling DefDlgProc, I call DefWindowProc, everything works as expected. So, if the CLASS statement is said to convert a dialog to a window, how should I (semantically) interpret Microsoft's recommendations such as this one? That is, in the sentence "The application-defined window class allows the application to define a window procedure for the dialog box and process messages before sending them to the dialog box procedure", what is the dialog box procedure? And lastly, is it really necessary for the WndProc procedure to process the WM_DESTROY command?

WndProc PROC hWin:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
   
    mov eax, uMsg
    .IF eax == WM_INITDIALOG
        Invoke InitGUI, hWin
       
    .ELSEIF eax == WM_COMMAND...
       
    .ELSEIF eax == WM_CLOSE
        Invoke CDCloseFile
        Invoke DestroyWindow, hWin
       
    .ELSEIF eax == WM_DESTROY
        Invoke PostQuitMessage, NULL
       
    .ELSE
        Invoke DefWindowProc, hWin, uMsg, wParam, lParam
        ret
    .ENDIF
    xor eax, eax
    ret
WndProc ENDP
Kamil

TimoVJL

May the source be with you

kkurkiewicz

Kamil

jj2007

Quote from: kkurkiewicz on December 03, 2023, 12:32:51 AMis it really necessary for the WndProc procedure to process the WM_DESTROY command?

If you don't, you will never exit your message loop:
  .While 1
    invoke GetMessage, addr msg, 0, 0, 0
    inc eax
    shr eax, 1
    .Break .if Zero?    ; 0 (OK) or -1 (error)
    invoke TranslateMessage, addr msg
    invoke DispatchMessage, addr msg
  .Endw

Check the attachment, line 69.

Re other questions, I've always avoided dialogs. They work, but a regular window is hardly more complicated, and much more controllable.

kkurkiewicz

But shouldn't the PostQuitMessage function be invoked only as a response to receiving WM_CLOSE?
Kamil

jj2007

No. You can handle WM_CLOSE but you don't have to. If you don't handle WM_DESTROY, your program will be stuck, and only Task Manager or Ctrl C can end it.

NoCforMe

Quote from: jj2007 on December 03, 2023, 07:38:49 AMNo. You can handle WM_CLOSE but you don't have to. If you don't handle WM_DESTROY, your program will be stuck, and only Task Manager or Ctrl C can end it.
My 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:
    MOV    EAX, uMsg
    CMP    EAX, WM_CLOSE
    JE    do_close
 . . . . .
do_close:
    INVOKE    PostQuitMessage, NULL
    MOV    EAX, TRUE
    RET

which works in all cases.

(This is assuming I want to end the program here. If I just want to close the dialog, I call EndDialog() instead,)
Assembly language programming should be fun. That's why I do it.

NoCforMe

Quote from: TimoVJL on December 03, 2023, 12:41:49 AMWM_INITDIALOG should return TRUE

That only affects how the dialog manager sets the keyboard focus:
QuoteThe dialog box procedure should return TRUE to direct the system to set the keyboard focus to the control specified by wParam. Otherwise, it should return FALSE to prevent the system from setting the default keyboard focus.
Assembly language programming should be fun. That's why I do it.

TimoVJL

If dialog have message loop, DefWindowProc is useless ?
Those are not used same time ?
May the source be with you

NoCforMe

Very good question. Don't know the answer.

One thing: in my dialog-based programs (where the dialog is the main program window and there's no message loop), I simply return zero rather than call DefDlgProc() for any unhandled messages. This seems to work fine, although I'm quite willing to admit that this may not be the right thing to do under all circumstances ...
Assembly language programming should be fun. That's why I do it.

kkurkiewicz

TimoVJL—the point is that DefWindowProc should apparently never be used as the default message-processing method when the window is a dialog box with a private window class. From the second article I linked:

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

kkurkiewicz

Note, however, that what they refer to as "window procedure" is the callback function that you pass to CreateDialog. So, the question is: Should this function still process the messages WM_INITDIALOG and WM_CLOSE, or should it only process the messages WM_CREATE and WM_DESTROY?
Kamil

NoCforMe

Yes; that window procedure (the dialog is in fact a window, with a HWND and all that) is your dialog procedure, which is a standard Windows callback procedure:
TheDialogProc    PROC hWin:HWND, uMsg:DWORD, wParam:DWORD, lParam:DWORD
except that it is a special window proc, one which is controlled by the "dialog manager" rather than just running from a user's message loop. Which is why you're spozed to use DefDlgProc() instead of DefWindowProc(), and some other variations from the regular window procedure handling.

And 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).
Assembly language programming should be fun. That's why I do it.