The MASM Forum

General => The Laboratory => Topic started by: jj2007 on August 26, 2014, 09:26:01 AM

Title: Re: problems with a window
Post by: jj2007 on August 26, 2014, 09:26:01 AM
Some people believe Windows should complete its job for the most common messages: (http://masm32.com/board/index.php?topic=2469.msg25901#msg25901)

WndProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
 
   .IF uMsg==WM_DESTROY
      invoke PostQuitMessage,NULL
   .ENDIF
   invoke DefWindowProc,hWnd,uMsg,wParam,lParam     
   ret

WndProc endp
Title: Re: Re: problems with a window
Post by: Tedd on August 27, 2014, 12:58:16 AM
DefWindowProc does handle WM_DESTROY, as far it is concerned -- it returns zero to indicate the message was processed. However, what it doesn't do (for whatever strange reason) is post WM_QUIT to your message queue.
And so, the result is that your process doesn't exit because it's still running around in the message loop, not ending because GetMessage didn't receive zero (which it does for WM_QUIT.)
Presumably, you could indicate the exit yourself with a 'stillRunning' flag, and have your message loop end in response to that; but the standard way is to post WM_QUIT yourself (that's all PostQuitMessage does -- you could manually PostMessage(hwnd,WM_QUIT,0,0) instead.)
Title: Re: Re: problems with a window
Post by: dedndave on August 27, 2014, 03:15:36 AM
if the WM_DESTROY message is received in a child window, you may not want to terminate

i think Jochen grabbed WM_DESTROY as an example - perhaps a poor choice
but, he's talking about the way the return value is handled
he and i don't agree on that one - not the first time   :lol:
Title: Re: Re: problems with a window
Post by: jj2007 on August 27, 2014, 04:28:42 AM
Quote from: dedndave on August 27, 2014, 03:15:36 AM
i think Jochen grabbed WM_DESTROY as an example - perhaps a poor choice

WM_DESTROY is, as Tedd rightly elaborated ("what [DefWindowProc] doesn't do (for whatever strange reason) is post WM_QUIT to your message queue"), the only message that you must handle.

All other messages are normally handled by DefWindowProc, including those that can return something useful, like a brush or a zero flag indicating "don't process me".

Of course, often it works without passing by DefWindowProc. But can you be sure that e.g. WM_PAINT is "done" with your handler? If it works with your current version, does it imply it will work with all future Windows versions?
Title: Re: Re: problems with a window
Post by: dedndave on August 27, 2014, 05:05:52 AM
each message is documented
what to return if the message has been "dealt with", and so on (many messages are different)
the documentation for DefWindowProc is not always as complete   :(
but, for many messages, an action is taken prior to exit

WM_PAINT is a special case, as DefWindowProc validates the update region and returns 0
if you have properly handled WM_PAINT, that should have been taken care of

if you have handled a message to your satisfaction, it is redundant to call DefWindowProc
it's similar to bloat-code, in that 1) it's the lazy way out, and 2) unnecessarily uses system resources

this is a little beyond the original poster's question, and we are in the campus
it won't hurt for him to become familiar with message handling
but, we don't need to confuse him with advanced discussion
Title: Re: Re: problems with a window
Post by: qWord on August 27, 2014, 05:25:45 AM
[irony]
It is a bit strange that Microsoft spreads obviously wrong examples for decades in the documentation and with SDK examples...
Typical crap they are comming up with (http://msdn.microsoft.com/en-us/library/windows/desktop/ms633570%28v=vs.85%29.aspx):

LRESULT CALLBACK MainWndProc(
    HWND hwnd,        // handle to window
    UINT uMsg,        // message identifier
    WPARAM wParam,    // first message parameter
    LPARAM lParam)    // second message parameter
{

    switch (uMsg)
    {
        case WM_CREATE:
            // Initialize the window.
            return 0;

        case WM_PAINT:
            // Paint the window's client area.
            return 0;

        case WM_SIZE:
            // Set the size and position of the window.
            return 0;

        case WM_DESTROY:
            // Clean up window-specific data objects.
            return 0;

        //
        // Process other messages.
        //

        default:
            return DefWindowProc(hwnd, uMsg, wParam, lParam);
    }
    return 0;
}



:icon_confused:
[\irony]


Title: Re: Re: problems with a window
Post by: jj2007 on August 27, 2014, 05:46:15 AM
I thought we had solved that question - or was it just put on ice?? (http://masm32.com/board/index.php?topic=2469.msg25883#msg25883)
Title: Re: Re: problems with a window
Post by: qWord on August 27, 2014, 06:05:15 AM
jj,
why did you come up with that discussion? Because you think that
WndProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
   
   .IF uMsg==WM_DESTROY
      invoke PostQuitMessage,NULL
      xor eax,eax
   .ELSEIF uMsg==WM_CREATE
      xor eax,eax
   .ELSE
      invoke DefWindowProc,hWnd,uMsg,wParam,lParam     
   .ENDIF
   ret

WndProc endp
is wrong?
Title: Re: Re: problems with a window
Post by: jj2007 on August 27, 2014, 06:48:55 AM
Quote from: qWord on August 27, 2014, 06:05:15 AM
jj,
why did you come up with that discussion? Because you think that
WndProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
   
   .IF uMsg==WM_DESTROY
      invoke PostQuitMessage,NULL
      xor eax,eax
   .ELSEIF uMsg==WM_CREATE
      xor eax,eax
   .ELSE
      invoke DefWindowProc,hWnd,uMsg,wParam,lParam     
   .ENDIF
   ret

WndProc endp
is wrong?

Yes, I think it's wrong, from a theoretical point of view:

All messages, if they don't have a handler, do pass DefWindowProc - Windows needs to do its job.

If you are giving special treatment to a message through e.g. a WM_CREATE handler, and you return a value (xor eax, eax / ret), it implies that you are not allowing Windows to perform the standard tasks required by WM_CREATE.

Of course, it might well be that the Windows developers are aware of the bad habit to use DefWindowProc only in a DEFAULT handler, and therefore do whatever needs to be done after the ret.

Of course, some messages are designed so that, if you choose to process them, a special value (e.g. a brush handle) should be returned (and therefore no invoke DefWindowProc, please).

But for the great majority, the safest assumption is that Windows may still have plans with that message, so put the invoke DefWindowProc after the Endsw. Here (http://masm32.com/board/index.php?topic=2469.msg25883#msg25883) is an example that shows what may go wrong if you put it only into the Default handler.

This practice is a few bytes shorter, and a few nanoseconds slower; the latter is completely irrelevant, even for the frequently posted messages like WM_MOUSEMOVE.

BTW Raymond Chen supports this view, too: Even if you have code to handle a message, you're allowed to call DefWindowProc, because you were doing that anyway after all. (http://blogs.msdn.com/b/oldnewthing/archive/2009/01/05/9274857.aspx)
Title: Re: Re: problems with a window
Post by: Gunther on August 27, 2014, 07:17:01 AM
Hi qWord,

I think we've beaten to death that point in the thread which Jochen mentioned, didn't we?

Gunther
Title: Re: Re: problems with a window
Post by: qWord on August 27, 2014, 07:33:51 AM
Quote from: jj2007 on August 27, 2014, 06:48:55 AMIf you are giving special treatment to a message through e.g. a WM_CREATE handler, and you return a value (xor eax, eax / ret), it implies that you are not allowing Windows to perform the standard tasks required by WM_CREATE.
Where are these standard tasks documented? You forget that this message is send by a function that creates the window - you imply that the developers split the code for windows creation in two function: CreateWindowEx and DefWindowProc. (the same as for WM_DESTROY which is send by DestroyWindow)

Quote from: jj2007 on August 27, 2014, 06:48:55 AMOf course, it might well be that the Windows developers are aware of the bad habit to use DefWindowProc only in a DEFAULT handler, and therefore do whatever needs to be done after the ret.
It is that exact these developers spread that "bad habit".

Quote from: jj2007 on August 27, 2014, 06:48:55 AMBut for the great majority, the safest assumption is that Windows may still have plans with that message
Any reference for that?

Quote from: jj2007 on August 27, 2014, 06:48:55 AMBTW Raymond Chen supports this view, too: Even if you have code to handle a message, you're allowed to call DefWindowProc, because you were doing that anyway after all. (http://blogs.msdn.com/b/oldnewthing/archive/2009/01/05/9274857.aspx)
I fully agree with that, but he only says that you must call DefWndProc if you do not process a message because of it parameters. A practical example that shows the point:
...
.elseif uMsg == WM_TIMER && wParam == IDT_XYZ ; <-- also test message parameter
...
.else
     invoke DefWindowProc,...
.endif


Quote from: Gunther on August 27, 2014, 07:17:01 AM
I think we've beaten to death that point in the thread which Jochen mentioned, didn't we?
no, as usual the discussion drift off.
Title: Re: Re: problems with a window
Post by: qWord on August 27, 2014, 08:25:26 AM
I just reconsider your last point and think that might be more reliable to use the following construct as template or for examples:
   .repeat
      .if uMsg == WM_XYZ
         ...
         ; default behaviour wished
      .elseif uMsg == WM_FOO
         .if wParam == xyz   ; further checks
            ...
            mov eax,result
            .break         ; job done
         .endif
      .elseif uMSg == ...
         ...
         xor eax,eax
         .break
      .endif
      invoke DefWindowProc,...
   .until 1
   ret


Of course one must take care to not forget .break and accidentally call DefWndProc.
Title: Re: Re: problems with a window
Post by: jj2007 on August 27, 2014, 08:45:05 AM
Quote from: qWord on August 27, 2014, 07:33:51 AMI fully agree with that, but he only says that you must call DefWndProc if you do not process a message because of it parameters

No, he says "Even if you have code to handle a message, you're allowed to call DefWindowProc, because you were doing that anyway after all".

And that is precisely what my example does: It calls DefWindowProc for all messages, because that is what Windows would be doing anyway after all.

BTW, both versions work fine. If you continue processing after the WM_CREATE handler (i.e. you pass by DefWindowProc, returning zero = success), then, after some hops, you end up at exactly the same location as if you had returned zero directly; e.g. for XP: 7E398734 mov ecx, fs:[18]. The only difference is some bytes of code less and some nanoseconds more.

QuoteI thought this was obvious.  I guess I was wrong. (http://blogs.msdn.com/b/oldnewthing/archive/2009/01/05/9274857.aspx#9281870)
;)
Title: Re: Re: problems with a window
Post by: qWord on August 27, 2014, 09:02:57 AM
Quote from: jj2007 on August 27, 2014, 08:45:05 AMAnd that is precisely what my example does: It calls DefWindowProc for all messages, because that is what Windows would be doing anyway after all.
Sorry, but I can't find that point in the blog post. The final code that is shown does call DefWndProc only for cases that are not handled:

switch (uMsg) {
   case WM_CHAR:
      OnChar(...);
      return 0; // <--

   case WM_SOMETHING:
   if (wParam == 4) {
      DoSomething4(...);
    }
    else
       return DefWindowProc(...);
   
    return 0; // <--

default:
   return DefWindowProc(...);
}
Title: Re: Re: problems with a window
Post by: qWord on August 27, 2014, 09:10:27 AM
Let me describe my point in other words:
With a window procedure we are describing the behavior of that window. So, when calling DefWindowProc for each message, we are always "overwriting" our own behavior-implementation with default behavior.
Title: Re: Re: problems with a window
Post by: jj2007 on August 27, 2014, 09:15:49 AM
If I had a case where an explicit return value was needed (a brush, ...), it would indeed RET that value. All other cases can handle the message, and then continue with DefWindowProc. By not passing DefWindowProc, you are blocking Windows' default processing, which may or may not work.

Quote from: qWord on August 27, 2014, 09:10:27 AM
Let me describe my point in other words:
With a window procedure we are describing the behavior of that window. So, when calling DefWindowProc for each message, we are always "overwriting" our own behavior-implementation with default behavior.

It depends on the message:

If a brush was expected, then your point is valid - DefWindowProc would overwrite our eax, and provide the default brush.
If no specific value would be expected, then Windows would do its default job on top of our code. The behaviour would be additive. WM_CREATE is such a case (although it seems that DefWindowProc does nothing useful afterwards, it just returns zero...).

There are situations, btw, where you would first call DefWindowProc and then add your own stuff, returning 0 or 1 or whatever. For WM_PAINT, this is sometimes necessary.
Title: Re: Re: problems with a window
Post by: dedndave on August 27, 2014, 09:16:17 AM
yah - i think that's going to backfire on you, at some point

there is one place where you need to let the default behaviour occur
that is in an MDI frame window
DefFrameProc needs to be able to handle the menu updates
Title: Re: Re: problems with a window
Post by: qWord on August 27, 2014, 09:31:32 AM
I see there will be no consent. Just to show up my point for clarification:

- whenever a message is not process by a handler, pass it to DefWindowProc
- whenever the documentation for a message exacts to call DefWndProc, do it.
- If (in whatever form) default behavior is wished, call DefWndProc after or before the own handler
- in any other case: do not call DefWndProc.
Title: Re: Re: problems with a window
Post by: qWord on August 27, 2014, 09:57:20 AM
Quote from: jj2007 on August 27, 2014, 09:15:49 AMAll other cases can handle the message, and then continue with DefWindowProc. By not passing DefWindowProc, you are blocking Windows' default processing, which may or may not work.
Any documentation for that?
Title: Re: Re: problems with a window
Post by: jj2007 on August 27, 2014, 04:55:20 PM
Quote from: qWord on August 27, 2014, 09:57:20 AM
Quote from: jj2007 on August 27, 2014, 09:15:49 AMAll other cases can handle the message, and then continue with DefWindowProc. By not passing DefWindowProc, you are blocking Windows' default processing, which may or may not work.
Any documentation for that?

I haven't seen a direct documentation, but Chen's blog explains the logic behind it:

If a message does not have a user-coded handler, it will definitely call DefWindowProc, and the latter will provide a default value (based on uMsg, wParam, lParam) which will then be returned to the OS.

So you can't do any harm by invoking DefWindowProc, except for those cases where you do want to return something that differs from the default, like a brush or a flag telling the OS "don't use this keypress".

Since in these cases you ret anyway, you can safely put the invoke DefWindowProc below the Endsw.

As to the potential performance loss: Balance it against the advantage of less code in the cache, and do some very basic calculations taking into account how often the message in question is being posted. If you find one that happens more than 100,000 times per second, then you should indeed be worried about performance. Otherwise not 8)
Title: Re: Re: problems with a window
Post by: Tedd on August 27, 2014, 09:34:12 PM
[This thread clearly needs to be split off into The Colosseum, as it is now really off-topic.]

JJ, I'm afraid you've got the wrong conclusion from Raymond's post.
The point is very simple: If you do not fully process a message, you may still pass it on to DefWindowProc to finish its processing.
That 'fully' is the key point. DefWindowProc does do further processing for many messages (rather than nothing at all), and so if you only handle part of the processing for a message, you can pass it on for the situations where you don't want to handle it, e.g. you only want to handle certain key-presses, but still have default handling for all other key-presses.
Now, if you always pass messages on to DefWindowProc, even after you just handled it, the default processing could very well contradict the processing that you just performed and wanted.
In summary:
1. If you do not handle a message at all, pass it to DefWindowProc;
2. If you do handle a message and complete all processing you require, do not pass it to DefWindowProc;
3. If you handle a message, but in some cases it will require further processing, pass it to DefWindowProc in those case only.
Title: Re: Re: problems with a window
Post by: jj2007 on August 27, 2014, 10:23:04 PM
Quote from: Tedd on August 27, 2014, 09:34:12 PM
[This thread clearly needs to be split off into The Colosseum, as it is now really off-topic.]
I would suggest the Laboratory.

QuoteJJ, I'm afraid you've got the wrong conclusion from Raymond's post.
The point is very simple: If you do not fully process a message, you may still pass it on to DefWindowProc to finish its processing.

If you partly process a message, e.g. the WM_CHAR handler for one particular key, what do you usually do afterwards? Right, you RETURN something, mostly zero indicating "no more processing". And therefore your processed messages will not invoke DefWindowProc.

All others should.
Title: Re: Re: problems with a window
Post by: Tedd on August 27, 2014, 10:47:56 PM
Quote from: jj2007 on August 27, 2014, 10:23:04 PM
If you partly process a message, e.g. the WM_CHAR handler for one particular key, what do you usually do afterwards? Right, you RETURN something, mostly zero indicating "no more processing". And therefore your processed messages will not invoke DefWindowProc.

All others should.
...what?!
If you handle WM_CHAR, then of course it shouldn't be passed to DefWindowProc; if you only handle some characters, then you can pass the rest to DefWindowProc, or not if you want them to be ignored (though default processing will mostly ignore them anyway.)
As for other messages, the same applies - they should not be re-processed if you've just processed them yourself.
Please go back and re-read Raymond's blog post again, carefully.
Title: Re: Re: problems with a window
Post by: hutch-- on August 27, 2014, 11:40:42 PM
Mutter, this stuff in Win95/NT4 technology, what is the debate about. Surely there is nothing new here, Win32 is 20 years old. The WM_CREATE is called by CreateWindow(Ex), most messages are sent to the address in the WNDCLASS structure and a range of keyboard messages are handled in the message loop.

The message you do not handle (most of them) are handled by the default processing, you fiddle some messages to get the effects you want and pass it along to the default handler and some you process and return ZERO without any default processing. Common in throwing away messages. There is nothing creative in message processing, it is system defined, deviate from system definition and you often end up in trouble.

Keep your creativity for good code design, basic system code is just hack stuff to make a windowing system work.
Title: Re: Re: problems with a window
Post by: jj2007 on August 27, 2014, 11:41:17 PM
Quote from: Tedd on August 27, 2014, 10:47:56 PMPlease go back and re-read Raymond's blog post again, carefully.

I always appreciate your good advice, Tedd. Show me where this code is incorrect...:

include \masm32\include\masm32rt.inc

.data
msg      MSG <?>
wc      WNDCLASSEX <WNDCLASSEX, 0, WndProc, 0, 0, 1, 2, 3, COLOR_BTNFACE+1, 0, txClass, 4>
txClass      db "Masm32GUI", 0

.code
start:
  mov wc.hInstance, rv(GetModuleHandle, 0)
  mov wc.hIcon, rv(LoadIcon, eax, IDI_APPLICATION)
  mov wc.hIconSm, eax
  mov wc.hCursor, rv(LoadCursor, NULL, IDC_ARROW)
  invoke RegisterClassEx, addr wc
  invoke CreateWindowEx, WS_EX_CLIENTEDGE,
     wc.lpszClassName, wc.lpszClassName,
     WS_OVERLAPPEDWINDOW or WS_VISIBLE,
     550, 150, 600, 400, NULL, NULL, wc.hInstance, NULL

  .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
  exit wParam

WndProc proc hWnd, uMsg, wParam, lParam
  SWITCH uMsg
  CASE WM_CHAR
    .if wParam==VK_SPACE      ; all other chars will go to DefWindowProc !!!
      MsgBox 0, "You hit space", "Hi", MB_OK
      xor eax, eax            ; this message was handled, and we decide
      ret                     ; that it will NOT be passed to DefWindowProc
    .endif
  CASE WM_DESTROY
    invoke PostQuitMessage, NULL
  ENDSW

  ; default processing for all other messages, including WM_CHAR if it is not a space
  invoke DefWindowProc, hWnd, uMsg, wParam, lParam

  ret
WndProc endp

end start


Quote from: Tedd on August 27, 2014, 10:47:56 PMthey should not be re-processed if you've just processed them yourself.
Correct if your own processing is a full substitute for the default processing.
Title: Re: Re: problems with a window
Post by: qWord on August 28, 2014, 12:07:21 AM
jj, the above code is correct as per documentation, but it is that you did claim all received messages should be default processed, with the exception for messages that have nonzero return values. As you said your self, there no peach of documentation that  exacts that - in contrast, msdn very clear about the purpose of DefWindowProc:
QuoteCalls the default window procedure to provide default processing for any window messages that an application does not process. This function ensures that every message is processed.
Title: Re: Re: problems with a window
Post by: jj2007 on August 28, 2014, 12:27:15 AM
Quote from: qWord on August 28, 2014, 12:07:21 AM
jj, the above code is correct as per documentation, but it is that you did claim all received messages should be default processed, with the exception for messages that have nonzero return values.

Glad to see that we are converging. Maybe we can agree on "with the exception for messages that take documented non-default return values, like FALSE, TRUE, or a brush"?
Title: Re: Re: problems with a window
Post by: qWord on August 28, 2014, 12:49:48 AM
Quote from: jj2007 on August 28, 2014, 12:27:15 AMGlad to see that we are converging. Maybe we can agree on [...]
sorry, we are not converging and I will never agree with your claim. My experience, the example code and documentation provided Microsoft and all that other WinAPI code I've seen so far stands in contrast to your claim.
Title: Re: Re: problems with a window
Post by: dedndave on August 28, 2014, 02:06:51 AM
it's not just the return value that concerns me
it's the default "action"

i would guess that most messages have very little default action, if any - but, some do
somewhere, you are going to run into a problem....
1) you handle a message, as desired
2) the default action is also performed, which may alter or mask the desired action
3) you start pulling your hair out trying to find the "bug"

we can agree to disagree - lol
i am right, you are wrong - the end    :biggrin:
Title: Re: Re: problems with a window
Post by: jj2007 on August 28, 2014, 04:26:32 AM
Quote from: dedndave on August 28, 2014, 02:06:51 AM
1) you handle a message, as desired
2) the default action is also performed, which may alter or mask the desired action

