テクニカル ノート 61: ON_NOTIFY メッセージと WM_NOTIFY メッセージ
[!メモ]
次のテクニカル ノートは、最初にオンライン ドキュメントの一部とされてから更新されていません。結果として、一部のプロシージャおよびトピックが最新でないか、不正になります。最新の情報について、オンライン ドキュメントのキーワードで関係のあるトピックを検索することをお勧めします。
このテクニカル ノートは WM_NOTIFY の新しいメッセージで背景情報を提供し、 MFC アプリケーションで WM_NOTIFY のメッセージを処理する推奨される (およびほとんどの一般的な方法について説明します。
Windows 3.x の通知メッセージ
Windows 3.x では、コントロールは親にメッセージを送信することによってコンテンツのマウス クリックなどのイベントの親を、変更の選択とコントロールの背景に描画通知します。単純な通知は wParam にパックされる通知コード ( BN_CLICKEDなど)やコントロールの ID と lParamコントロールのハンドルを持つ WM_COMMAND の特別なメッセージとして送信されます。追加データを渡す方法がないことを lParam が完了したことを wParam からことに注意して、これらのメッセージは、単純な通知でのみ実行できます。たとえば、 BN_CLICKED の通知に、ボタンがクリックされたときにマウス カーソルの位置に関する情報を送信する方法はありません。
Windows 3.x のコントロールで追加のデータを含む通知メッセージを送信する必要がある場合に、さまざまな目的のメッセージを、 WM_CTLCOLORが、 WM_VSCROLL、 WM_HSCROLL、 WM_DRAWITEM、 WM_MEASUREITEM、 WM_COMPAREITEM、 WM_DELETEITEM、 WM_CHARTOITEM、 WM_VKEYTOITEMなど使用します。これらのメッセージは、クッキーを送信するコントロールに対して反映できます。詳細については、 TN062: ウィンドウ コントロールのリフレクション メッセージを参照してください。
Win32 の通知メッセージ
Windows 3.1 にあったコントロールの場合、 Windows 3.x. で使用した通知メッセージから Win32 API の使用。ただし、 Win32 には、いくつかの高度な Windows 3.x. でサポートされるメソッドへの複雑なコントロール追加します。多くの場合、通知メッセージである追加のデータを送信するこれらのコントロールは。追加データを必要とする新しい各通知の WM_* の新しいメッセージを追加するのではなく、 Win32 API のデザイナーは、 1 種類のメッセージ、標準化されたメソッドの追加データの量を渡すことができる WM_NOTIFYを追加することを選択しました。
WM_NOTIFY のメッセージが wParam に送信するコントロールの ID をメッセージと構造に lParamにポインターが含まれます。この構造体は NMHDR の構造体または最初のメンバーとして NMHDR の構造体よりも大きな構造体です。使用できるように、キャストまたは NMHDR のメンバーが 1 番目のであるため、この構造体へのポインターは NMHDR へのポインター、またはより大きな構造体へのポインターとしてことができることに注意してください。
ほとんどの場合、より大きな構造体をポイントし、それを使用するときにキャストする必要があります。いくつかの通知だけでは、共通の (名前が **NM_**から開始して)通知とツール ヒント コントロールの TTN_SHOW と TTN_POP の通知など、実際に使用される NMHDR の構造体です。
NMHDR の構造または最初のメンバーに送信するコントロールのハンドルと ID をメッセージと通知のコードが含まれます ( TTN_SHOWなど)。NMHDR の構造体の形式は次のように示しています:
typedef struct tagNMHDR {
HWND hwndFrom;
UINT idFrom;
UINT code;
} NMHDR;
TTN_SHOW のメッセージに対して、 code のメンバーは TTN_SHOWに設定されます。
ほとんどの通知は、まずメンバーとして NMHDR の構造を含む、より大きな構造体へのポインターを渡します。たとえば、構造体をリスト ビュー コントロール キーが押されたときに送信されるリスト ビュー コントロールの LVN_KEYDOWN の通知メッセージで使用されることを検討してください。次に示すように定義されている LV_KEYDOWN の構造体へのポインターの点:
typedef struct tagLV_KEYDOWN {
NMHDR hdr;
WORD wVKey;
UINT flags;
} LV_KEYDOWN;
NMHDR のメンバーがこの構造体の 1 番目であるため、通知メッセージに渡されたポインターが NMHDR へのポインターまたは LV_KEYDOWNへのポインターにキャストできることに注意してください。
すべてのウィンドウのコントロールに共通通知
ある通知が新しいウィンドウのすべてのコントロールに共通です。これらの通知は NMHDR の構造体へのポインターを渡します。
通知コード |
送信されるためです。 |
---|---|
NM_CLICK |
コントロールのユーザーによってクリックされたマウスの左ボタン |
NM_DBLCLK |
コントロールのユーザーでダブル クリックされたマウスの左ボタン |
NM_RCLICK |
コントロールのユーザーによってクリックされた右ボタン |
NM_RDBLCLK |
コントロールのユーザーによってダブル クリックの右ボタン |
NM_RETURN |
ユーザーはコントロールに入力フォーカスがあるときに Enter キーが押しました |
NM_SETFOCUS |
コントロールが入力フォーカスをされました。 |
NM_KILLFOCUS |
コントロールが入力フォーカスを解除されました |
NM_OUTOFMEMORY |
コントロールは、使用できる十分なメモリがないため、操作を完了できませんでした |
ON_NOTIFY: MFC アプリケーションの WM_NOTIFY のメッセージの処理
関数の CWnd::OnNotify ハンドルの通知メッセージ。既定の実装は、ダイヤルする通知ハンドラーのメッセージ マップをチェックします。一般に、 OnNotifyをオーバーライドしません。代わりに、ハンドラー関数を提供し、オーナー ウィンドウのクラスのメッセージ マップするハンドラーのメッセージマップ エントリを追加します。
ClassWizard は、 ClassWizard のプロパティ シートで、 ON_NOTIFY のメッセージマップ エントリを作成し、スケルトン ハンドラー関数を提供できます。ClassWizard のこの操作を簡単に行うために使用の詳細に 関数への割り当てのメッセージを参照してください。
ON_NOTIFY のメッセージマップのマクロに次の構文があります:
ON_NOTIFY( wNotifyCode, id, memberFxn )
斜体のパラメーターは次のとおりのどこに置き換えたりする:
wNotifyCode
LVN_KEYDOWNなど、処理される通知メッセージのコード。id
通知が送信されるコントロールの子の ID。memberFxn
この通知が送信されるときに呼び出すメンバー関数。
メンバー関数には、次のプロトタイプで宣言する必要があります:
afx_msg void memberFxn( NMHDR * pNotifyStruct, LRESULT * result );
解説
斜体のパラメーターは次のとおりです:
pNotifyStruct
上記のセクションで説明するように、通知の構造体へのポインター。result
返される前に設定した結果コードへのポインター。
使用例
メンバー関数 OnKeydownList1 に ID が IDC_LIST1である CListCtrl から LVN_KEYDOWN のメッセージを処理するを指定するには、メッセージ マップに次のコードを追加するために ClassWizard を使用して:
ON_NOTIFY( LVN_KEYDOWN, IDC_LIST1, OnKeydownList1 )
上の例では、 ClassWizard によって提供される関数は次のとおりです:
void CMessageReflectionDlg::OnKeydownList1(NMHDR* pNMHDR, LRESULT* pResult)
{
LV_KEYDOWN* pLVKeyDow = (LV_KEYDOWN*)pNMHDR;
// TODO: Add your control notification handler
// code here
*pResult = 0;
}
ClassWizard が適切な型のポインターを自動的に提供することに注意してください。pNMHDR か pLVKeyDowによって通知の構造にアクセスできます。
ON_NOTIFY_RANGE
一連のコントロールの WM_NOTIFY の同じメッセージを処理する必要がある場合 ON_NOTIFYではなく ON_NOTIFY_RANGE を使用できます。たとえば、ある特定の通知メッセージに対して同じ操作を実行する一連のボタンがある場合があります。
ON_NOTIFY_RANGEを使用すると、通知メッセージを範囲の開始と終了の子の ID を指定して処理する子の ID の連続する範囲を指定します。
ClassWizard は ON_NOTIFY_RANGEは処理; このコマンドを使用するには、自分メッセージ マップを編集する必要があります。
次のよう ON_NOTIFY_RANGE のメッセージマップ エントリと関数プロトタイプはです:
ON_NOTIFY_RANGE( wNotifyCode, id, idLast, memberFxn )
斜体のパラメーターは次のとおりのどこに置き換えたりする:
wNotifyCode
LVN_KEYDOWNなど、処理される通知メッセージのコード。id
特定の連続した範囲の最初の ID。idLast
特定の連続した範囲の最後の ID。memberFxn
この通知が送信されるときに呼び出すメンバー関数。
メンバー関数には、次のプロトタイプで宣言する必要があります:
afx_msg void memberFxn( UINT id, NMHDR * pNotifyStruct, LRESULT * result );
解説
斜体のパラメーターは次のとおりです:
id
通知を送信するコントロールの子の ID。pNotifyStruct
通知の構造体へのポインター、上のようにします。result
返される前に設定した結果コードへのポインター。
ON_NOTIFY_EX、 ON_NOTIFY_EX_RANGE
通知のルーティングの複数のオブジェクトにメッセージを処理する場合は ON_NOTIFY できます。また、 ON_NOTIFY_RANGEなく ON_NOTIFY_EX (または ON_NOTIFY_EX_RANGEを使用)。EX バージョンと通常のバージョンの唯一の違いは、メッセージの処理を続ける必要があるかどうかを示すメンバー関数が EX バージョンを戻り BOOL に呼び出したことです。この関数から FALSE を返すと、複数のオブジェクトで同じメッセージを処理できるようにします。
ClassWizard は ON_NOTIFY_EX か ON_NOTIFY_EX_RANGEは処理; これらのいずれかを使用する場合は、自分でメッセージ マップを編集する必要があります。
ON_NOTIFY_EX のメッセージマップ エントリと関数プロトタイプと ON_NOTIFY_EX_RANGE は次のとおりです。パラメーターの意味はEX 非バージョンの場合と同じです。
ON_NOTIFY_EX( nCode, id, memberFxn )
ON_NOTIFY_EX_RANGE( wNotifyCode, id, idLast, memberFxn )
上の両方のプロトタイプは同じです:
afx_msg BOOL memberFxn( UINT id, NMHDR * pNotifyStruct, LRESULT * result );
解説
どちらの場合も、 id は、通知を送信するコントロールの子の ID を保留。
関数は、コマンド ルーティングの他のオブジェクトにメッセージを処理する可能性がある場合は、通知メッセージが完全にまたは FALSE 処理された TRUE を返す必要があります。