⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 wtl for mfc programmers, part i - atl gui classes - wtl.htm

📁 MFC程序员的WTL指南,非常具体,WTL入门最好的书
💻 HTM
📖 第 1 页 / 共 3 页
字号:
  RGB(0,0,255)&gt;作为参数传递,那个“,”会使预处理器认为我们使用了多个参数。</P>
      
<P>你可以在继承列表中使用多个嵌入类,每一个嵌入类使用一个CHAIN_MSG_MAP宏,这样消息映射链就会将消息传递给它。这与MFC不同,MFC地CWnd派生类只能有一个基类,MFC自动将消息传递给基类。</P>
<H2><A name=exestructure></A><font color="#FFFF66">ATL程序的结构</font></H2>
      
<P>到目前为止我们已经有了一个完整地主窗口类(即使不完全有用),让我们看看如何在程序中使用它。一个ATL程序包含一个CComModule类型的全局变量_Module,这和MFC的程序都有一个CWinApp类型的全局变量theApp有些类似,唯一不同的是在ATL中这个变量必须命名为_Module。</P>
      
<P>下面是stdafx.h文件的开始部分:</P>
<PRE><SPAN class=cpp-comment><font color="#3300FF">// stdafx.h:</font></SPAN>
<font color="#3300FF"><SPAN class=cpp-preprocessor>#define STRICT</SPAN>
<SPAN class=cpp-preprocessor>#define VC_EXTRALEAN</SPAN>
 
<SPAN class=cpp-preprocessor>#include &lt;atlbase.h&gt;       <font color="#000000"> // 基本的ATL类</font></SPAN>
<SPAN class=cpp-keyword>extern</SPAN> CComModule _Module;  <SPAN class=cpp-comment><font color="#000000">// 全局_Module</font></SPAN>
<SPAN class=cpp-preprocessor>#include &lt;atlwin.h&gt;        <font color="#000000"> // ATL窗口类</font></SPAN></font></PRE>
<P>atlbase.h已经包含最基本的Window编程的头文件,所以我们不需要在包含windows.h,tchar.h之类的头文件。在CPP文件中声明了_Module变量:</P>
<PRE><SPAN class=cpp-comment>// main.cpp:</SPAN>
<font color="#3300FF">CComModule _Module;</font></PRE>
      
<P>CComModule含有程序的初始化和关闭函数,需要在WinMain()中显示的调用,让我们从这里开始:</P>
<PRE><SPAN class=cpp-comment>// main.cpp:</SPAN>
<font color="#3300FF">CComModule _Module;</font>
 
<SPAN class=cpp-keyword><font color="#3300FF">int</font></SPAN><font color="#3300FF"> WINAPI WinMain(HINSTANCE hInst, HINSTANCE hInstPrev,
                   LPSTR szCmdLine, <SPAN class=cpp-keyword>int</SPAN> nCmdShow)
{
    _Module.Init(NULL, hInst);
    _Module.Term();
}</font></PRE>
      
<P>Init()的第一个参数只有COM的服务程序才有用,由于我们的EXE不含有COM对象,我们只需将NULL传递给Init()就行了。ATL不提供自己的WinMain()和类似MFC的消息泵,所以我们需要创建CMyWindow对象并添加消息泵才能使我们的程序运行。<br>
</P>
<PRE><SPAN class=cpp-comment>// main.cpp:</SPAN>
<SPAN class=cpp-preprocessor><font color="#3300FF">#include "MyWindow.h"</font></SPAN><font color="#3300FF">
CComModule _Module;
 
