MFC程序员WTL指南(2)ATL界面类
2008-01-19 20:26:41 来源:WEB开发网我们前面提到过,ATL有两个对话框类,我们的About对话框使用CDialogImpl。生成一个新对话框和生成一个主窗口几乎一样,只有两点不同:
- 窗口的基类是CDialogImpl而不是CWindowImpl。
- 你需要定义名称为IDD的公有成员用来保存对话框资源的ID。
现在开始为About对话框定义一个新类:
class CAboutDlg : public CDialogImpl<CAboutDlg>
{
public:
enum { IDD = IDD_ABOUT };
BEGIN_MSG_MAP(CAboutDlg)
END_MSG_MAP()
};
ATL没有在内部实现对“OK”和“Cancel”两个按钮的响应处理,所以我们需要自己添加这些代码,如果用户用鼠标点击标题栏的关闭按钮,WM_CLOSE的响应函数就会被调用。我们还需要处理WM_INITDIALOG消息,这样我们就能够在对话框出现时正确的设置键盘焦点,下面是完整的类定义和消息响应函数。
class CAboutDlg : public CDialogImpl<CAboutDlg>
{
public:
enum { IDD = IDD_ABOUT };
BEGIN_MSG_MAP(CAboutDlg)
MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
MESSAGE_HANDLER(WM_CLOSE, OnClose)
COMMAND_ID_HANDLER(IDOK, OnOKCancel)
COMMAND_ID_HANDLER(IDCANCEL, OnOKCancel)
END_MSG_MAP()
LRESULT OnInitDialog(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
CenterWindow();
return TRUE; // let the system set the focus
}
LRESULT OnClose(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
EndDialog(IDCANCEL);
return 0;
}
LRESULT OnOKCancel(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
{
EndDialog(wID);
return 0;
}
};
我使用一个消息响应函数同时处理“OK”和“Cancel”两个按钮的WM_COMMAND消息,因为命令响应函数的wID参数就已经指明了消息是来自“OK”按钮还是来自“Cancel”按钮。
显示对话框的方法与MFC相似,创建一个新对话框类的实例,然后调用DoModal()方法。现在我们返回主窗口,添加一个带有About菜单项的菜单用来显示我们的对话框,这需要再添加两个消息响应函数,一个是响应WM_CREATE
,另一个是响应菜单的IDC_ABOUT命令。
class CMyWindow : public CWindowImpl<CMyWindow, CWindow, CFrameWinTraits>,
public CPaintBkgnd<CMyWindow,RGB(0,0,255)>
{
public:
BEGIN_MSG_MAP(CMyWindow)
MESSAGE_HANDLER(WM_CREATE, OnCreate)
COMMAND_ID_HANDLER(IDC_ABOUT, OnAbout)
// ...
CHAIN_MSG_MAP(CPaintBkgndBase)
END_MSG_MAP()
LRESULT OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
HMENU hmenu = LoadMenu ( _Module.GetResourceInstance(),
MAKEINTRESOURCE(IDR_MENU1) );
SetMenu ( hmenu );
return 0;
}
LRESULT OnAbout(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
{
CAboutDlg dlg;
dlg.DoModal();
return 0;
}
// ...
};
在指定对话框的父窗口的方式上有些不同,MFC是通过构造函数将父窗口的指针传递给对话框而在ATL中是将父窗口的指针作为DoModal()方法的第一个参数传递给对话框的,如果象上面的代码一样没有指定父窗口,ATL会使用GetActiveWindow()
得到的窗口(也就是我们的主框架窗口)作为对话框的父窗口。
对LoadMenu()方法的调用展示了CComModule的另一个方法-GetResourceInstance(),它返回你的EXE的HINSTANCE实例,和MFC的AfxGetResourceHandle()方法相似。(当然还有CComModule::GetModuleInstance(),它相当于MFC的AfxGetInstanceHandle()。)
这就是主窗口和对话框的显示效果:
我会继续讲WTL的,只是会在第二部分。我觉得既然这些文章是写给使用MFC的开发者的,所以有必要在投入WTL之前先介绍一些ATL。如果你是第一次接触到ATL,那现在你就可以尝试写一些小程序,处理消息和使用嵌入类,你也可以尝试用类向导支持消息映射链,使它能够自动添加消息响应。现在就开始,右键单击CMyWindow项,在弹出的上下文菜单中单击“Add Windows Message Handler”菜单项。
在第二部分,我将全面介绍基本的WTL窗口类和一个更好的消息映射宏。
修改记录2003年3月22日,本文第一次发表。
更多精彩
赞助商链接