Announcement

Collapse
No announcement yet.

WMSYSCOMMAND DIALOG SC_CLOSE anomaly?

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Michael Mattias
    replied
    new users who like me have skimped on the fundamentals in their haste to produce windows applications
    Ya think there might be some others? Really?

    I am shocked, shocked!

    MCM

    Leave a comment:


  • Chris Holbrook
    replied
    This thread which has gone way beyond answering my original question and will no doubt be an education to new users who like me have skimped on the fundamentals in their haste to produce windows applications (it's really shocking that PB allows one to do this!).

    I've gleaned several useful facts and again am impressed and humbled by the effort that "those who know" have put in to explain their reasoning.

    Also noting that the "meat" of this thread is a little at odds with its title, I've put a suggestion onto the cafe forum here
    Last edited by Chris Holbrook; 10 Jan 2008, 04:54 PM. Reason: added link

    Leave a comment:


  • David Roberts
    replied
    Perhaps we were sidetracked but I found Chris' post #9 an eye opener. The SDK says of GetMessage "The function dispatches incoming sent messages until a posted message is available for retrieval."

    This explains why without the EXIT LOOP that I added, SC_CLOSE is 'picked up' twice. It is clear now that Close or Alt F4 notifications are posted by Windows whereas Close via 'X' is sent, not that it matters in anything that I write.

    Added: We can see what is going on another way by commenting out "If App_ExitFlag& Then Exit Loop ' terminate app" and adding "Function = %TRUE" in the CallBack (with the EXIT LOOP inserted as mentioned). Closing via 'X' now gets throttled.
    Last edited by David Roberts; 10 Jan 2008, 02:11 PM.

    Leave a comment:


  • Chris Boss
    replied
    If you look at the original code posted by Chris in starting this thread, the core problem he was having was trying to process the WM_SYSCOMMAND message in the message loop.

    IMO, this was based on a "common" misconception that all messages go through the message loop.

    This is incorrect.

    I tried to post working code examples, as well as detailed explanations about how messages are handled (which required understanding such things as sending/posting messages, the message queue and the message loop) so one can appreciate why trying to process certain messages in the message loop will not work.

    If one understands how messages are handle by Windows, then one will know when you can trap messages in the message loop (I do it in my software) and when they shouldn't be.

    Often problems in writing Windows applications correctly originates with misunderstandings of how Windows actually works. The more basic information one has about the core workings of Windows, the better ones code will be.

    The background I posted was quite warranted for the original question asked.

    Leave a comment:


  • Michael Mattias
    replied
    Not that getting sidetracked is such a bad thing - I often learn from these excursions and I'm certain others do as well - but in this case we seem to have really gone off the beaten path.


    The original question was.....
    Looking at ways to close the application.
    ... and the "what I've tried" was various combinations of PostQuitMessage and sending WM_SYSCOMMAND/SC_CLOSE.

    Then this discussion got into sending versus posting messages, modifying message loops and even multi-threaded applications.

    I'm just hoping the correct solutions - which are here - have not been lost in the traffic...since this is an important topic especially for the "lurking newbies."

    - PostQuitMessage() is a mechanism for ending an SDK-style message loop and is often used to end a program... or at least the program's primary thread of execution.

    - The WM_SYSCOMMAND/SC_CLOSE notification is generated by Windows in response to a specific user action and should not be sent or posted by the application program via code. Using either SDK-style or DDT-Style coding, the default action in response to WM_SYSCOMMAND/SC_CLOSE is to destroy the window.

    - A program should always destroy its screen (with EndDialog, DestroyWindow or DIALOG END) before exiting its message loop.

    - When a window is destroyed, a WM_DESTROY notification is sent to the window procedure, allowing the program to use PostQuitMessage at that time, if that is how the programmer wants to end his message loop.

    MCM

    Leave a comment:


  • Chris Boss
    replied
    My comments about SendMessage were assuming the standard single thread (main GUI thread) model of most applications, so for all practical purposes, my description is correct.

    Multi-Threading is a totally different situation requiring a full explanation of how threads work before one will appreciate the handling of functions like SendMessage to another thread.

    Leave a comment:


  • Fred Harris
    replied
    My basic pre-supposition is that ALL users are nasty, illogical, demented, mean, preoccupied, even downright evil. And I have given up on them. No longer do I impose my ethical preconceptions on them as elucidated by Peter...

    ....I find it bad practice to start with if a user clicks [X] to end the program...
    Being as my nature is basically a pessimist, and it is so easy to trap WM_CLOSE messages in SDK style, whatever processing needs to occur when the user [X]'s the window, I put that in something like this...

    Code:
    Function fnWndProc_OnClose(parameters...)
    ...
    ...
    ...
    
      FnWndProc_OnClose=0
    End Function
    ...and everybody lives happily everafter.

    Leave a comment:


  • Dominic Mitchell
    replied
    SendMessage sends a message directly to the window procedure of a window. It does not return until the message has been processed.
    The use of the word directly makes your statement a bit inaccurate.

    That is true only if the window was created by the calling thread.
    If it was, the window procedure for the window is called directly.
    If it was not, the message is queued in what is known as the Send-Message queue.
    The OS waits until the receiving thread is idle before calling the window procedure
    of the target window.

    Leave a comment:


  • Dominic Mitchell
    replied
    I've resolved to work out where to put my event code by writing a C app (having downloaded a suitable
    IDE and compiler) to do it, then reverse it into PB.
    You will just end up with a system similar to that used by Phoenix or FireFly.
    Dumping all notifications from a control to its parent to a single procedure is not difficult.
    For example, if this procedure is prototyped as

    Code:
    FUNCTION <ControlName>_Handler _
      ( _
      BYVAL hWnd    AS DWORD, _ ' window handle
      BYVAL uMsg    AS DWORD, _ ' type of message
      BYVAL wParam  AS DWORD, _ ' first message parameter
      BYVAL lParam  AS LONG _   ' second message parameter
      ) AS LONG
    just forward messages such as WM_COMMAND, WM_NOTIFY, WM_MEASUREITEM, WM_DRAWITEM, WM_CTLCOLORXXX,
    WM_CHARTOITEM, WM_VKEYTOITEM and WM_PARENTNOTIFY to the handler.
    If you want to include other messages such as WM_KEYDOWN, WM_MOUSEMOVE and WM_NCCALCSIZE, subclass
    or superclass the control and forward these messages to the handler.

    For parent notifications(WM_COMMAND etc.), I would probably set the value of the hWnd parameter to
    the handle of the control to keep things consistent.

    Leave a comment:


  • Chris Boss
    replied
    Posting and Sending messages:

    This relates to the two API functions:

    PostMessage
    SendMessage

    They are similiar but work differently.

    SendMessage sends a message directly to the window procedure of a window. It does not return until the message has been processed.

    PostMessage sends a message (posts) to the message queue of the application and immediately returns. The message is not processed immediately, but waits in the message queue. The message queue is read by calling the GetMessage API function in a message loop. The messages normally are processed in FIFI (First In, First out) order. When the message loop gets a message from the message queue, it then calls an API which handles the message (ie. IsDialogMessage, TranslateMessage) and those API functions will send the message to the window procedure of the window.

    There is a reason why some messages are better posted, while others sent directly. I won't go into all the details of importance of each method, but suffice it to say, that both methods are very important.

    Leave a comment:


  • Dominic Mitchell
    replied
    MSDN:
    PostQuitMessage Function
    The PostQuitMessage function indicates to the system that a thread has made a request to terminate (quit).
    It is typically used in response to a WM_DESTROY message.
    It is an accurate but terse description of what actually happens.
    PostQuitMessage does not post any message to the message queue.

    Leave a comment:


  • Chris Holbrook
    replied
    Michael, I may have chosen my words poorly, but if it's given you a chance to advertise, don't knock it!

    This SDK/DDT is a headache. There are so many examples of mixed SDK/DDT that it is tempting to assume that they fit together OK. Maybe the do in some hands. Add in a limited knowledge of the underlying platform and you have a heady mix.

    I've resolved to work out where to put my event code by writing a C app (having downloaded a suitable IDE and compiler) to do it, then reverse it into PB.

    Leave a comment:


  • Peter Lameijn
    replied
    Why not just disable the [X] close button? I mostly do so, because I find it bad practice to start with if a user clicks [X] to end the program...

    Leave a comment:


  • David Roberts
    replied
    > so I write a letter to the person I want to do the job

    and if you do not specify a person, with a given window handle, then the mail gets delivered to the mail box at the end of the street - the street being the application and the houses being windows.

    Leave a comment:


  • Ian Cairns
    replied
    It seems to me that 'posting' is analogous to delivering to a mail box - the mail box is the message queue. We pop down the mail box to collect the mail. We are the message loop. The mail is not delivered to us directly.
    I understand it this way. I want something to be done, so I write a letter to the person I want to do the job. I assume he will do it as soon as he gets the letter. And I carry on with my life without worrying about it. That is "Posting"
    On the other hand 'sending' is analogous to the mail person knocking on our door and they will not leave until we take the mail from them. In this case the mail did not get put into the mail box.
    Now, if I not only want the job to be done, but I want a reply, I "Send" the message by a courier, and I sit and wait until the courier has seen the person, delivered the mail and waits for the person to write the reply, which the courier brings back to me. The courier won't leave without a reply. If the person doesn't write a reply, the courier never comes back. I sit there doing nothing (but breathing) until he returns.

    regards, Ian.

    Leave a comment:


  • David Roberts
    replied
    > For example, clicking the X button, WM_COMMAND goes straight to the dialog procedure, skipping the message loop.

    OK

    > Clicking the captionbar icon to display the system menu and clicking "close" will generate the WM_SYSCOMMAND message which is sent to the message queue and go through the message loop.

    OK again but also the dialog procedure unless we add Exit Loop

    Code:
    If msg.message = %WM_SYSCOMMAND Then
      If (msg.wParam And &HFFF0) = %SC_CLOSE Then
        ' this event never occurs, because the message never goes through message queue
        MsgBox "Dialog Closed via X button!"+Chr$(13)+Chr$(10)+"Trapped in Message Loop."
        App_ExitFlag&=2
      End If
      [COLOR="Red"]Exit Loop[/COLOR]
    End If

    Leave a comment:


  • David Roberts
    replied
    Yes, Chris' explanation is much better but I find terms like 'sending to' or 'posting to' a message loop confusing.

    It seems to me that 'posting' is analogous to delivering to a mail box - the mail box is the message queue. We pop down the mail box to collect the mail. We are the message loop. The mail is not delivered to us directly.

    On the other hand 'sending' is analogous to the mail person knocking on our door and they will not leave until we take the mail from them. In this case the mail did not get put into the mail box.

    Leave a comment:


  • Michael Mattias
    replied
    Chris' explanation is MUCH better than MSDN's.

    Especially...
    not all messages are passed through the message loop.
    .. which suggests trying to process specific messages in the message loop rather than in the window procedure is a fool's errand.

    Leave a comment:


  • David Roberts
    replied
    > Generally when someone compares me to an equine body part it's not its mouth.

    What is it then, generally?

    Enquiring minds need to know.

    I think Chris was referring to MSDN.

    Leave a comment:


  • Michael Mattias
    replied
    I need to thank you for your kind words.

    Generally when someone compares me to an equine body part it's not its mouth.

    Leave a comment:

Working...
X