【问题标题】:Where to call base.WndProc() or base.DefWndProc()?在哪里调用 base.WndProc() 或 base.DefWndProc()?
【发布时间】:2013-11-01 00:46:26
【问题描述】:

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

你有什么推荐的?是否存在最佳情况,还是很大程度上取决于我处理的消息?

【问题讨论】:

    标签: c# overriding base wndproc


    【解决方案1】:

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

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

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

    WndProc 完成后,将调用 DefWndProc。

    【讨论】:

      【解决方案2】:

      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 案例是另一种情况,如果您需要在默认窗口程序绘制的 top 上进行绘制,那么您必须这样做。
      • 根本不调用 base.WndProc()。如果您完全自定义消息处理并且不想使用默认行为,则适用。过滤消息非常常见,这就是 KeyPressEventArgs.Handled 的工作原理。

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

      【讨论】:

      • 关于“你应该几乎总是 pinvoke SendMessage() 来向窗口发送消息。”,为什么?您是否不想避免处理 pinvoke,而是利用 Control.DefWndProc() 是 pinvoke 的薄包装器这一事实,根据运行时,它甚至可能不会调用本机 SendMessage() 函数或使用DLL?
      猜你喜欢
      • 2010-11-18
      • 1970-01-01
      • 2013-02-16
      • 2015-08-11
      • 2019-11-06
      • 2012-03-13
      • 2016-10-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多