科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道ATL的GUI程序设计(一)

ATL的GUI程序设计(一)

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

在这一章里,就像所有的入门级教程一样,我也将不能免俗地以一个“Hello, World!”程序开始我的教程。

作者:李马 来源:CSDN 2007年9月24日

关键字:

  • 评论
  • 分享微博
  • 分享邮件

在本页阅读全文(共2页)

“不过如此”

说句题外话先。许是我太狂妄,又许是我太幼稚,总之我在上大学以来,越来越喜欢说“不过如此”这句话。譬如上了大学以后,没过俩月我就觉得大学“不过如此”;学会喝酒之后,就又会觉得喝酒“不过如此”;到了北京以后,又觉得北京“不过如此”;参观了某著名软件公司之后,又觉得它“不过如此”……书归正传话归正题,不知道你第一眼看过ATL版本的“Hello, World!”之后会不会同样有这样一种感觉?——自然,我希望是这样的。

那么,在了解ATL之前,就让我们先来目测一下这个“Hello, World!”吧。也许,你会从上面的代码猜到以下内容:

  1. atlbase.h大概其应该是ATL程序需要包含的头文件。
  2. CComModule,从类名称看应该是一个模块类。_Module是这个模块类的实例。
  3. WinMain没变。
  4. CComModule::Init应该是对模块进行初始化,这个方法应该是在程序初始化的时候调用。
  5. CComModule::Term应该是对模块进行结束处理,这个方法应该是在程序结束之前调用。
  6. WinMain的最后仍然是以return结尾。

好,是不是“不过如此”呢?没错!

大抵如此

到此为止,希望你的猜想能够让你对ATL的恐惧感(如果有的话)一扫而光。那么,现在李马来为你补充上几点:

atlbase.h在用ATL进行GUI程序设计的时候,就如同SDK中的windows.h一样重要。对于GUI程序设计的部分,这个文件中主要有这么几个值得关注的地方:

  1. Win32程序设计必备的头文件,诸如windows.h、tchar.h等。
  2. CComModule的定义。对于GUI程序设计,我们可以将它简单地看作对HINSTANCE的一个封装。
  3. 一些简单的工具类。(请原谅我不能在这里提供给你它们具体的名字,因为ATL 3.0和ATL 7.0是不一样的。VC 6.0附带的是ATL 3.0,它的atlbase.h中主要提供了一些COM的智能指针和字符串,如CComPtr、CComBSTR等;而VS2003中的ATL 7.0中则附带了一些更有趣的类,比如CRegKey、CHandle等。)

下面接着说CComModule。相信你可以从它的类名称中看出来,这个类主要用来管理COM的各种信息。如果你深入到ATL的源代码之中,你可能会为它的众多成员与方法感觉到迷惑。其实在进行GUI程序设计的时候,你只需要关心以下这些内容:

  1. HRESULT CComModule::Init( _ATL_OBJMAP_ENTRY* p, HINSTANCE h, const GUID* plibid = NULL );
    进行模块的初始化,第一个参数取NULL,第二个参数取应用程序的实例句柄,也就是WinMain中传入的hInstance。
  2. void CComModule::Term();
    进行模块的卸载,在程序结束时调用。
  3. HINSTANCE CComModule::GetModuleInstance();
    获取应用程序实例句柄CComModule::m_hInst。
  4. HINSTANCE CComModule::GetResourceInstance();
    获取资源模块句柄CComModule::m_hInstResource,这个值在默认情况下是和CComModule::m_hInst一致的。如果你程序的所有资源位于一个DLL之中,那么你可以在初始化应用程序中将CComModule::m_hInstResource成员赋值为这个DLL的模块句柄。

接着说CComModule的实例_Module。可以说,这个全局变量贯穿于ATL整个框架的始终,无论你是使用它编写COM组件还是GUI程序。譬如,你可能不止一次地需要使用模块的实例句柄(LoadIcon、LoadCursor),那么你只需要这样调用:

extern CComModule _Module;
HICON hIcon = ::LoadIcon( _Module.GetResourceInstance(), MAKEINTRESOURCE( IDI_YOURICON ) );

好了,那么现在我们可以充分展示一下这个模块类的具体使用了。在此,我仅仅将我先前的“Hello, World!”作了一番扩展,如下:

//////////////////////////////////////////////////////////////////////////
// ATL的GUI程序设计配套源代码
// 第一章 不能免俗的“Hello, World!”
// 工程名称:HelloWorldEx
// 作者:李马
// http://www.titilima.cn
//////////////////////////////////////////////////////////////////////////

#include <atlbase.h>
CComModule _Module;

int WINAPI _tWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nShowCmd )
{
    _Module.Init( NULL, hInstance );
    _Module.m_hInstResource = LoadLibrary( _T("shell32.dll") );

    MSGBOXPARAMS mbp;
    ZeroMemory( &mbp, sizeof( mbp ) );
    mbp.cbSize       = sizeof( mbp );
    mbp.dwLanguageId = GetSystemDefaultLangID();
    mbp.dwStyle      = MB_USERICON;
    mbp.hInstance    = _Module.GetResourceInstance();
    mbp.lpszCaption  = _T("Hello");
    mbp.lpszIcon     = MAKEINTRESOURCE( 44 );
    mbp.lpszText     = _T("Hello, World!");
    MessageBoxIndirect( &mbp );

    FreeLibrary( _Module.m_hInstResource );
    _Module.m_hInstResource = NULL;
    _Module.Term();
    return 0;
}

这个程序运行起来是这个样子:

如你所见,在这里我使用了来自应用程序之外的资源,也就是对CComModule::GetModuleInstance进行了特殊处理。WTL就是对CComModule这个类进行了继承处理而派生出了CAppModule类,使之成为了更适合应用程序使用的模块类。有兴趣的朋友可以参看WTL附带的atlapp.h文件,我这里就不多说了。

“貌合神离”

字典上对这个词的解释是:“表面上很亲密而实际上怀有二心”。在此,我将它用在ATL 3.0与7.0上,用来表示它们俩“用法兼容而实现迥异”的既有事实。不过,对于GUI程序设计而言,你并不需要深入了解这方面的内容。因此我这里列举的,也只是与GUI有关的部分。

  • ATL 3.0之中,CComModule直接继承自_ATL_MODULE;而ATL 7.0之中,CComModule则经历了一串的继承链。
  • 相比之下,ATL 7.0中的CComModule更有COM的味道,譬如它的ModuleInstance、ResourceInstance都可以作为COM组件的property,使用get、put来处理。

当然,ATL毕竟是一个为开发COM组件而构建的Framework,所以ATL 7.0中的atlbase.h之中还包含了更多有关COM开发的工具类。这些内容与本书无关,而且李马也自认现在尚无能力来解说这些内容,所以一并从略了就。

点这里下载本章配套代码



Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1664813

    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章