11

I'm currently writing my own mini visual framework to wrap pure WinAPI in classes.

Currently the process of analyzing messages looks as follows:

  • static Application::Run has a message loop; it gets new message and dispatches it to apropriate WndProc.

  • All windows I create are created from the same class (in terms of WinAPI), so the same WndProc is being called. Actually, it's a static FormAPI::WndProc method. This one checks, which window the message refers to and calls its WndProc.

  • Form::WndProc method is called, which analyzes message. Suppose, that it's a WM_MOUSEMOVE. It calls ProcessMouseMove and then DefWindowProc. Remember this point as [1].

  • private Form::ProcessMouseMove gets the actual data from the message (eg. x, y, shift state), converts it into usable data and calls protected Form::OnMouseMove.

  • Finally, protected OnMouseMove checks, whether event handler is set (that is, std::function<void(Form *, int, int, ShiftState)> ) and if so, it calls the handler. Otherwise it does nothing.

My concern is about calling DefWindowProc. It may seem, that its simply "do the default behavior for me", but sometimes it actually does some critical stuff. For instance, disabling WM_LBTNDOWN by not calling DefWindowProc will result in inability to close window by clicking the [X] button.

On the other hand, sometimes I don't want to call DefWindowProc. For instance, if WM_CLOSE comes, I may decide not to close application. DefWindowProc in this case calls DestroyWindow.

My question is: should I call the DefWindowProc or not? If so, always or only sometimes?

Spook
  • 25,318
  • 18
  • 90
  • 167

2 Answers2

17

You've got three choices when deciding how to handle a message:

  • Not calling DefWindowProc(). Appropriate when you want to completely customize the way the message is handled and do not want the default implementation. WM_COMMAND and WM_PAINT are typical examples.

  • Do something custom, then calling DefWindowProc(). Appropriate when you like or need the default implementation. WM_CLOSE is a typical example.

  • First call DefWindowProc(), then altering the result if appropriate. A typical example is WM_NCHITTEST

There is no golden rule to select the appropriate choice, it depends a great deal on the specific message and the specific default handling for the window. Note that this may not be the documented default handling if you are subclassing a window. Getting it wrong is however generally easy to diagnose.

Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
2

It seems, that I've answered my question simply by asking it. I presented two cases:

  • WM_LBTNDOWN when DefWindowProc has to be called - otherwise window won't work properly;
  • WM_CLOSE, when - depending on event handler - DefWindowProc must not be called - otherwise it'll break the framework's logic.

The answer is then: it depends on kind of message. I have to read carefully, how DefWindowProc works in every case and act appropriately.

Spook
  • 25,318
  • 18
  • 90
  • 167
  • 3
    It comes down to "has it been handled or not". My window handle wrapper has a handled flag, which when set to true, causes it to exit rather than call `DefWindowProc`. – Deanna Jan 24 '13 at 12:48
  • That depends, again. If you use `handled` in - say - `WM_LBTNDOWN`, you give an opportunity to event handler to lock user from closing window. In other words, event handler has to be responsible for deciding, whether to call `DefWindowProc` or not. It is doable, but I wouldn't call that comfortable... unless I misunderstood your concept. – Spook Jan 24 '13 at 13:28
  • Well, the event handler is specific to every message. By default, it should be called, but then the handle can block this if required. I assume you also have specific code in your library for each message so you can override this if a certain message never needs to be passed. – Deanna Jan 24 '13 at 14:12
  • I consider it should always be called unless you want to specifically prevent the default behavior. Which is basically what you already said. – jcoder Jan 24 '13 at 14:33