// main.cpp: #include "mywindow.h" ccommodule _module; int winapi winmain(hinstance hinst, hinstance hinstprev, lpstr szcmdline, int ncmdshow) { _module.init(null, hinst); cmywindow wndmain; msg msg; // create & show our main window if ( null == wndmain.create ( null, cwindow::rcdefault, _t("my first atl window") )) { // bad news, window creation failed return 1; } wndmain.showwindow(ncmdshow); wndmain.updatewindow(); // run the message loop while ( getmessage(&msg, null, 0, 0) > 0 ) { translatemessage(&msg); dispatchmessage(&msg); } _module.term(); return msg.wparam; }
上面的代码唯一需要说明的是cwindow::rcdefault,这是cwindow中的成员(静态数据成员),数据类型是rect。和调用createwindow() api时使用cw_usedefault指定窗口的宽度和高度一样,atl使用rcdefault作为窗口的最初大小。
在atl代码内部,atl使用了一些类似汇编语言的魔法将主窗口的句柄与相应的cmywindow对象联系起来,在外部看来就是可以毫无问题的在线程之间传递cwindow对象,而mfc的cwnd却不能这样作。
这就是我们的窗口:
![[first atl window - 4k]](http://dev.csdn.net/develop/articleimages/26/26417/csdn_dev_image_2004-4-41327300.png)
我得承认这确实没有什么激动人心的地方。我们将添加一个about菜单并显示一个对话框,主要是为它增加一些情趣。
atl中的对话框
我们前面提到过,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命令。