Sends the specified message to the default window procedure.
参数说明:m:The Windows Message to process.
protected virtual void DefWndProc(ref Message m)
备注:
For more information about processing Windows messages, see the WindowProc function.
Processes Windows messages.
参数说明:m:The Windows Message to process.
protected virtual void WndProc(ref Message m)
备注:
All messages are sent to the WndProc method after getting filtered through the PreProcessMessage method.
在PreProcessMessage方法对消息进行筛选之后,所有的消息都发送到了WndProc方法
The WndProc method corresponds exactly to the Windows WindowProc function. For more information about processing Windows messages, see the WindowProc function.
WndProc 方法对应于windows系统中的WindowProc 函数
Notes to Inheritors
Inheriting controls should call the base class's WndProc method to process any messages that they do not handle.
如果继承自Control的类,在override的WndProc方法中有没有处理的消息,那么就需要调用base.WndProc 方法来处理消息
http://stackoverflow.com/questions/19529878/where-to-call-base-wndproc-or-base-defwndproc
What exactly is the difference between WndProc and DefaultWndProc?
There is no method named "DefaultWndProc", I'll assume you are talking about DefWndProc. This question is difficult to answer since there is very little difference between the two. The DefWndProc() method corresponds to the way you write code in a language like C, the ability to call base.WndProc() is specific to .NET. They do the same thing, call the original window procedure of the window but with a small difference. The base.WndProc() method is capable of altering the message completely, DefWndProc() can only alter the Message.Result value. I can't think of a case where this matters.
The MSDN Library article for Control.WndProc() otherwise helps to remove the doubt, it stipulates that if you override the method then you should always use base.WndProc().
what is DefaultWndProc for, which I can call anytime?
Focusing on the "anytime" part of the phrase, this is very rarely the correct thing to do. You should almost always pinvoke SendMessage() to send a message to a window. Calling DefWndProc() should only ever be used if you intentionally want to bypass a custom WndProc() method. That is rare.
And where to call base.WndProc in my overridden method?
That depends on what you want to accomplish. There are three basic strategies:
- Look at the
m
argument and implement your own custom behavior, then call base.WndProc(). This is the most common way and ought to be your default choice. - Call base.WndProc() first, then alter the
m
argument or execute code to customize the default processing of the message. This is appropriate for certain kind of messages, WM_NCHITTEST is the best example. Your WM_PAINT case is another one, if you need to paint on top of what was painted by the default window procedure then you have to do it this way. - Not call base.WndProc() at all. Appropriate if you completely customize the message handling and don't want to use the default behavior. Very common for filtering message, this is how KeyPressEventArgs.Handled works for example.
Exactly which bullet is appropriate requires insight in the way the message gets handled normally. This entirely depends on the specific control you derive from and the specific message so its impossible to give generic guidance. Getting it wrong however is almost always easy to diagnose.
http://www.cnblogs.com/08shiyan/archive/2012/01/06/2313864.html
谈到Winform的消息处理,多数时候是通过事件处理程序进行的,但当没有对应的事件时通常的做法是声明DefWndProc或者WndProc或者IMessageFilter
所有的有用户界面的控件都继承自Control,这种方式需要创建对应控件的派生类,不能统一对各个窗口的消息进行拦截处理,因为从根本上说这两者都是Windows的窗口过程,只有收到针对本窗口自身的消息。
通过复习Windows的消息处理机制,对这三者的关系可以有更好的理解。
应用程序的消息来自于系统消息队列,被应用程序的主程序中的消息循环所处理。
这个消息循环从应用程序的消息队列中取出消息,进行预处理,然后派发到消息对应的窗口过程,窗口过程在被调用后根据消息的类型进行相应的处理,有些可以由Windows默认处理的消息就调用Windows的DefWindowProc。
这里的WndProc就是对应控件窗口的窗口过程,而DefWndProc会被WndProc调用,处理那些WndProc中未处理的消息(包括WndProc未吞掉的),因此DefWndProc收到的消息会比WndProc少。
IMessageFilter的调用发生在应用程序的消息循环中,是消息预处理的一部分,所以它收到的消息是更全的(除了直接发送到窗口过程不进入消息队列的那些消息)。
三者都有一个共同的参数类型Message,它封装了Windows消息。同时还包括一个很方便的ToString方法,可以将Message对象转换成包括消息名称(WM_XXX)在内的字符串,
通过Reflector可以看到实现是通过一个内部类MessageDecoder,使用一个很长的switch语句将消息ID转换成消息名称。