您的位置:首页 > 其它

ATL和WTL中的消息反射

2015-07-16 16:03 246 查看
  转载地址:  http://www.cppblog.com/qinqing1984/archive/2010/06/14/117872.html

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

{
 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

     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

     
20

private:
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(this,1)     //
指定消息分派ID为1
3

{

  
4

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: