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 について話していると仮定します。この 2 つの違いはほとんどないため、この質問に答えるのは困難です。DefWndProc() メソッドは、C などの言語でコードを記述する方法に対応しており、base.WndProc() を呼び出す機能は .NET に固有のものです。それらは同じことを行い、ウィンドウの元のウィンドウ プロシージャを呼び出しますが、わずかな違いがあります。base.WndProc() メソッドはメッセージを完全に変更できますが、DefWndProc() は Message.Result 値のみを変更できます。これが問題になるケースは考えられません。

それ以外の場合、Control.WndProc() に関する MSDN ライブラリの記事は、疑いを取り除くのに役立ちます。メソッドをオーバーライドする場合は、常に base.WndProc() を使用する必要があると規定しています。

いつでも呼び出すことができる DefaultWndProc とは何ですか?

フレーズの「いつでも」の部分に注目すると、これが正しいことはめったにありません。メッセージをウィンドウに送信するには、ほとんどの場合、SendMessage() をピンボークする必要があります。DefWndProc() の呼び出しは、意図的にカスタム WndProc() メソッドをバイパスしたい場合にのみ使用してください。それはまれです。

そして、オーバーライドされたメソッドで base.WndProc を呼び出す場所は?

それはあなたが達成したいことに依存します。基本的な戦略は次の 3 つです。

  • 引数を見て、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 はメッセージをウィンドウに送信するため、OS との既定の対話が行われます。

WndProc が完了すると、DefWndProc が呼び出されます。

于 2013-10-22T23:11:29.810 に答える