テクニカル ノート 62: Windows コントロールへのメッセージ リフレクション (メッセージ返送)
[!メモ]
次のテクニカル ノートは、最初にオンライン ドキュメントの一部とされてから更新されていません。結果として、一部のプロシージャおよびトピックが最新でないか、不正になります。最新の情報について、オンライン ドキュメントのキーワードで関係のあるトピックを検索することをお勧めします。
このテクニカル ノートは、リフレクション メッセージ、 MFC 4.0 の新機能について説明します。また、メッセージ リフレクションを使用する簡単な再利用可能なコントロールを作成する手順を示します。
このテクニカル ノートは、 ActiveX コントロールに適用すると、リフレクション メッセージについては説明しません (以前の OLE コントロール)。 技術情報 ActiveX コントロール: サブクラス化は、 Windows 制御しますを参照してください。
リフレクション メッセージは何ですか。
ウィンドウ コントロールには親ウィンドウに通知メッセージを送信します。たとえば、多くのコントロールには親が親コントロールの背景を描画するブラシを指定できるように、コントロールの色の通知メッセージ (バリアントのWM_CTLCOLOR または 1 個)送信します。
のウィンドウとバージョン 4.0 以前の MFC、親ウィンドウ、ダイアログ ボックスは、これらのメッセージを処理する必要があります。これは、メッセージを処理するコードが親ウィンドウ クラスにある必要があり、そのメッセージを処理する必要があるすべてのクラスで繰り返す必要があることを意味します。上記の場合、カスタム背景の望まれたコントロールがコントロールの色の通知メッセージを処理すると、すべてのダイアログ ボックス。独自の背景色を処理するコントロール クラスを書き込むことができるコードを再利用する方が簡単です。
MFC 4.0 では、古い機能は引き続き動作します。親ウィンドウに通知メッセージを処理できます。また、 MFC 4.0 「は」リフレクション メッセージをそのいう機能を提供することで再利用を割り当てと子コントロールのウィンドウまたは親ウィンドウ、または両方で処理されるこれらの通知メッセージ容易になります。コントロールの背景色の例では、 WM_CTLCOLOR のリフレクション メッセージの —親に依存しないですべて処理して独自の背景色を設定するコントロール クラスを作成できます。(リフレクション メッセージがウィンドウに、 MFC ではなく、親ウィンドウのクラス実装されるため、リフレクション メッセージの CWnd から操作するために取得する必要があります。)
MFC の古いバージョンがオーナー描画リスト ボックス (WM_DRAWITEM提供して、メッセージ リフレクションと同様のものをなど)のメッセージなどの一部のメッセージに仮想関数を、しました。新しいメッセージ リフレクションの機能は、汎化され、一貫性があります。
リフレクション メッセージは 4.0 の前に MFC のバージョン用に記述されたコードと下位互換性があります。
特定のメッセージ、またはメッセージの範囲のハンドラーを、親ウィンドウのクラスで渡す場合、同じメッセージのリフレクション メッセージ ハンドラーが用意されていましたダイヤルするハンドラーを独自の基本クラスのハンドラー関数をオーバーライドします。たとえば、ダイアログ ボックス クラスの WM_CTLCOLOR を処理する場合、処理はリフレクション メッセージ ハンドラーをオーバーライドします。
、親ウィンドウのクラスでは、 WM_NOTIFY のメッセージの WM_NOTIFY の特定のメッセージまたは範囲のハンドラーを指定した場合、ハンドラーはメッセージを送信する子コントロールが **ON_NOTIFY_REFLECT()**でリフレクション メッセージ ハンドラーがない場合にのみ呼び出されます。メッセージ マップで ON_NOTIFY_REFLECT_EX() を使用して親ウィンドウがメッセージを処理するようにする、メッセージ ハンドラーは可能性がある場合とない場合があります。ハンドラーが FALSEを返す場合、メッセージは親によって TRUE を返す呼び出しは親が例外を処理することを許可しないが、処理されます。リフレクション メッセージが通知メッセージの前に処理されることに注意してください。
WM_NOTIFY のメッセージが送信されると、コントロールは例外を処理する最初の可能性が提供されます。そのほかのリフレクション メッセージがある場合、親ウィンドウに扱う最初のと、コントロールはリフレクション メッセージを受け取ります。そのためには、コントロールのクラスのメッセージ マップでハンドラー関数と適切なエントリが必要です。
リフレクション メッセージのメッセージマップのマクロは、通常の通知は少し異なります: これは、通常の名前に追加する _REFLECT があります。たとえば、親 WM_NOTIFY のメッセージを処理するために、親のメッセージ マップ マクロで ON_NOTIFY を使用します。子コントロールのリフレクション メッセージを処理するために、子コントロールのメッセージ マップで ON_NOTIFY_REFLECT のマクロを使用します。場合によっては、パラメーターが異なっているか。ClassWizard は、のメッセージマップ エントリを追加し、適切なパラメーターをスケルトン関数の実装に付与できることに注意してください。
WM_NOTIFY の新しいメッセージについては、 TN061: ON_NOTIFY と WM_NOTIFY のメッセージ を参照してください。
リフレクション メッセージのメッセージマップ エントリとハンドラー関数プロトタイプ
リフレクション コントロール通知メッセージを処理するには、次の表に示しますメッセージマップのマクロや関数プロトタイプを使用します。
ClassWizard は通常、これらのメッセージマップ エントリを追加し、スケルトン関数の実装を提供できます。リフレクション メッセージのハンドラーを定義する方法の詳細については リフレクション メッセージのメッセージ ハンドラーの定義 を参照してください。
メッセージの名前が反映されたマクロ名に変換するには、 ON_ を追加し、 _REFLECTを追加します。たとえば、 WM_CTLCOLOR は ON_WM_CTLCOLOR_REFLECTになります。(どのメッセージが反映できるか確認する次の表のマクロ エントリのカウンターを変換します)。
上記の規則の 3 種類の例外は次のとおりです。:
WM_COMMAND の通知のマクロは ON_CONTROL_REFLECTです。
WM_NOTIFY のリフレクションのマクロは ON_NOTIFY_REFLECTです。
ON_UPDATE_COMMAND_UI のリフレクションのマクロは ON_UPDATE_COMMAND_UI_REFLECTです。
上記の特殊なケースにおいては、ハンドラー メンバー関数の名前を指定します。そのほかの場合は、ハンドラー関数に対する既定の名前を使用します。
関数のパラメーターと戻り値の意味は関数名の下については、 On の関数名は追加しました。たとえば、 CtlColor は OnCtlColorで説明します。一部のリフレクション メッセージ ハンドラーは親ウィンドウに似たハンドラーよりも少ない数のパラメーターが必要です。、ドキュメントの正式なパラメーターの名前、次の表の名前を一致させる必要があります。
マップ エントリ |
関数プロトタイプ |
---|---|
ON_CONTROL_REFLECT( wNotifyCode, memberFxn ) |
afx_msg void memberFxn ( ); |
ON_NOTIFY_REFLECT( wNotifyCode, memberFxn ) |
afx_msg void memberFxn ( NMHDR * pNotifyStruct, LRESULT* の結果); |
ON_UPDATE_COMMAND_UI_REFLECT( memberFxn ) |
afx_msg void memberFxn ( CCmdUI* pCmdUI); |
ON_WM_CTLCOLOR_REFLECT () |
afx_msg HBRUSH CtlColor ( CDC* pDC, UINT nCtlColor); |
ON_WM_DRAWITEM_REFLECT () |
afx_msg void DrawItem ( LPDRAWITEMSTRUCT lpDrawItemStruct); |
ON_WM_MEASUREITEM_REFLECT () |
afx_msg void MeasureItem ( LPMEASUREITEMSTRUCT lpMeasureItemStruct); |
ON_WM_DELETEITEM_REFLECT () |
afx_msg void DeleteItem ( LPDELETEITEMSTRUCT lpDeleteItemStruct); |
ON_WM_COMPAREITEM_REFLECT () |
afx_msg int CompareItem ( LPCOMPAREITEMSTRUCT lpCompareItemStruct); |
ON_WM_CHARTOITEM_REFLECT () |
afx_msg int CharToItem ( UINT nKey, UINT nIndex); |
ON_WM_VKEYTOITEM_REFLECT () |
afx_msg int VKeyToItem ( UINT nKey, UINT nIndex); |
ON_WM_HSCROLL_REFLECT () |
afx_msg void HScroll ( UINT nSBCode, UINT nPos); |
ON_WM_VSCROLL_REFLECT () |
afx_msg void VScroll ( UINT nSBCode, UINT nPos); |
ON_WM_PARENTNOTIFY_REFLECT () |
afx_msg void ParentNotify ( UINT message, LPARAM lParam); |
ON_NOTIFY_REFLECT と ON_CONTROL_REFLECT のマクロに複数のオブジェクト (コントロールや親などの特定のメッセージを処理するためにするバリエーションがあります。
マップ エントリ |
関数プロトタイプ |
---|---|
ON_NOTIFY_REFLECT_EX( wNotifyCode, memberFxn ) |
afx_msg BOOL memberFxn ( NMHDR * pNotifyStruct, LRESULT* の結果); |
ON_CONTROL_REFLECT_EX( wNotifyCode, memberFxn ) |
afx_msg BOOL memberFxn ( ); |
リフレクション メッセージの処理: 再利用可能なコントロールの例
この例では CYellowEditと呼ばれる再利用可能なコントロールを作成します。コントロールは標準エディット コントロールと同じように動作しますが、黄色い背景に黒のテキストが表示されます。CYellowEdit のコントロールが異なる色を表示できるメンバー関数を追加したりできます。
再利用可能なコントロールを作成する例を試みます。
既存のアプリケーションに新しいダイアログ ボックスを作成します。詳細については、 ダイアログ エディター のトピックを参照してください。
再利用可能なコントロールを開発するアプリケーションが必要です。使用する既存のアプリケーションがない場合は、 AppWizard を使用してダイアログベースのアプリケーションを作成します。
Visual C++ に読み込まれるプロジェクトが CEditに基づいて CYellowEdit という名前の新しいクラスを作成するには、 ClassWizard を使用します。
CYellowEdit のクラスに 3 人の変数を追加します。最初の 2 つがテキストの色と背景色を保持する COLORREF の変数です。番目は背景を描画するブラシを保留 CBrush のオブジェクトです。CBrush のオブジェクトは CYellowEdit のコントロールが破棄されると、ブラシを可能にし、その後は、それを一度作成し、ブラシを参照して自動的に破棄することができます。
コンストラクターを記述してメンバー変数を初期化して次のよう:
CYellowEdit::CYellowEdit() { m_clrText = RGB( 0, 0, 0 ); m_clrBkgnd = RGB( 255, 255, 0 ); m_brBkgnd.CreateSolidBrush( m_clrBkgnd ); }
ClassWizard を使用して、 CYellowEdit のクラスに WM_CTLCOLOR のリフレクション メッセージのハンドラーを追加します。メッセージが反映されていることを処理できるメッセージの一覧のメッセージの前に等号が示すことに注意してください。これは リフレクション メッセージのメッセージ ハンドラーの定義で説明します。
ClassWizard では以下のメッセージマップ マクロとスケルトン関数を追加します:
ON_WM_CTLCOLOR_REFLECT() // Note: other code will be in between.... HBRUSH CYellowEdit::CtlColor(CDC* pDC, UINT nCtlColor) { // TODO: Change any attributes of the DC here // TODO: Return a non-NULL brush if the // parent's handler should not be called return NULL; }
次のコードでは、関数本体を置き換えます。コードは、コントロールの他のテキストの色、テキストの背景色と背景色を指定します。
pDC->SetTextColor( m_clrText ); // text pDC->SetBkColor( m_clrBkgnd ); // text bkgnd return m_brBkgnd; // ctl bkgnd
エディット コントロールをダイアログ ボックスで作成し、メンバー変数にエディット コントロールをダブル クリックして接続します。コントロール キーを押している間。追加のメンバー変数] ダイアログ ボックスで、変数名の受け付け、カテゴリの 「コントロール」を、変数の型の 「」 CYellowEdit 選択します。ダイアログ ボックスのタブ オーダーを設定することを未完了のください。また、ダイアログ ボックスのヘッダー ファイルに CYellowEdit のコントロールのヘッダー ファイルをインクルードしてください。
アプリケーションをビルドして実行します。エディット コントロールに黄色い背景があります。