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

Ray*_*Ray 5 c# overriding 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);
}
Run Code Online (Sandbox Code Playgroud)

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

Han*_*ant 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情况下是另外一个,如果你需要画上什么用默认的窗口过程画那么你必须做这种方式.
  • 根本不调用base.WndProc().如果您完全自定义消息处理并且不想使用默认行为,则适用.过滤消息非常常见,这就是KeyPressEventArgs.Handled的工作原理.

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

  • 关于"你几乎应该总是将SendMessage()发送消息以向窗口发送消息.",为什么?难道你不想避免处理pinvoke,而是利用`Control.DefWndProc()`是一个围绕pinvoke的瘦包装这一事实,根据运行时,它甚至可能不会调用本机`SendMessage ()`函数还是使用DLL? (2认同)