關於wm_notify與訊息反射—耗費我兩天時間才解決的問題
綜合資源電子書社群 其實,問題很簡單,我想在listctrl響應nm_setfocus的同時通知其父視窗(其實我這句話說錯了,listctrl只能響應=nm_setfocus,為什麼有個「=」呢?稍後解釋),最幼稚的想法是讓在listctrl和父視窗中都新增對此訊息的響應,很不幸,我在一開始就是這麼想的-_-| 。。。很明顯我失敗了!
後來我又發現,如果在listctrl中新增對=nm_setfocus的響應,父視窗就無法響應nm_setfocus,反之就可以響應。於是很容易想到在listctrl的訊息響應中sendmessage給父視窗,控制項傳送的訊息有兩種:wm_command和wm_notify,像button,edit,combobox等控制項,主要使用wm_command訊息,而listctrl這類控制項主要使用wm_notify訊息,傳送訊息時有兩個很重要的引數wparam和lparam,msdn說明如下:
lresult = sendmessage( // returns lresult in lresult
(hwnd) hwndcontrol, // handle to destination control
(uint) wm_notify, // message id
(wparam) wparam, // = (wparam) (int) idctrl;
(lparam) lparam // = (lparam) (lpnmhdr) pnmh; );
結果我還是失敗了!折騰了一天一夜,直到晚上熄燈,我就不信我弄不出來,第二天上csdn求救,有乙個同志的回答提醒了我:訊息反射。訊息反射是個什麼東西,我還是第一次聽到,看來我真是菜鳥。於是查閱了一下訊息反射的資料,原來,控制項根本無法直接給自己傳送訊息,這樣就導致控制項無法控制自己,所有的控制必須在父視窗類中實現,這樣不符合物件導向的思想,於是出現了訊息反射;即子控制項傳送給父視窗的訊息被父視窗馬上反射回來,如果子控制項響應了反射訊息,父視窗就不響應,反之則響應。這就和我剛才發現的現象吻合了。
那麼,訊息反射是怎樣實現的呢?源**說明一切!父視窗在接收到子控制項的通知訊息時呼叫虛的訊息響應函式cwnd::onnotify(),**如下:
bool cwnd::onnotify(wparam, lparam lparam, lresult* presult)
接著看reflectlastmsg()函式:
bool pascal cwnd::reflectlastmsg(hwnd hwndchild, lresult* presult)
} #endif //!_afx_no_occ_support
return false; }
// only ole controls and permanent windows will get reflected msgs
assert(pwnd != null);
return pwnd->sendchildnotifylastmsg(presult); }
注意紅色**!此時呼叫的是子控制項的sendchildnotifylastmsg() 。繼續看sendchildnotifylastmsg():
bool cwnd::sendchildnotifylastmsg(lresult* presult)
呼叫子控制項的虛函式onchildnotify函式,進行處理。 如果沒有處理,則呼叫reflectchildnotify(...)函式進行標準的反射訊息的訊息對映處理。 如果在reflectchildnotify(...)中此訊息還沒被處理,就返回到cwnd::onnotify(...)中呼叫oncmdmsg(...)處理,這樣,父視窗就可以響應此訊息了。
下面回到我最初的問題中來,我想在listctrl和父視窗中都處理此訊息,因此我們可以過載onnotify(...)如下:
bool cwelllistview::onnotify(wparam wparam, lparam lparam, lresult* presult)
//cwelllistview繼承子cformview,相當與對話方塊
還要新增兩個標頭檔案:
#include "afxpriv.h"
#include "c:\program files\microsoft visual studio\vc98\mfc\src\afximpl.h"
看到它和cwnd::onnotify(...)的區別了沒?恩,就是這樣!
但是,很不幸,我最終沒有採取這種辦法,因為我在一開始就沒有想到最佳方案,我完全可以用指標來實現我的需求,在子控制項類中需要的地方新增如下**就可以操作父視窗了:
cwelllistview* listview=(cwelllistview*)getparent();
因此,在以後的程式設計學習中,我們應該盡量用指標操作來代替傳送訊息來實現我們的需求!
文章出處:飛諾網(
www.firnow.com):
控制項的WM NOTIFY訊息對映
控制項的wm notify訊息對映 前幾天,我嘗試在clistctrl中對映hdn begintrack這個wm notify訊息。輕鬆的用classwizard建立了訊息對映,幾秒中完成了所有工作之後發生的事情卻讓我很長時間輕鬆不起來了。訊息根本對映不上!begin message map cpr...
WM NOTIFY訊息流程例項分析
我們以clistctrl控制項為例來分析wm notify訊息。clistctrl控制項在report樣式下會包含cheaderctrl標頭控制項,即cheaderctrl標頭控制項為clistctrl控制項的子控制項,所以不難理解,拖動cheaderctrl標頭控制項的列分隔欄會投遞hdn beg...
WM NOTIFY訊息流程例項分析
我們以clistctrl控制項為例來分析wm notify訊息。clistctrl控制項在report樣式下會包含cheaderctrl標頭控制項,即cheaderctrl標頭控制項為clistctrl控制項的子控制項,所以不難理解,拖動cheaderctrl標頭控制項的列分隔欄會投遞hdn beg...