News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests

Main Menu

Re: problems with a window

Started by jj2007, August 26, 2014, 09:26:01 AM

Previous topic - Next topic

jj2007

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.

dedndave

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

qWord

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.
MREAL macros - when you need floating point arithmetic while assembling!

qWord

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?
MREAL macros - when you need floating point arithmetic while assembling!

jj2007

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)

Tedd

[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.
Potato2

jj2007

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.

Tedd

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.
Potato2

hutch--

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.

jj2007

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.

qWord

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.
MREAL macros - when you need floating point arithmetic while assembling!

jj2007

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"?

qWord

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.
MREAL macros - when you need floating point arithmetic while assembling!

dedndave

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:

jj2007

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)
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.