<SPAN class=cpp-keyword>int</SPAN> WINAPI WinMain(HINSTANCE hInst, HINSTANCE hInstPrev,
                   LPSTR szCmdLine, <SPAN class=cpp-keyword>int</SPAN> nCmdShow)
{
    _Module.Init(NULL, hInst);
 
    CMyWindow wndMain;
    MSG msg;
 
    <SPAN class=cpp-comment>// Create &amp; show our main window</SPAN>
    <SPAN class=cpp-keyword>if</SPAN> ( NULL == wndMain.Create ( NULL, CWindow::rcDefault, 
                                 _T(<SPAN class=cpp-string>"My First ATL Window"</SPAN>) ))
    {
        <SPAN class=cpp-comment>// Bad news, window creation failed</SPAN>
        <SPAN class=cpp-keyword>return</SPAN> <SPAN class=cpp-literal>1</SPAN>;
     }
 
    wndMain.ShowWindow(nCmdShow);
    wndMain.UpdateWindow();
 
    <SPAN class=cpp-comment>// Run the message loop</SPAN>
    <SPAN class=cpp-keyword>while</SPAN> ( GetMessage(&amp;msg, NULL, <SPAN class=cpp-literal>0</SPAN>, <SPAN class=cpp-literal>0</SPAN>) &gt; <SPAN class=cpp-literal>0</SPAN> )
    {
        TranslateMessage(&amp;msg);
        DispatchMessage(&amp;msg);
    }
 
    _Module.Term();
    <SPAN class=cpp-keyword>return</SPAN> msg.wParam;
}</font></PRE>
      
<P>上面的代码唯一需要说明的是CWindow::rcDefault,这是CWindow中的成员(静态数据成员),数据类型是RECT。和调用CreateWindow() 
  API时使用CW_USEDEFAULT指定窗口的宽度和高度一样,ATL使用rcDefault作为窗口的最初大小。</P>
      
<P>在ATL代码内部,ATL使用了一些类似汇编语言的魔法将主窗口的句柄与相应的CMyWindow对象联系起来,在外部看来就是可以毫无问题的在线程之间传递CWindow对象,而MFC的CWnd却不能这样作。</P>
      
<P>这就是我们的窗口:</P>
      <P><IMG height=249 alt=" [First ATL window - 4K] " 
      src="images/firstwin.png" 
      width=370 align=bottom border=0></P>
      
<P>我得承认这确实没有什么激动人心的地方。我们将添加一个About菜单并显示一个对话框,主要是为它增加一些情趣。</P>
<h2><A name=dialogs></A><font color="#FFFF66">ATL中的对话框</font></H2>
      
<P>我们前面提到过,ATL有两个对话框类,我们的About对话框使用CDialogImpl。生成一个新对话框和生成一个主窗口几乎一样,只有两点不同:<br>
</P>
      
<OL>
  <LI>窗口的基类是CDialogImpl而不是CWindowImpl。 
  <LI>你需要定义名称为IDD的公有成员用来保存对话框资源的ID。 </LI>
</OL>
      
<P>现在开始为About对话框定义一个新类:</P>
<PRE><SPAN class=cpp-keyword><font color="#3300FF">class</font></SPAN><font color="#3300FF"> CAboutDlg : <SPAN class=cpp-keyword>public</SPAN> CDialogImpl&lt;CAboutDlg&gt;
{
<SPAN class=cpp-keyword>public</SPAN>:
    <SPAN class=cpp-keyword>enum</SPAN> { IDD = IDD_ABOUT };
 
    BEGIN_MSG_MAP(CAboutDlg)
    END_MSG_MAP()
};</font></PRE>
<P>ATL没有在内部实现对“OK”和“Cancel”两个按钮的响应处理,所以我们需要自己添加这些代码,如果用户用鼠标点击标题栏的关闭按钮,WM_CLOSE的响应函数就会被调用。我们还需要处理WM_INITDIALOG消息,这样我们就能够在对话框出现时正确的设置键盘焦点,下面是完整的类定义和消息响应函数。</P>
<PRE><SPAN class=cpp-keyword><font color="#3300FF">class</font></SPAN><font color="#3300FF"> CAboutDlg : <SPAN class=cpp-keyword>public</SPAN> CDialogImpl&lt;CAboutDlg&gt;
{
<SPAN class=cpp-keyword>public</SPAN>:
    <SPAN class=cpp-keyword>enum</SPAN> { 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&amp; bHandled)
    {
        CenterWindow();
        <SPAN class=cpp-keyword>return</SPAN> TRUE;    <SPAN class=cpp-comment>// let the system set the focus</SPAN>
    }
 
    LRESULT OnClose(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL&amp; bHandled)
    {
        EndDialog(IDCANCEL);
        <SPAN class=cpp-keyword>return</SPAN> <SPAN class=cpp-literal>0</SPAN>;
    }
 
    LRESULT OnOKCancel(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL&amp; bHandled)
    {
        EndDialog(wID);
        <SPAN class=cpp-keyword>return</SPAN> <SPAN class=cpp-literal>0</SPAN>;
    }
};</font></PRE>
      