1) you handle a message, as desired, and either...

a) ... return something (TRUE, FALSE, a brush, ...), therefore the default action is not performed

or

b) ... do not return, so the default action is also performed, which is what Windows would have done anyway if you had not handled that message.

BTW you see often code like (source (http://www.cplusplus.com/forum/windows/35571/))
Quotecase WM_KEYDOWN:
            if(GetDlgCtrlID(GetFocus())==IDC_KEY) {
                SendMessage(HWND_KEY,WM_SETTEXT,0,(LPARAM)"test");
                return 0;
            } else {
                return DefWindowProc (hwnd, message, wParam, lParam);
            }

Which is utterly inefficient, but if you have a DEFAULT handler, and it's the only one that invokes DefWindowProc, then you need to return the DefWindowProc result for those cases that you don't handle.
Title: Re: Re: problems with a window
Post by: dedndave on August 28, 2014, 04:49:31 AM
it is inefficient to repeat the INVOKE DefWndProc call, over and over
but, i might also remind you that it is inefficient to repeat the RET code

in those rare instances where i need to "break" into the default, i might do...
    .if eax==WM_SOMEMESSAGE
        .if something
            ;do stuff
        .else
            jmp     DefPrc
        .endif

DefPrc: INVOKE  DefWndProc,,,,


of course, the WM_KEYDOWN documentation tells us...
QuoteAn application should return zero if it processes this message.
but, i know you're trying to give a non-specific example
Title: Re: Re: problems with a window
Post by: jj2007 on August 28, 2014, 05:03:41 AM
Quote from: dedndave on August 28, 2014, 04:49:31 AM
but, i might also remind you that it is inefficient to repeat the RET code

            ;do stuff
            xor eax, eax
            jmp RetEax
   ...

DefPrc:  INVOKE  DefWndProc,,,,
RetEax:  ret
Title: Re: Re: problems with a window
Post by: Tedd on August 28, 2014, 07:50:24 AM
You can tell an argument is going wayward when it starts to devolve into nit-picking over certain points, so let's state the facts:
But obviously the masses are wrong and JJ is right. Microsoft purposely create misleading development examples in order to trick people so they can't produce correct software. Event Raymond Chen is in on the conspiracy.

JJ, really, I wasn't being 'smart' - go back and re-read the blog post carefully. If you still think it suggests calling DefWindowProc after you have already fully processed a message, I will go through it in patronising detail to make sure there is no misinterpretation.
Title: Re: Re: problems with a window
Post by: jj2007 on August 28, 2014, 02:36:45 PM
Quote from: Tedd on August 28, 2014, 07:50:24 AM
  • Reputable members of this board say to process a message or pass it to DefWindowProc, not both;

That includes me, indeed. On numerous occasions above I have written that, if the processed part of a message (search for what?! inside this page) does return something useful, this implies that you would not invoke DefWindowProc.

We are basically discussing two options here:

A: default handler calls DefWindowProc (standard C practice)
WndProc proc hWnd, uMsg, wParam, lParam
  SWITCH uMsg
  CASE WM_CHAR
    .if wParam==VK_SPACE      ; all other chars will go to DefWindowProc !!!
      MsgBox 0, "You hit space", "Hi", MB_OK
      xor eax, eax            ; this message was handled, and we decide
      ret                     ; that it will NOT be passed to DefWindowProc
    .else
      return rv(DefWindowProc, hWnd, uMsg, wParam, lParam)
    .endif
  CASE WM_DESTROY
    invoke PostQuitMessage, NULL
    xor eax, eax  ; RETURN ZERO
  DEFAULT
    ; default processing for all other messages
    invoke DefWindowProc, hWnd, uMsg, wParam, lParam
  ENDSW

  ret
WndProc endp


B: no default handler, handled messages either return or end up calling DefWindowProc
WndProc proc hWnd, uMsg, wParam, lParam
  SWITCH uMsg
  CASE WM_CHAR
    .if wParam==VK_SPACE      ; all other chars will go to DefWindowProc !!!
      MsgBox 0, "You hit space", "Hi", MB_OK
      xor eax, eax            ; this message was handled, and we decide
      ret                     ; that it will NOT be passed to DefWindowProc
    .endif
  CASE WM_DESTROY
    invoke PostQuitMessage, NULL
  ENDSW

  ; default processing for all messages that do NOT return,
  ; including WM_CHAR if it is not a space
  invoke DefWindowProc, hWnd, uMsg, wParam, lParam

  ret
WndProc endp


Both versions perform exactly the same tasks, with one notable exception: My handling of WM_DESTROY performs a call to DefWindowProc before returning. That is a superfluous step because we all know that DefWindowProc will return zero for that message, so we might as well add return 0, as all C programmers would instinctively do, but why do you think Raymond Chen chooses a loooong title like Even if you have code to handle a message, you're allowed to call DefWindowProc, because you were doing that anyway after all? (http://blogs.msdn.com/b/oldnewthing/archive/2009/01/05/9274857.aspx#9281870) And what do you think will be the value of eax after invoke DefWindowProc, hWnd, WM_DESTROY, wParam, lParam?

EDIT: Attached a crispy example, with sources. They differ only by C_style=1.
Title: Re: Re: problems with a window
Post by: qWord on August 28, 2014, 03:20:56 PM
jj, you did claim that we must call DefWindowProc even when the message has been processed!



EDIT: just remove stupid example.
Title: Re: Re: problems with a window
Post by: jj2007 on August 28, 2014, 05:22:20 PM
Quote from: qWord on August 28, 2014, 03:20:56 PM
jj, you did claim that we must call DefWindowProc even when the message has been processed!
Where?

QuoteEDIT: just remove stupid example.
??

P.S.: See EDIT/attachment in reply #41 above. Let me know if you can close the app with Alt F4 in the C_style=1 version ;)
Title: Re: Re: problems with a window
Post by: qWord on August 28, 2014, 05:46:54 PM
Quote from: jj2007 on August 28, 2014, 05:22:20 PMWhere?
Quote from: jj2007 on August 27, 2014, 09:15:49 AMIf I had a case where an explicit return value was needed (a brush, ...), it would indeed RET that value. All other cases can handle the message, and then continue with DefWindowProc. By not passing DefWindowProc, you are blocking Windows' default processing, which may or may not work.

Quote from: jj2007 on August 28, 2014, 05:22:20 PMLet me know if you can close the app with Alt F4 in the C_style=1 version ;)
That is simply a wrong message handling, but this has nothing do with your above statement.
Title: Re: Re: problems with a window
Post by: jj2007 on August 28, 2014, 08:11:43 PM
Quote from: qWord on August 28, 2014, 05:46:54 PMThat is simply a wrong message handling

Yes indeed, but with a few lines more you can "improve" it to make it work (and make it look more like proper C code):

WndProc proc hWnd, uMsg, wParam, lParam
  SWITCH uMsg
  CASE WM_SYSKEYDOWN
    .if wParam==VK_F1      ; all other chars will go through DefWindowProc !!!
          MsgBox 0, "Click OK", "Hi", MB_OK
    .else
          invoke DefWindowProc, hWnd, uMsg, wParam, lParam
          ret
    .endif
  CASE WM_DESTROY
    invoke PostQuitMessage, NULL
    xor eax, eax      ; if an app processes this message, it should return zero
    ret      ; if it would pass DefWindowProc, it would indeed return zero
  DEFAULT      ; Microsoft, Tedd and qWord say this is the right way to do it
    invoke DefWindowProc, hWnd, uMsg, wParam, lParam
  ENDSW
  ret
WndProc endp
Title: Re: Re: problems with a window
Post by: MichaelW on August 28, 2014, 08:28:42 PM
At least running under Windows 7 this coding works for me, and responds to Alt+F4 normally, with or without the return rv(DefWindowProc... statement.

WindowProc proc hwnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
    SWITCH uMsg     
        CASE WM_CHAR
            .if wParam==VK_SPACE
                MsgBox 0, "You hit space", "Hi", MB_OK
                xor eax, eax
                ret
            .else
                return rv(DefWindowProc, hwnd, uMsg, wParam, lParam)
            .endif               
        CASE WM_CLOSE
            invoke DestroyWindow, hwnd
        CASE WM_DESTROY
            invoke PostQuitMessage, NULL
        DEFAULT
            invoke DefWindowProc, hwnd, uMsg, wParam, lParam
            ret
    ENDSW
    return 0
WindowProc endp

Title: Re: Re: problems with a window
Post by: Tedd on August 28, 2014, 10:30:21 PM
Quote from: jj2007 on August 28, 2014, 02:36:45 PM
On numerous occasions above I have written that, if the processed part of a message (search for what?! inside this page) does return something useful, this implies that you would not invoke DefWindowProc.
This is not about return values - it's a very simple matter to return zero to indicate you've processed a given message, or another appropriate value where that is required (such cases are documented). The issue is with doing additional processing after you have already fully processed the message because that further processing could contradict the original processing you just performed.
Of course, now you will just argue that one shouldn't call DefWindowProc in those specific cases either, but this is the point - one should not call DefWindowProc in any cases where you have already fully processed the message.

Quote
We are basically discussing two options here:
...
This is an overly simplified example that handles 2 whole messages and does nothing useful. Of course it happens to work; though it fails to really demonstrate your argument. And I would argue that calling DefWindowProc after already handling WM_DESTROY is not only unnecessary, but incorrect. If the only reason is so you can return zero, why not just return zero?

Quote
why do you think Raymond Chen chooses a loooong title like Even if you have code to handle a message, you're allowed to call DefWindowProc, because you were doing that anyway after all? (http://blogs.msdn.com/b/oldnewthing/archive/2009/01/05/9274857.aspx#9281870)
So, is this is the source of your misunderstanding? Ignore the title and read the very first paragraph.
Quote from: RaymondChenJust because you write case WM_SOMETHING: doesn't mean that you have to handle all possible parameters for the WM_SOMETHING message. You're still allowed to call the DefWindowProc function. After all, that's what you did when you didn't have a case WM_SOMETHING: statement in the first place.
The "you were doing that anyway" means "you were doing that anyway [when you were not handling the message at all]", it does not mean "you were doing that anyway [when you had already fully handled the message and then returned so that windows could process the message yet again]"

Had you read carefully, this is what you should have understood:
Quote from: Tedd on August 27, 2014, 09:34:12 PM
1. If you do not handle a message at all, pass it to DefWindowProc;
2. If you do handle a message and complete all processing you require, do not pass it to DefWindowProc;
3. If you handle a message, but in some cases it will require further processing, pass it to DefWindowProc in those cases only.

Quote
And what do you think will be the value of eax after invoke DefWindowProc, hWnd, WM_DESTROY, wParam, lParam?
The return value is zero, where appropriate. The result is additional processing that was not required or wanted.
Title: Re: Re: problems with a window
Post by: jj2007 on August 28, 2014, 11:34:15 PM
Quote from: Tedd on August 28, 2014, 10:30:21 PMThe issue is with doing additional processing after you have already fully processed the message because that further processing could contradict the original processing you just performed.

It doesn't get more convincing if you repeat the same stuff over and over, Tedd.

  CASE WM_CHAR
    .if wParam==VK_SPACE      ; all other chars will go to DefWindowProc !!!
      MsgBox 0, "You hit space", "Hi", MB_OK
      xor eax, eax            ; this message was handled, and we decide
      ret             ; that it will NOT be passed to DefWindowProc
    .endif
Title: Re: Re: problems with a window
Post by: hutch-- on August 29, 2014, 02:34:24 AM
Lets go for a short walk down memory lane here, for those of us who have been coding Windows since THE original SDK (which cost you over a grand here in OZ circa 1990) the basic logic of a system defined window (there are not any other type) has not changed since the 16 bit Win3.0/1 era. Differing from the 16 bit DOS era, the system is a message driven windowing system that provides the windowing system according to its specifications to any programmer who bothers to read the Windows API lists.

Now Win32 has been with us for close to 20 years and for the normal reasons of backwards compatibility, the basic mechanics of how to get a window going and how to process the messages that are sent through it have not changed over that period, it is still a lead in procedure (often called a WinMain) that refers to a callback procedure in its definition structure WNDCLASS and empties into a system defined message loop which has a system defined method of exiting the message loop and terminating the application.

The archetypal examples were Charles Petzold back in the middle 1990s and minus the dual 16/32 bit C compatibility code, nothing has changed in Win32 since then. The system defined callback procedure is often called a WndProc and it has a very specific format, 4 DWORD size variable are passed to it on the stack by the operating system which identify the bulk of the messages sent to the Window by the operating system. If you ever want to see the vast array of messages sent to a running window, set up a message spy utility that looks at all of them and you will see a flood of messages going past. This is what the default Windows procedure is routinely processing. Most people never need to process the non client hit test messages but they are still sent through the callback.

Many get confused by the many examples of layering that you find in different development environments, the simplified easy style of Windows, even the system defined dialogs are a system defined layering system but this much is true, the system layering STILL uses the same core that was defined as Win32 20 years ago because if it did not, it would not be backwards compatible.

Now while creative genius is virtuous and encouraged by most of the older members here, the Campus is not the best place for debates over inflicting deviations on folks who are trying to get the swing of what is originally complex code. We have enough places for custom code designs but the Campus is not the place for it. What I ask of members is keep the debates over technical details OUT OF THE CAMPUS as it simply confuses folks who are learning this style of coding. This is the place for core Win32 code defined by the operating system, you can play with message crackers, despatchers and a many other tricky variations elsewhere and once folks who are learning this stuff know enough, they can learn yours, mine and everyone else's bad habits as well as developing a range of their own.
Title: Re: Re: problems with a window
Post by: dedndave on August 29, 2014, 03:11:33 AM
suggestion:
start with reply #8, and split the thread   :t
Title: Re: Re: problems with a window
Post by: Tedd on August 29, 2014, 03:29:50 AM
Quote from: jj2007 on August 28, 2014, 11:34:15 PM
It doesn't get more convincing if you repeat the same stuff over and over, Tedd.
I could say the same to you. I'm repeating myself because you seem to be missing the point and I don't know how I can explain it any more clearly.
Also, moving the focus to examples on which we never disagreed does not hide the fact that your original statements which sparked this argument are still wrong.

Quote from: jj2007 on August 27, 2014, 06:48:55 AM
If you are giving special treatment to a message through e.g. a WM_CREATE handler, and you return a value (xor eax, eax / ret), it implies that you are not allowing Windows to perform the standard tasks required by WM_CREATE.
No. WM_CREATE is a 'notification' that the window has been created - to allow you to perform initialisation. That is all. There are no standard tasks required.

Quote
Of course, it might well be that the Windows developers are aware of the bad habit to use DefWindowProc only in a DEFAULT handler, and therefore do whatever needs to be done after the ret.
No. If there are things that need to be done after returning from processing a message, they will be done. If you call DefWindowProc to handle that message and then return, they will still be done. If you don't call DefWindowProc to handle that message and then return, they will still be done. If it happens that they won't be done when you return zero, then so be it, but calling DefWindowProc in that case will still not get them done.

Quote
...for the great majority [of messages], the safest assumption is that Windows may still have plans with that message, so put the invoke DefWindowProc after the Endsw.
No. This is wrong. This is where the actual argument is. The only purpose of DefWindowProc is handle those messages which you do not fully handle yourself. There is no secret processing that happens afterward. If you have processed it fully, that is it - there is no need to pass it on - it has been fully processed. The end. Fin.

Quote
BTW Raymond Chen supports this view, too: Even if you have code to handle a message, you're allowed to call DefWindowProc, because you were doing that anyway after all. (http://blogs.msdn.com/b/oldnewthing/archive/2009/01/05/9274857.aspx)
No. He doesn't. This is not what he says - as I have already explained. None of the code in this article falls through to call DefWindowProc after a message has been fully processed. DefWindowProc is called for some messages, but only when they will not be fully processed otherwise - which is the entire point of the article.
Title: Re: Re: problems with a window
Post by: Tedd on August 29, 2014, 03:33:19 AM
Quote from: hutch-- on August 29, 2014, 02:34:24 AM
Now while creative genius is virtuous and encouraged by most of the older members here, the Campus is not the best place for debates over inflicting deviations on folks who are trying to get the swing of what is originally complex code. We have enough places for custom code designs but the Campus is not the place for it. What I ask of members is keep the debates over technical details OUT OF THE CAMPUS as it simply confuses folks who are learning this style of coding. This is the place for core Win32 code defined by the operating system, you can play with message crackers, despatchers and a many other tricky variations elsewhere and once folks who are learning this stuff know enough, they can learn yours, mine and everyone else's bad habits as well as developing a range of their own.
Indeed. I did suggest splitting the argument off and moving it to The Colosseum; starting from reply #8.

Apologies to Ar0n for the thread hijacking; also welcome to board politics :icon_mrgreen:
Title: Re: problems with a window
Post by: jj2007 on August 29, 2014, 04:25:26 AM
Quote from: Tedd on August 29, 2014, 03:29:50 AM
Quote
...for the great majority [of messages], the safest assumption is that Windows may still have plans with that message, so put the invoke DefWindowProc after the Endsw.
No. This is wrong. This is where the actual argument is. The only purpose of DefWindowProc is handle those messages which you do not fully handle yourself. There is no secret processing that happens afterward. If you have processed it fully, that is it - there is no need to pass it on - it has been fully processed. The end. Fin.

Test it on the example attached above:

  CASE WM_SYSKEYDOWN
    .if wParam==VK_F1
          MsgBox 0, "Click OK, then press Alt F4 to close this app", "Hi", MB_OK
    .endif
    xor eax, eax      ; return FALSE
    inc eax      ; or return TRUE
    ret      ; we don't let DefWindowProc do its job


You may return TRUE or FALSE, it won't change the result: You can't close that window with Alt F4 any more. So there is "secret processing" happening, and DefWindowProc is not just there to "notify" the programmer. Who in this example would have to ret rv(DefWindowProc, ...) to make Alt F4 work again.

Quote from: Tedd on August 29, 2014, 03:29:50 AMWM_CREATE is a 'notification' that the window has been created - to allow you to perform initialisation. That is all. There are no standard tasks required.

That seems correct for WM_CREATE, but there are many other messages - like WM_SYSKEYDOWN - that don't fall into this category; they need their default processing, unless you explicitly want to block that by returning something.

I guess we'll now start arguing about the meaning of "fully" 8)

@Hutch: Thanks for moving this :t
Title: Re: problems with a window
Post by: Gunther on August 29, 2014, 05:25:38 AM
Moving was a good decision, Hutch.  :t

Gunther
Title: Re: problems with a window
Post by: Tedd on August 29, 2014, 07:00:02 AM
Quote from: jj2007 on August 29, 2014, 04:25:26 AM
...
You may return TRUE or FALSE, it won't change the result: You can't close that window with Alt F4 any more. So there is "secret processing" happening, and DefWindowProc is not just there to "notify" the programmer. Who in this example would have to ret rv(DefWindowProc, ...) to make Alt F4 work again.
There are two function calls in the standard message-loop, the second of which is TranslateMessage - whose job is to convert sequences of WM_KEYDOWN+WM_KEYUP into WM_CHAR messages, and WM_SYSKEYDOWN+WM_SYSKEYUP into WM_SYSCHAR messages. (ALT+?? combinations produce WM_SYSCHAR messages.)
So, if you eat WM_SYSKEYDOWN messages, guess what happens - no WM_SYSCHAR message, and so no ALT+F4 notification. In your inadequate example, you're taking ALT+F1 for yourself, but then discarding all other ALT+?? keys (which includes F4). In other words, you're not fully handling WM_SYSKEYDOWN.
Of course it doesn't work. And this is why you need to pass those unhandled messages to DefWindowProc. You are only handling it for ALT+F1 (which should not be passed to DefWindowProc), while you're not handling any others (which should then be passed to DefWindowProc).
Pass the unhandled messages to DefWindowProc and it will work correctly.

Quote
Quote from: Tedd on August 29, 2014, 03:29:50 AMWM_CREATE is a 'notification' that the window has been created - to allow you to perform initialisation. That is all. There are no standard tasks required.

That seems correct for WM_CREATE, but there are many other messages - like WM_SYSKEYDOWN - that don't fall into this category; they need their default processing, unless you explicitly want to block that by returning something.
It was meant only for WM_CREATE, since you were suggesting there may be secret processing going on that required calling DefWindowProc after you had already handled the message yourself. Some messages are only for notification, while others do indeed require processing (which you either do yourself, or you pass it to DefWindowProc, but still not both.)

Quote
I guess we'll now start arguing about the meaning of "fully" 8)
I would hope the meaning is obvious.
As with the WM_SYSKEYDOWN message, if there are many possible cases (all possible key-presses) and you only handle a single one, then that is clearly not 'fully' - you have not handled 100% of the cases; pass the remaining cases to DefWindowProc.
Title: Re: problems with a window
Post by: dedndave on August 29, 2014, 07:18:18 AM
WM_SYSKEYDOWN is a special case
the OS processes the keys in a pre-defined way if DefWndProc is called
however, the message is sent so that a window proc may bypass the "standard" (default) behaviour, if desired
otherwise, you would probably handle one of the other key-related messages
Title: Re: problems with a window
Post by: hutch-- on August 29, 2014, 11:56:09 AM
Is it any secret that key strokes are processed directly in the message loop ALA Petzold 1995 ? You do not see system defined accelerators in the WndProc, you see them directly in the message loop, that is how Win32 was designed in the first place and to keep it backwards compatible, it still works that way. It is done to address a 1 character lag that often occurs if you try and process keystrokes in the WndProc or a control subclass.

RE: WM_CREATE, it is only ever called once, during the creation of the Window ALA CreateWindowEx in Win32 so if you can see some advantage in stacking messages in an order in a switch block, you put it down near the end as it has already been called that once at window creation. Truly some of you guys needed to have written Win16 Windows code in a co-operative multitasking environment where the slightest glitch crashed the OS (the BLACK screen of death really told you that you had messed up).
Title: Re: problems with a window
Post by: jj2007 on August 29, 2014, 12:34:23 PM
Quote from: Tedd on August 29, 2014, 07:00:02 AMSo, if you eat WM_SYSKEYDOWN messages, guess what happens - no WM_SYSCHAR message, and so no ALT+F4 notification. In your inadequate example, you're taking ALT+F1 for yourself, but then discarding all other ALT+?? keys (which includes F4). In other words, you're not fully handling WM_SYSKEYDOWN.
Of course it doesn't work. And this is why you need to pass those unhandled messages to DefWindowProc. You are only handling it for ALT+F1 (which should not be passed to DefWindowProc), while you're not handling any others (which should then be passed to DefWindowProc).
Pass the unhandled messages to DefWindowProc and it will work correctly.

Tedd, YOU ARE ABSOLUTELY RIGHT!!! 100%!!!

The only disagreement is whether it should be done the ugly C way:

WndProc proc hWnd, uMsg, wParam, lParam
  SWITCH uMsg
  CASE WM_SYSKEYDOWN
    .if wParam==VK_F1
          MsgBox 0, "Click OK", "Hi", MB_OK
          ret      ; we don't pass by DefWindowProc, we RETURN
    .else
          ; because of the DEFAULT below, you will need this shitty else branch for all messages that are only "partly" processed:
          invoke DefWindowProc, hWnd, uMsg, wParam, lParam
          ret
    .endif
  CASE WM_DESTROY
    invoke PostQuitMessage, NULL
    xor eax, eax      ; "if an app processes this message, it should return zero"
    ret
  DEFAULT      ; C style...
    invoke DefWindowProc, hWnd, uMsg, wParam, lParam
  ENDSW
  ret
WndProc endp


... or the elegant ASM way:

WndProc proc hWnd, uMsg, wParam, lParam
  SWITCH uMsg
  CASE WM_SYSKEYDOWN
    .if wParam==VK_F1
          MsgBox 0, "Click OK", "Hi", MB_OK
          ret      ; we don't pass by DefWindowProc, we RETURN
    .endif
  CASE WM_DESTROY
    invoke PostQuitMessage, NULL      ; next step is DefWP, which will set eax to zero
  ENDSW
  ; process all messages that did NOT return above
  invoke DefWindowProc, hWnd, uMsg, wParam, lParam
  ret
WndProc endp


Of course, somebody will now remark that WM_DESTROY was processed, and therefore should not pass DefWindowProc; but Raymond Chen says that Even if you have code to handle WM_DESTROY, you're allowed to call DefWindowProc, because you were doing that anyway after all. (http://blogs.msdn.com/b/oldnewthing/archive/2009/01/05/9274857.aspx#9281870)

P.S.: If you think this is nitpicking, try this thread among C programmers (especially novacain's comments) (http://cboard.cprogramming.com/windows-programming/140936-return-value-wndproc.html#post1051555) ;)

P.P.S.: Below an explanation why Raymond Chen is so adamant about using DefWindowProc.
Title: Re: problems with a window
Post by: Tedd on August 30, 2014, 01:04:58 AM
Quote from: jj2007 on August 29, 2014, 12:34:23 PM
Tedd, YOU ARE ABSOLUTELY RIGHT!!! 100%!!!
Yes, I know.

Quote
The only disagreement is whether it should be done the ugly C way:

... or the elegant ASM way:
Or, do it the sensible and correct way.
WndProc proc hWnd, uMsg, wParam, lParam
  SWITCH uMsg
  CASE WM_SYSKEYDOWN
    .if wParam==VK_F1
          MsgBox 0, "Click OK", "Hi", MB_OK
          ;fall through to return zero
    .else
          jmp defwndproc
    .endif
  CASE WM_DESTROY
    invoke PostQuitMessage, NULL
    ;fall through to return zero
  DEFAULT
    defwndproc:
    invoke DefWindowProc, hWnd, uMsg, wParam, lParam
    ret
  ENDSW
  xor eax,eax  ;return zero to indicate message processed
  ret
WndProc endp

(Messages which are handled and require a non-zero return can explicitly return instead of falling through.)

Quote
Of course, somebody will now remark that WM_DESTROY was processed, and therefore should not pass DefWindowProc; but Raymond Chen says that Even if you have code to handle WM_DESTROY, you're allowed to call DefWindowProc, because you were doing that anyway after all. (http://blogs.msdn.com/b/oldnewthing/archive/2009/01/05/9274857.aspx#9281870)
Yes, I will stay that - because it's correct.
As I have already explained very clearly -- not that you're able to read, apparently -- that is not what Raymond Chen says.
Quote from: Tedd on August 28, 2014, 10:30:21 PM
"you were doing that anyway" means "you were doing that anyway [when you were not handling the message at all]", it does not mean "you were doing that anyway [when you had already fully handled the message and then returned so that windows could process the message yet again]"

Quote
P.P.S.: Below an explanation why Raymond Chen is so adamant about using DefWindowProc.
1. He's not;
2. What that's actually demonstrating is that you can't simply return zero as a shortcut for not handling messages, and should call DefWindowProc for the situations you don't handle.


This has been amusing, but it's quite obvious you're either ignoring the main points of my explanations, or you're just unable to understand. Either way, it's pointless to continue replying.

There is quality software to be written; enjoy your weekend! 8)
Title: Re: problems with a window
Post by: jj2007 on August 30, 2014, 02:35:31 AM
Quote from: Tedd on August 30, 2014, 01:04:58 AM
    .else
          jmp defwndproc   ; There is quality software to be written  ;)
    .endif

  CASE WM_DESTROY
    invoke PostQuitMessage, NULL
    ;fall through to return zero <- there is no fall through in assembler (there was no fall through in any language until K&R messed it up) (http://stackoverflow.com/questions/252489/why-was-the-switch-statement-designed-to-need-a-break)
  DEFAULT
    defwndproc:
    invoke DefWindowProc, hWnd, uMsg, wParam, lParam
    ret
  ENDSW
  xor eax,eax  ;return zero to indicate message processed
  ret
WndProc endp
...
enjoy your weekend! 8)

Same to you :icon14:
Title: Re: problems with a window
Post by: Tedd on August 30, 2014, 03:50:18 AM
Really - this is the best you could come up with?

Quote from: jj2007 on August 30, 2014, 02:35:31 AM
    .else
          jmp defwndproc   ; There is quality software to be written  ;)
    .endif
