在哪里调用base.WndProc()或base.DefWndProc()?

时间:2013-10-22 23:02:13

标签: c# override base wndproc

我有一些关于覆盖Windows窗体/ NativeWindow的WndProc方法的问题。

WndProc和DefWndProc之间究竟有什么区别(编辑:之前我认为它叫做“DefaultWndProc”)?我只能覆盖WndProc,但是什么是DefWndProc,我可以随时调用它?

在我的重写方法中调用base.WndProc的位置?或者我应该调用DefWndProc吗?我想到了以下立场:

protected override void WndProc(ref Message m)
{
    // 1st: I call the base handler at the start, in front of my handling.
    // Are there disadvantages here?
    base.WndProc(ref m);

    switch (m.Msg)
    {
        case (int)WindowsMessage.Paint:
            // 2nd: Do whatever you want to do now. I could also place
            // base.WndProc for each message manually here, at a point I
            // can control myself. It makes the method a little messy
            // since I have several base calls for each message I handle.
            base.WndProc(ref m);
            break;
        default:
            // 3rd: If I put it here, it never gets called for messages I
            // have handled. I think it is disastrous for specific
            // messages which need additional handling of the system.
            base.WndProc(ref m);
        }
    }
    // 4th: Or put it here. It gets called even after messages I have
    // already handled. If I made some drawings in WM_PAINT, doesn't
    // calling the system's default method draw "over" my paintings?
    // And is this really needed?
    base.WndProc(ref m);
}

你推荐什么?是否存在最佳情况或是否严重依赖于我处理的消息?

2 个答案:

答案 0 :(得分:14)

  

WndProc和DefaultWndProc之间究竟有什么区别?

没有名为“DefaultWndProc”的方法,我假设你在谈论DefWndProc。这个问题很难回答,因为两者之间差别很小。 DefWndProc()方法对应于用C语言编写代码的方式,调用base.WndProc()的能力特定于.NET。他们做同样的事情,调用窗口的原始窗口过程,但有一点点差异。 base.WndProc()方法能够完全改变消息,DefWndProc()只能改变Message.Result值。我无法想到一个重要的案例。

对于Control.WndProc()的MSDN Library文章否则有助于消除疑问,它规定如果重写该方法,则应始终使用base.WndProc()。

  

什么是DefaultWndProc,我可以随时调用它?

专注于短语的“随时”部分,这很少是正确的事情。你应该几乎总是pinvoke SendMessage()来发送消息到窗口。只有在故意想要绕过自定义WndProc()方法时才应该使用调用DefWndProc()。这很少见。

  

在我重写的方法中调用base.WndProc的位置?

这取决于你想要完成的事情。有三种基本策略:

  • 查看m参数并实现自己的自定义行为,然后调用base.WndProc()。这是最常见的方式,应该是您的默认选择。
  • 首先调用base.WndProc(),然后更改m参数或执行代码以自定义消息的默认处理。这适用于某些类型的消息,WM_NCHITTEST是最好的例子。你的WM_PAINT案例是另一个案例,如果你需要在默认窗口过程绘制的 top 上绘画,那么你必须这样做。
  • 根本不调用base.WndProc()。如果您完全自定义消息处理并且不想使用默认行为,则适用。过滤消息非常常见,这就是KeyPressEventArgs.Handled的工作原理。

究竟哪个子弹是合适的,需要深入了解正常处理消息的方式。这完全取决于您从中获得的具体控制和具体信息,因此无法给出通用指导。然而,错误的诊断几乎总是很容易。

答案 1 :(得分:0)

这取决于您处理的消息。 base.WndProc继续沿着它前进。因此,您可以对每封邮件进行任何预处理或后期处理。

我使用它的方式是将它放在最后,只要我不想进行任何进一步处理就返回该函数。

WndProc和DefWndProc之间的区别在于WndProc处理消息(当你覆盖它时包括你的消息),而DefWndProc将消息发送到窗口,因此它与操作系统进行默认交互。

WndProc完成后,调用DefWndProc。