8

我有一些关于覆盖 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);
}

你有什么建议吗?是否有最好的情况,还是很大程度上取决于我处理的消息?

4

2 回答 2

17

WndProc 和 DefaultWndProc 之间到底有什么区别?

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

Control.WndProc() 的 MSDN 库文章否则有助于消除疑问,它规定如果您覆盖该方法,那么您应该始终使用 base.WndProc()。

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

专注于短语的“随时”部分,这很少是正确的做法。您几乎应该总是调用 SendMessage() 来向窗口发送消息。仅当您有意绕过自定义 WndProc() 方法时,才应使用调用 DefWndProc() 。这是罕见的。

在我的重写方法中在哪里调用 base.WndProc?

这取决于你想要完成什么。有以下三种基本策略:

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

究竟哪个项目符号是合适的,需要深入了解消息的正常处理方式。这完全取决于您从中获得的特定控件和特定消息,因此不可能提供通用指导。然而,弄错它几乎总是很容易诊断。

于 2013-10-27T12:37:43.353 回答
0

这取决于您处理哪些消息。base.WndProc 将继续进行。因此,您可以对每条消息进行任何预处理或后处理。

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

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

WndProc 完成后,将调用 DefWndProc。

于 2013-10-22T23:11:29.810 回答