It's a straightforward modification to fit with the lacking example you posted, not the way I would necessarily implement it.

Quote
  CASE WM_DESTROY
    invoke PostQuitMessage, NULL
    ;fall through to return zero <- there is no fall through in assembler (there was no fall through in any language until K&R messed it up) (http://stackoverflow.com/questions/252489/why-was-the-switch-statement-designed-to-need-a-break)
The CASE macro is implemented as IF-statements, it's not a real 'case' statement. I was clearly referring 'falling through' to exit the case (actually a jump to the ENDIF) and thus return zero; if it were 'real' fall-through, execution would continue in the next case-block, not exiting to return zero.

:eusa_boohoo:
Title: Re: problems with a window
Post by: jj2007 on August 30, 2014, 04:10:58 AM
Quote from: Tedd on August 30, 2014, 03:50:18 AMI was clearly referring 'falling through' to exit the case

You mean you clearly intended to add the red line below, and then were distracted by something more important?

    .else
          jmp defwndproc   ; in C speak, this elegant solution means "the absence of a break statement" ;-)
    .endif
  CASE WM_DESTROY
    invoke PostQuitMessage, NULL
    jmp defwndproc     ;fall through to return zero
  DEFAULT
    defwndproc:
    invoke DefWindowProc, hWnd, uMsg, wParam, lParam
