ATL和WTL中的消息反射

ATL和WTL中的消息反射
   WTL是窗口模板库(Windows Library Template)的简称,是一套轻量级C++ GUI库,因为它使用了C++模板封装了窗口界面操作API和消息映射处理,它扩展了ATL中的UI窗口部分,并支持如下更多的功能特性:
    (1)   对话框和通用控件:包括对话框数据交换(DDX),子类化,控件消息通知与反射等
    (2)   工具栏和状态栏:包括工具条UI状态更新,多窗格状态条及UI状态更新等
    (3)   分隔窗口:包括窗格容器,嵌套分隔,特殊绘制等
    (4)   属性页和向导:包括属性表,普通属性页,向导属性页等
    (5)   GDI类等:包括GDI封装类,通用对话框等
    (6)   使用ActiveX控件:包括使用控件类,调用控件的方法,控件事件映射处理等
    (7)   高级对话框UI类:包括自绘和外观定制类,新控件类,控件UI状态更新,对话框数据验证DDV等
    (8)   支持拖放操作:包括拖放接口实现类,最近使用文件列表等
    综上所述,使用WTL几乎可以实现MFC所能实现的功能与界面,而且生成的执行文件体积更小,不需要动态链接库就可直接快速地执行。

    根据WIN32窗口原理,当事件发生的时候,一般由父窗口接收其子窗口或控件的通知或命令消息,在这里父窗口是消息接收者,子窗口或控件是消息发送者,那么谁是消息处理者呢?实际上由谁来处理消息只是代码上的逻辑,既可以在父窗口的窗口过程回调内处理,也可以在子窗口或控件的窗口过程回调内处理,在哪处理更方便合理就在哪处理,如果是在子窗口或控件窗口过程回调内处理,那么就需要作额外的处理了,也就是在父窗口中将消息反射给发送者,进而再由发送者处理。下面以父窗口为打开文件对话框,双击它的列表视图控件为例,给出运用上面(1)中的控件消息通知与反射来处理NM_DBLCLK消息的两种实现方式。

   继承方式:由控件处理消息
   从CWindowImpl模板基类派生一个子窗口或控件子类即listview子类,添加消息映射项和消息处理函数,消息映射项用REFLECTED_NOTIFY_XXX或REFLECTED_COMMAND_XXX系列反射宏实现,具体使用哪个宏,决定于是否通知或命令消息,及消息对应的ID和通知码。
1 class  CFileListViewCtrl  :  public  CWindowImpl < CFileListViewCtrl , CListViewCtrl >
2 {
3 protected:
4      BEGIN_MSG_MAP(CFileListViewCtrl)
5          REFLECTED_NOTIFY_CODE_HANDLER_EX(NM_DBLCLK,OnListViewDblclk)   //反射通知消息处理宏
6          CHAIN_MSG_MAP(CListViewCtrl)
7     END_MSG_MAP()
8    LRESULT OnListViewDblclk(NMHDR* pNMHDR);   //消息响应处理函数
9}
;
   
   在父窗口类消息映射链中最后添加反射通知宏REFLECT_NOTIFICATIONS()项。                                           
 1 class  COpenFileDlg  :  public  CDialogImpl < COpenFileDlg >   ,   public  CWinDataExchange < COpenFileDlg >
 2 {
 3public:
 4   COpenFileDlg();
 5   ~COpenFileDlg();
 6  enum  { IDD = IDD_OPEN_FILE_DLG };
 7
 8protected:
 9     BEGIN_MSG_MAP(COpenFileDlg)
10            MESSAGE_HANDLER(WM_INITDIALOG,OnInitDialog) 
11            REFLECT_NOTIFICATIONS()      //消息反射通知宏
12     END_MSG_MAP()
13    
14     BEGIN_DDX_MAP(COpenFileDlg)
15           DDX_CONTROL(IDC_LIST_FILE,m_list_File)
16     END_DDX_MAP()
17
18     LRESULT OnInitDialog(UINT uMsg,WPARAM wParam,LPARAM lParam,BOOL& bHandle);
19     
20private:
21    CFileListViewCtrl  m_list_File;    //使用派生类实例作为成员变量
22}
;

 成员方式:由父窗口处理消息 
   直接使用ATL中的包含窗口模板类CContainedWindowT,参数为子控件的类名即listviewctrl,实例化为父窗口类的一个成员变量,在父窗口类消息映射链中添加ALT_MSG_MAP宏来实现消息分派,其参数为分派ID,这个ID为成员变量初始化时指定的常量;添加反射通知宏REFLECT_NOTIFICATIONS(),注意ALT_MSG_MAP宏必须在反射通知宏REFLECT_NOTIFICATIONS之后。  
 1 class  COpenFileDlg  :  public  CDialogImpl < COpenFileDlg >  ,   public  CWinDataExchange < COpenFileDlg >
 2 {
 3    public:
 4        COpenFileDlg();
 5       ~COpenFileDlg();
 6  enum  { IDD = IDD_OPEN_FILE_DLG };
 7 
 8  protected:
 9     BEGIN_MSG_MAP(COpenFileDlg)
10          MESSAGE_HANDLER(WM_INITDIALOG,OnInitDialog) 
11          REFLECT_NOTIFICATIONS()           //  消息反射通知宏
12          ALT_MSG_MAP(1)                             //  消息分派宏
13          REFLECTED_NOTIFY_CODE_HANDLER_EX(NM_DBLCLK,OnListViewDblclk)     //  反射通知消息处理宏
14     END_MSG_MAP()
15
16     BEGIN_DDX_MAP(COpenFileDlg)
17           DDX_CONTROL(IDC_LIST_FILE,m_list_File)
18     END_DDX_MAP()
19
20     LRESULT OnInitDialog(UINT uMsg,WPARAM wParam,LPARAM lParam,BOOL& bHandle);
21     LRESULT OnListViewDblclk(NMHDR* pNMHDR);            //消息响应处理函数
22  private:
23    CContainedWindowT<CListViewCtrl>   m_list_File;    //  实例化包含窗口模板类作为成员变量
24 }
;

   在父窗口内需要初始化m_list_File以指定分派ID号。                                                               
1 COpenFileDlg :: COpenFileDlg ():
2 m_list_File( t his , 1 )     // 指定消息分派ID为1
3 {  
4}

你可能感兴趣的:(ATL和WTL中的消息反射)