WTL编程--运行框架

              WTL的历史和渊源就不介绍了。如果要谈论一门编程语言,基础的内容却必不可少--总得有些东西把所有的一切都串起来才行。

      我从接触WTL到今天,大概有7-8年了。6年前,我决定放弃了使用多年的MFC彻底转向WTL,做这个决定的一个基本的原因就是自由,当你使用WTL编码,你可以感受到操作系统的律动,你会觉得自己在跟操作系统协作。你知道自己在做什么,也能够预计即将发生什么,这感觉相当好。

     那么WTL都能做什么呢?答案是--任何事情。如果你觉得某样事情还不能做,那基本上只是表示你还有东西需要学,仅此而已。

            我目前使用的库是WTL8.1,由于我必须使用window 2003 server版的操作系统,有些东西我甚至还没有去尝试。 好吧,我们还是进入正题,看看WTL究竟是怎么回事,他是怎么开始的,如何工作?

             在开始之前,希望你已经了解Win32 windows编程,起码你知道,向windows注册一个窗口,消息循环,消息处理诸如此类的事情。如果你使用的是VS2008或者更高版本的开发环境,你可以生成一个win32程序看看。

             WTL实际上必须完成那些基础工作,我们现在来看看她是怎么做的。


CAppModule _Module;

int Run(LPTSTR /*lpstrCmdLine*/ = NULL, int nCmdShow = SW_SHOWDEFAULT)
{
	CMessageLoop theLoop;
	_Module.AddMessageLoop(&theLoop);

	CMainFrame wndMain;

	if(wndMain.CreateEx() == NULL)
	{
		ATLTRACE(_T("Main window creation failed!\n"));
		return 0;
	}

	wndMain.ShowWindow(nCmdShow);

	int nRet = theLoop.Run();

	_Module.RemoveMessageLoop();
	return nRet;
}

int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/, LPTSTR lpstrCmdLine, int nCmdShow)
{
	HRESULT hRes = ::CoInitialize(NULL);
// If you are running on NT 4.0 or higher you can use the following call instead to 
// make the EXE free threaded. This means that calls come in on a random RPC thread.
//	HRESULT hRes = ::CoInitializeEx(NULL, COINIT_MULTITHREADED);
	ATLASSERT(SUCCEEDED(hRes));

	// this resolves ATL window thunking problem when Microsoft Layer for Unicode (MSLU) is used
	::DefWindowProc(NULL, 0, 0, 0L);

	AtlInitCommonControls(ICC_COOL_CLASSES | ICC_BAR_CLASSES);	// add flags to support other controls

	hRes = _Module.Init(NULL, hInstance);
	ATLASSERT(SUCCEEDED(hRes));

	int nRet = Run(lpstrCmdLine, nCmdShow);

	_Module.Term();
	::CoUninitialize();

	return nRet;
}


         当你用WTL向导建立一个SDI程序,你会看到向导产生了这样的代码。开始的时候,你大概知道也许就可以了,但是总究有一天你会想去弄明白这些代码的意义。这个程序框架所带来的效果,就是你只需要专注去处理   CMainFrame 这个类就行了。就算你不管上面这些代码,程序也会运行的很好。

          将目光放在_tWinMain ,因为这里是整个程序的入口点。

        1. CoInitializeEx是Windows提供的API函数,为当前线程初始化COM库并设置并发模式。应用程序调用com库中的函数(除CoGetMalloc内存分配函数)之前必须初始化com库。在应用程序中使用COM库,至少要调用一次CoInitializeEx函数(通常也就调用一次)。如果传入参数的并发标志相同,单个线程也可以多次调用该函数,但后来有效的调用将返回 S_FALSE。在正常关闭COM库情况下,每一个CoInitialize 或者CoInitializeEx的成功的调用(也包含返回S_FALSE的调用),都必须用通Uninitialize函数来结束。

       使用函数 CoInitializeEx的代码的前面需要包含于处理标志 #define _WIN32_DCOM

     基于线程的并发模式一旦设置,将不能再改变。一个线程上调用CoInitializeEx如果与原来调用设置的并发模式不一致,将会失败并返回RPC_E_CHANGED_MODE。

     2.  注册通用控件(AtlInitCommonControls):

       InitCommonControlsex

 

         InitCommonControlsex
         函数原形:BOOL WINAPI InitCommonControlsEx(LPINITCOMMONCONTROLSEX lpInitCtrls);
               pInitCtrls参数指向一个INITCOMMONCONTROLSEX结构:
typedef struct tagINITCOMMONCONTROLSEX {
DWORD dwSize; // size of this structure结构长度
DWORD dwICC; // flags indicating which classes to be initialized需要初始化的类
} INITCOMMONCONTROLSEX, *LPINITCOMMONCONTROLSEX;
结构中的dwICC字段指定了需要注册的扩展通用控件类,与InitCommonControls注册所有它支持的通用控件类不同,InitCommonControlsEx函数只注册dwICC字段指明的扩展通用控件类,字段可以是下面取值的组合:
● ICC_BAR_CLASSES——注册工具栏、状态栏、Trackbar和Tooltip类。
● ICC_COOL_CLASSES——注册Rebar类。
● ICC_DATE_CLASSES——注册Date and Time Picker类。
● ICC_HOTKEY_CLASS——注册Hot Key类。
● ICC_INTERNET_CLASSES——注册IP Address Picker类。
● ICC_LISTVIEW_CLASSES——注册ListView和Header类。
● ICC_PAGESCROLLER_CLASS——注册Pager类。
● ICC_PROGRESS_CLASS——注册Progress Bar类。
● ICC_TAB_CLASSES——注册Tab和Tooltip类。
● ICC_TREEVIEW_CLASSES——注册TreeView和Tooltip类。
● ICC_UPDOWN_CLASS——注册Up-Down类。
● ICC_USEREX_CLASSES——注册ComboBoxEx类。

● ICC_WIN95_CLASSES——注册InitCommonControls函数注册的所有类。
InitCommonControlsEx函数是InitCommonControls函数的扩充


消息循环类:CMessageLoop

        观察一下第一个函数Run,它在 _tWinMain 中被调用, 这个地方用来处理命令行和初始化问题,例如建立特定的窗口并设置窗口的状态。这个Run函数内部,首先建立一个一个消息循环对象,把它附加给实体全局变量,由于实体全局变量已经初始化, 也就是线程已经运行, 这时候定义 CMainFrame wndMain, 并且建立这个窗口,然后显示他,最后开启消息循环函数的Run,观察一下 CMessageLoop 分类里面的Run函数,对比win32程序,看上几遍,你应该就已经理解这里发生了什么事情了。


全局变量 CAppModule _Module

       因为目前还不需要深究深层的运行的机制。这里就简单的说一下,能理解就可以了。所谓实体,其实就是一个进程,也就是指一个运行的程序。在windows下,它有自己的运行环境,有自己的独立内存空间,有自己的消息循环。大致看一下CAppModule 这个类就知道了。他有消息循环,系统设置改变通知,空闲处理,模块也有个初始化和释放的功能要调用,大致可以理解为创建线程和销毁线程的作用。而在这两者之间,就是消息循环了,我们编写应用的全部工作就在这个阶段。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值