Title: Re: problems with a window
Post by: qWord on August 30, 2014, 05:25:06 AM
Quote from: Tedd on August 30, 2014, 03:50:18 AM
Really - this is the best you could come up with?
he just needs that to whitewash his original calim, which was the reason for the whole discussion.
Title: Re: problems with a window
Post by: Tedd on August 30, 2014, 11:19:51 AM
Quote from: Tedd on August 27, 2014, 09:34:12 PM
1. If you do not handle a message at all, pass it to DefWindowProc;
2. If you do handle a message and complete all processing you require, do not pass it to DefWindowProc;
3. If you handle a message, but in some cases it will require further processing, pass it to DefWindowProc in those cases only.

Quote from: jj2007 on August 29, 2014, 12:34:23 PM
Tedd, YOU ARE ABSOLUTELY RIGHT!!! 100%!!!


:eusa_boohoo:
Title: Re: problems with a window
Post by: Gunther on August 31, 2014, 09:07:32 AM
And what's the essence of the entire elongated discussion?

Gunther
Title: Re: problems with a window
Post by: hutch-- on August 31, 2014, 11:52:31 AM
Just as an aside to such weighty issues, long ago I remember reading a lament from one of K&R about how the C switch block worked and the need for "break". Its something you get used to but its a pain switching from one language to another, with C I often forget the "break" and have to go back and fix it (lucky I write very little C these days) and with Basic I usually forget to put the "Then" operator after the starting line of an "If" block.

Now given that I don't suffer any bias at all over languages  :biggrin: MASM got it right where the rest stuffed it up with their purple prose, wordy waffle and general imprecision. Real men[tm] code their own in mnemonics.  :P
Title: Re: problems with a window
Post by: jj2007 on August 31, 2014, 04:53:57 PM
Quote from: hutch-- on August 31, 2014, 11:52:31 AM
Just as an aside to such weighty issues, long ago I remember reading a lament from one of K&R about how the C switch block worked and the need for "break". Its something you get used to but its a pain switching from one language to another, with C I often forget the "break"...

You are in good company there, Hutch - remember the Apple's most famous source code (http://masm32.com/board/index.php?topic=2959.0) thread?

But indeed, Masm is very flexible, just add an equate like goto equ <jmp>, and you can write beautiful code in 'Apple C style' like

  SWITCH uMsg
  CASE WM_SYSKEYDOWN
    .if wParam==VK_F1
          MsgBox 0, "Click OK", "Hi", MB_OK
          ;fall through to return zero
    .else
          goto defwndproc;
    .endif
  CASE WM_DESTROY
    invoke PostQuitMessage, NULL
  DEFAULT
    defwndproc:
    invoke DefWindowProc, hWnd, uMsg, wParam, lParam
;)
Title: Re: problems with a window
Post by: Gunther on August 31, 2014, 07:38:02 PM
Oh yes, no one can deny a goto in honor.