<P>我使用一个消息响应函数同时处理“OK”和“Cancel”两个按钮的WM_COMMAND消息,因为命令响应函数的wID参数就已经指明了消息是来自“OK”按钮还是来自“Cancel”按钮。</P>
<P>显示对话框的方法与MFC相似,创建一个新对话框类的实例,然后调用DoModal()方法。现在我们返回主窗口,添加一个带有About菜单项的菜单用来显示我们的对话框,这需要再添加两个消息响应函数,一个是响应<code>WM_CREATE</code>,另一个是响应菜单的IDC_ABOUT命令。</P>
<PRE><SPAN class=cpp-keyword><font color="#3300FF">class</font></SPAN><font color="#3300FF"> CMyWindow : <SPAN class=cpp-keyword>public</SPAN> CWindowImpl&lt;CMyWindow, CWindow, CFrameWinTraits&gt;,
                  <SPAN class=cpp-keyword>public</SPAN> CPaintBkgnd&lt;CMyWindow,RGB(<SPAN class=cpp-literal>0</SPAN>,<SPAN class=cpp-literal>0</SPAN>,<SPAN class=cpp-literal>255</SPAN>)&gt;
{
<SPAN class=cpp-keyword>public</SPAN>:
    BEGIN_MSG_MAP(CMyWindow)
        MESSAGE_HANDLER(WM_CREATE, OnCreate)
        COMMAND_ID_HANDLER(IDC_ABOUT, OnAbout)
        <SPAN class=cpp-comment>// ...</SPAN>
        CHAIN_MSG_MAP(CPaintBkgndBase)
    END_MSG_MAP()
 
    LRESULT OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL&amp; bHandled)
    {
    HMENU hmenu = LoadMenu ( _Module.GetResourceInstance(),
                             MAKEINTRESOURCE(IDR_MENU1) );
 
        SetMenu ( hmenu );
        <SPAN class=cpp-keyword>return</SPAN> <SPAN class=cpp-literal>0</SPAN>;
    }
 
    LRESULT OnAbout(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL&amp; bHandled)
    {
    CAboutDlg dlg;
 
        dlg.DoModal();
        <SPAN class=cpp-keyword>return</SPAN> <SPAN class=cpp-literal>0</SPAN>;
    }
    <SPAN class=cpp-comment>// ...</SPAN>
};</font></PRE>
      
<P>在指定对话框的父窗口的方式上有些不同,MFC是通过构造函数将父窗口的指针传递给对话框而在ATL中是将父窗口的指针作为DoModal()方法的第一个参数传递给对话框的,如果象上面的代码一样没有指定父窗口,ATL会使用<code>GetActiveWindow()</code>得到的窗口(也就是我们的主框架窗口)作为对话框的父窗口。</P>
      
<P>对LoadMenu()方法的调用展示了CComModule的另一个方法-GetResourceInstance(),它返回你的EXE的HINSTANCE实例,和MFC的AfxGetResourceHandle()方法相似。(当然还有CComModule::GetModuleInstance(),它相当于MFC的AfxGetInstanceHandle()。)</P>
      
<P>这就是主窗口和对话框的显示效果:</P>
<P><IMG height=248 alt=" [About box - 5K] " 
      src="images/firstabout.png" 
      width=369 align=bottom border=0></P>
<H2><A name=whereswtlman></A><font color="#FFFF66">我会继续讲WTL,我保证!</font></H2>
      
<P>我会继续讲WTL的,只是会在第二部分。我觉得既然这些文章是写给使用MFC的开发者的,所以有必要在投入WTL之前先介绍一些ATL。如果你是第一次接触到ATL,那现在你就可以尝试写一些小程序,处理消息和使用嵌入类,你也可以尝试用类向导支持消息映射链,使它能够自动添加消息响应。现在就开始,右键单击CMyWindow项,在弹出的上下文菜单中单击“<i>Add 
  Windows Message Handler</i>”菜单项。</P>
<P>在第二部分,我将全面介绍基本的WTL窗口类和一个更好的消息映射宏。</P>
<H2><A name=revisionhistory></A><font color="#FFFF66">修改记录</font></H2>
      
<P>2003年3月22日,本文第一次发表。</P>
<P>&nbsp;</P>
<P>&nbsp;</P>
</body>
</html>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -