4

標準のウィンドウ コントロール ("EDIT"コントロールなど) が作成されると、それWNDPROCはウィンドウ クラスの一部として定義されます (つまり、ウィンドウを表示し、編集コントロールとして動作させるように設計され"EDIT"た固有のものがあります)。WNDPROC

MFC を使用すると、ウィンドウ コントロールCEditの特殊なメッセージのラッパーなどのラッパー クラスを介して、このようなコントロールと対話できます。"EDIT"

MFC ではさらに、"EDIT"ウィンドウのインスタンスを CEdit の C++ サブクラス、たとえば aにバインドできます。ここでは、およびCMyEditの継承された仮想関数をオーバーライドできます。また、メッセージ テーブルを定義して、ウィンドウ インスタンス自体に送信されたメッセージにアクセスしたりオーバーライドしたりできます。 .CEditCWnd

現在のメッセージ引数で this->DefWndProc を呼び出すCWnd::Default()があります。WNDPROCこれは、関連付けられている HWNDを検索しているようです。では、これは正しい答えですか? DefWndProc() (または同様に Default()) を呼び出します。どちらがWNDPROCウィンドウ コントロールに渡しますか?

明らかに、これは、メッセージを処理しなかったことを示すために FALSE を返すことができる他のメッセージ テーブル ハンドラーとは異なります。MFC は、クラス継承階層を上って、このメッセージの次のメッセージ ハンドラーにメッセージを自動的にルーティングします。 、ネイティブによって処理される Default() にWNDPROC?

WM_SETTEXT などの任意のメッセージ ハンドラーを定義する場合、このメッセージを に渡す正しい方法は何"EDIT" WNDPROCですか?

また、処理のためにメッセージをスーパークラス (C++ クラス階層) に渡す方法があるかどうかも知りたいです。多くの OnXXX スタイル ハンドラーにはそうする方法がありますが、ON_MESSAGE ハンドラーで機能するメカニズムはありますか?

class CDynamicMenuControlEdit : public CEdit  
{
    ...
    LRESULT OnSetText(WPARAM wParam, LPARAM lParam);
    ...
}

BEGIN_MESSAGE_MAP(CDynamicMenuControlEdit, CEdit)
    ...
    ON_MESSAGE(WM_SETTEXT, OnSetText)
    ...
END_MESSAGE_MAP()

LRESULT CDynamicMenuControlEdit::OnSetText(
    WPARAM wParam,          // not used; must be zero
    LPARAM lParam           // window-text string (LPCTSTR)
)
{
    if (m_bHasFocus)
    {
        // do normal thing 
        // !!! THIS IS MY QUESTION: IS THIS CALLING EDIT's WNDPROC, or ::DefWinProc()? !!!
        return DefWindowProc(WM_SETTEXT, wParam, lParam);
    }
    ...
}

明確化

C++ レベルで複数の MFC サブクラスを持つことができます -

したがって、C は B を継承します。ここで、A は MFC クラスです (例: CEdit)。

それらのそれぞれは、MFC メッセージ テーブルを持つことができますBEGIN_MESSAGE_MAP。つまりEND_MESSAGE_MAP、それぞれ任意の Windows メッセージのハンドラーを持つことができます。たとえばWM_MESSAGE(WM_SETTEXT, OnSetText)、そのOnSetTextメンバーは必ずしも仮想ではなく、単なる静的メンバーです (各 MFC サブクラスはそのメッセージを次のようにルーティングできます)。任意の方法)。

私の質問は、WM_MESSAGEディスパッチ エントリには戻り値がないため、実際の Windows 'EDIT' クラスの wndproc に戻す前に、MFC が MFC ディスパッチ テーブルを C から B、A に移動できるようにするにはどうすればよいですか?

それとも、そのようなすべてのエントリは、MFC 設計レベルで実行されないように意図されていますか? つまり、最もサブクラス化されたレイヤーのディスパッチャーだけが呼び出されるように意図されていますか? 継承されたメンバーを利用したい場合は、手動でその呼び出しを行う必要があります.MFCには、これのための特定の汎用構造がありませんか?

4

2 に答える 2

4

呼び出すDefault()と、メッセージに応答して発生したはずの「通常の」処理が発生します。あなたが何を達成しようとしているのか完全にはわかりませんが、電話をかけるDefault()ことがあなたがやりたいことのように思えます。

ハンドラー内のWindowsメッセージからのCWndハンドラー(およびなどから派生したクラスからCWndのハンドラーCEdit)の多くを見ると、それらがを呼び出すことがわかりますDefault()

賢明な言葉ですDefault()が、実際には元のメッセージが持っていたパラメータを使用します-それらを変更することはできません。

于 2013-03-06T17:23:19.967 に答える
2

あなたはそれを正しくやっています。CWnd :: DefWindowProc()は、サブクラス化したWINDOWPROCを使用し、EDITウィンドウのウィンドウプロシージャを呼び出します。

于 2013-03-06T17:22:16.743 に答える