Gunther
Title: Re: problems with a window
Post by: dedndave on August 31, 2014, 09:10:44 PM
i have to wonder if issues like the ones in the link are related to the discussion here...

http://masm32.com/board/index.php?topic=94.msg36513#msg36513 (http://masm32.com/board/index.php?topic=94.msg36513#msg36513)
Title: Re: problems with a window
Post by: jj2007 on August 31, 2014, 09:53:44 PM
Quote from: dedndave on August 31, 2014, 09:10:44 PM
i have to wonder if issues like the ones in the link are related to the discussion here...

http://masm32.com/board/index.php?topic=94.msg36513#msg36513 (http://masm32.com/board/index.php?topic=94.msg36513#msg36513)

See Guga's answer:
Quote from: guga on August 02, 2014, 06:57:41 PMthe menus on the middle of the desktop goes back to the original position after a few time (milliseconds, in fact)
It works fine, although with a small delay - simply because the top row of the menus is a separate, independent window. That solution is a bit odd but it beats Aero on Vista+ ;-)

BTW Thunderbird has now moved the menus into the caption, to gain vertical space, see screenshot below. I wonder how they do that with Aero, but can't test it yet :(
Title: Re: problems with a window
Post by: Gunther on September 01, 2014, 04:32:52 AM
Jochen,

Quote from: jj2007 on August 31, 2014, 09:53:44 PM
BTW Thunderbird has now moved the menus into the caption, to gain vertical space, see screenshot below. I wonder how they do that with Aero, but can't test it yet :(

that's interesting. I thought that Thunderbird comes from Apple.

Gunther
Title: Re: problems with a window
Post by: dedndave on September 01, 2014, 04:49:36 AM
Thunderbird is an e-mail client from Mozilla - the same group that authors FireFox

JJ - i seem to recall that Bill Cravener had an example of how to put stuff in the caption
it may not be in the examples folder - search the old forum, maybe ?
Title: Re: problems with a window
Post by: Gunther on September 01, 2014, 05:31:30 AM
Dave,

Quote from: dedndave on September 01, 2014, 04:49:36 AM
Thunderbird is an e-mail client from Mozilla - the same group that authors FireFox

Thanks.  :t

Gunther
Title: Re: problems with a window
Post by: jj2007 on September 01, 2014, 06:14:17 AM
Quote from: dedndave on September 01, 2014, 04:49:36 AMJJ - i seem to recall that Bill Cravener had an example of how to put stuff in the caption

There are many examples using GetWindowDC, but it won't work with DWM/Aero, that's why I reverted to this exotic solution.