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

问题描述 投票:0回答:2

我有一些关于覆盖 Windows

WndProc
/
Form
NativeWindow
方法的问题。

WndProc
DefWndProc
到底有什么区别?我只能覆盖
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);
            break;
        }
    }
    // 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# winforms winapi pinvoke
2个回答
19
投票

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 的工作原理。
  • 究竟哪种项目符号合适需要深入了解消息的正常处理方式。这完全取决于您从中派生的特定控件和特定消息,因此不可能提供通用指导。然而,错误几乎总是很容易诊断。


1
投票

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

WndProc 和 DefWndProc 之间的区别在于,WndProc 处理消息(当您重写它(包括您自己的消息)时),而 DefWndProc 将消息发送到窗口,以便它执行与操作系统的默认交互。

WndProc 完成后,DefWndProc 被调用。

© www.soinside.com 2019 - 2024. All rights reserved.