共用方式為


TN061:ON_NOTIFY 和 WM_NOTIFY 訊息

注意

下列技術提示自其納入線上文件以來,未曾更新。 因此,有些程序和主題可能已過期或不正確。 如需最新資訊,建議您在線上文件索引中搜尋相關的主題。

此技術附注提供新WM_NOTIFY訊息的背景資訊,並說明在 MFC 應用程式中處理WM_NOTIFY訊息的建議(和最常見)方式。

Windows 3.x 中的通知訊息

在 Windows 3.x 中,控制項會藉由傳送訊息給父系,以通知其父代事件,例如按一下滑鼠、變更內容和選取專案,以及控制背景繪製。 簡單通知會以特殊WM_COMMAND訊息傳送,其中包含通知碼(例如BN_CLICKED),以及封裝在 wParam 中的控制項識別碼,以及控制項在 lParam 中的 控制碼。 請注意,由於 wParam lParam 已滿,因此無法傳遞任何其他資料 , 這些訊息只能是簡單的通知。 例如,在BN_CLICKED通知中,按一下按鈕時,無法傳送滑鼠游標位置的相關資訊。

當 Windows 3.x 中的控制項需要傳送包含其他資料的通知訊息時,它們會使用各種不同的特殊用途訊息,包括WM_CTLCOLOR、WM_VSCROLL、WM_HSCROLL、WM_DRAWITEM、WM_MEASUREITEM、WM_COMPAREITEM、WM_DELETEITEM、WM_CHARTOITEM、WM_VKEYTOITEM等等。 這些訊息可以反映回傳送它們的控制項。 如需詳細資訊,請參閱 TN062:Windows 控制項 的訊息反思。

Win32 中的通知訊息

針對 Windows 3.1 中存在的控制項,WIN32 API 會使用 Windows 3.x 中使用的大部分通知訊息。 不過,Win32 也會將一些複雜的複雜控制項新增至 Windows 3.x 中支援控制項。 這些控制項經常需要傳送其他資料及其通知訊息。 WIN32 API 的設計者選擇只新增一則訊息,WM_NOTIFY,以標準化的方式傳遞任何數量的額外資料,而不是為每個需要額外資料 WM_ * 的新 通知新增訊息。

WM_NOTIFY訊息包含在 wParam 傳送訊息之控制項的識別碼,以及 lParam 結構的指標。 這個結構是 NMHDR 結構,或是具有 NMHDR 結構做為其第一個 成員的較大結構。 請注意,由於 NMHDR 成員是第一個,因此此結構的指標可以做為 NMHDR 的指標 ,或做為較大結構的指標,視您轉換的方式而定。

在大部分情況下,指標會指向較大的結構,而且當您使用它時,將需要轉換它。 在少數通知中,例如常見的通知(其名稱開頭 為 NM_ ),以及工具提示控制項的TTN_SHOW和TTN_POP通知,是 實際使用的 NMHDR 結構。

NMHDR 結構或初始成員包含傳送訊息和通知碼之控制項的控制碼和識別碼(例如TTN_SHOW)。 NMHDR 結構的格式 如下所示:

typedef struct tagNMHDR {
    HWND hwndFrom;
    UINT idFrom;
    UINT code;
} NMHDR;

針對TTN_SHOW訊息,程式 代碼 成員會設定為 TTN_SHOW。

大部分的通知都會將指標傳遞至包含 NMHDR 結構做為其第一個 成員的較大結構。 例如,請考慮清單檢視控制項LVN_KEYDOWN通知訊息所使用的結構,這會在清單檢視控制項中按下按鍵時傳送。 指標指向 LV_KEYDOWN 結構,其定義如下:

typedef struct tagLV_KEYDOWN {
    NMHDR hdr;
    WORD wVKey;
    UINT flags;
} LV_KEYDOWN;

請注意,由於 NMHDR 成員是此結構中的第一個成員,因此您傳入通知訊息的指標可以轉換成 NMHDR 的指標 或LV_KEYDOWN 指標。

所有新 Windows 控制項通用的通知

某些通知適用于所有新的 Windows 控制項。 這些通知會將指標傳遞至 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
傳送通知之控制項的子識別碼。

memberFxn
傳送此通知時要呼叫的成員函式。

您的成員函式必須以下列原型宣告:

afx_msg void memberFxn(NMHDR* pNotifyStruct, LRESULT* result);

其中的參數:

pNotifyStruct
通知結構的指標,如上一節所述。

result
傳回之前所設定結果碼的指標。

範例

若要指定成員函 OnKeydownList1 式要處理其識別碼為 IDC_LIST1CListCtrl 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_RANGE,而不是ON_NOTIFY。 例如,您可能有一組按鈕,您想要針對特定通知訊息執行相同的動作。

當您使用ON_NOTIFY_RANGE時,您可以指定連續的子識別碼範圍,藉由指定範圍的開頭和結束子識別碼來處理通知訊息。

ClassWizard 不會處理ON_NOTIFY_RANGE;若要使用它,您必須自行編輯訊息對應。

ON_NOTIFY_RANGE的訊息對應專案和函式原型如下所示:

ON_NOTIFY_RANGE(wNotifyCode, id, idLast, memberFxn)

其中的參數:

wNotifyCode
要處理之通知訊息的程式碼,例如LVN_KEYDOWN。

id
連續識別碼範圍中的第一個識別碼。

idLast
連續識別碼範圍中的最後一個識別碼。

memberFxn
傳送此通知時要呼叫的成員函式。

您的成員函式必須以下列原型宣告:

afx_msg void memberFxn(UINT id, NMHDR* pNotifyStruct, LRESULT* result);

其中的參數:

id
傳送通知之控制項的子識別碼。

pNotifyStruct
通知結構的指標,如上所述。

result
傳回之前所設定結果碼的指標。

ON_NOTIFY_EX,ON_NOTIFY_EX_RANGE

如果您想要通知路由中的多個物件來處理訊息,您可以使用ON_NOTIFY_EX(或ON_NOTIFY_EX_RANGE),而不是ON_NOTIFY(或ON_NOTIFY_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 會保存傳送通知之控制項的子識別碼。

如果已完全處理通知訊息, 您的函式必須傳回 TRUE ;如果命令路由中的其他物件應該有機會處理訊息,則此函式必須傳回 FALSE

另請參閱

依編號顯示的技術提示
依分類區分的技術提示