豆知識−WM_NOTIFYメッセージとON_NOTIFYメッセージ

通常、Windows3.xでは、コントロールは親に対してメッセージを送信することでそのコントロールに起きた様々なイベントを通知します。単純な通知はWM_COMMANDメッセージとして送信されます。このメッセージにはパラメータとしてwParamとlParamがあり、wParamには通知コードおよびコントロールIDが、lParamにはコントロールのハンドルが格納されています。よって、WM_COMMANDメッセージではこれ以上の付加情報を送信することはできません。
Windows3.xでは、コントロールが追加データを含む通知メッセージを送信する必要がある場合、専用のメッセージ(WM_CTLCOLOR, WM_VSCROLL, WM_DRAWITEMなど)を使用します(これらは送信元のコントロールに返送することができます)。

Win32では、Windows3.xでサポートされているコントロールに加えて数多くの複雑なコントロールが追加されています。これらの中には通知メッセージと共に追加データの送信を必要とするものが多いため、それぞれに専用メッセージを追加することは非常に大変です。
そこで、新たにWM_NOTIFYというメッセージを作り、これを使うことで任意の数の追加データを渡すことができるようにしてあります。


WM_NOTIFYメッセージの構造
コントロールでWM_NOTIFYメッセージを取得するには、CWnd::OnNotify関数をオーバーライドします。この関数は以下のような形をしています。

virtual BOOL CWnd::OnNotify( WPARAM wParam, LPARAM lParam, LRESULT* pResult );
wParamにはメッセージを送信するコントロールのIDが格納されています。lParamには、ある構造体へのポインタが格納されています。この構造体はNMHDR構造体か、あるいはNMHDR構造体を最初のメンバに持つ構造体のいずれかです。
NMHDR構造体は以下のような形式になっています。

typedef struct tagNMHDR {
    HWND hwndFrom;  // メッセージを送信するコントロールのハンドル
    UINT idFrom;    // メッセージを送信するコントロールのID
    UINT code;      // 通知コード
} NMHDR;
通知コードは、例えばリストビューのヘッダのディバイダをドラッグした場合はHDN_BEGINTRACKになります。

lParamにはたいていの場合、NMHDR構造体を最初のメンバに持つ構造体へのポインタが格納されています。例えばリストビューでキーを押したときに送信されるLVN_KEYDOWNメッセージの場合は、以下のようなLV_KEYDOWN構造体が使われます。

typedef struct tagLV_KEYDOWN {
    NMHDR hdr;
    WORD wVKey;  
    UINT flags;
} LV_KEYDOWN;
最初のメンバがNMHDR構造体になっているので、lParamはNMHDRへのポインタとLV_KEYDOWNへのポインタのどちらにもキャストすることができます。

ON_NOTIFYメッセージについて
特定のメッセージに対するハンドラを作成するには、ON_NOTIFYメッセージに対するハンドラ関数を作成します。 ヘッダのディバイダドラッグ時のメッセージの取得 の方法1で、その記述のしかたが説明されています。詳しくはそちらを参照してください。

目次へ