您的位置:逆风者 VC++ 正文
 添加时间:2008-03-21 原文发表:2008-03-21 人气:140 来源:vckbase.com

本文章共2919字,分2页,当前第2页,快速翻页:
 



MFC中通用控件的初始化

MFC中采用了延迟加载的办法来初始化通用控件.这样,如果程序不使用任何通用控件,则不会加载comctl32.dll.如果使用了任何通用控件,则会在该控件的PreCreateWindow函数中初始化对应的通用控件.这就是使用depends工具查看一个使用了通用控件的MFC程序,一般都看不到有comctl32.dll存在的原因.这里是说一般,如果在你的代码中直接调用了两个初始化函数之一,就会正常链接到comctl32.dll。
逆风编程精品

要在MFC源代码中找到通用控件初始化的地方很简单,只要看看一个使用了通用控件的程序何时加载comctl32.dll就可以了.你可以调试这样一个程序,单步执行或每隔一段代码设置一个断点,然后每次执行后用工具看看exe是否加载了comctl32.dll模块,如此逐步缩小范围,很快就可以找到.查看exe在运行时包含模块的工具很多,比如IceSword或者windows优化大师带的一个进程管理工具都可以.

以控件syslistview32为例.MFC的包装类是CListView.

BOOL CListView::PreCreateWindow(CREATESTRUCT& cs)
{
    return CCtrlView::PreCreateWindow(cs);
}

BOOL CCtrlView::PreCreateWindow(CREATESTRUCT& cs)
{
    ...

    // initialize common controls
    VERIFY(AfxDeferRegisterClass(AFX_WNDCOMMCTLS_REG));
    AfxDeferRegisterClass(AFX_WNDCOMMCTLSNEW_REG);
    ...

    return CView::PreCreateWindow(cs);
}

AfxDeferRegisterClass会根据控件的种类不同,设置不同的参数,然后调用_AfxInitCommonControls,比如下面的代码:
 

init.dwICC = ICC_WIN95_CLASSES;
fRegisteredClasses |= _AfxInitCommonControls(&init, AFX_WIN95CTLS_MASK);

函数_AfxInitCommonControls完成实际的通用控件初始化.

LONG AFXAPI _AfxInitCommonControls(LPINITCOMMONCONTROLSEX lpInitCtrls, LONG fToRegister)
{
    ...
    HINSTANCE hInst = ::LoadLibraryA("COMCTL32.DLL");
    ...
    (FARPROC&)pfnInit = ::GetProcAddress(hInst, "InitCommonControlsEx");

    if (pfnInit == NULL)
    {
        ...
    }
    else if (InitCommonControlsEx(lpInitCtrls))
    {
        ... 
    }

    FreeLibrary(hInst);
    ...
}

这里要说明一下,LoadLibrary和FreeLibrary成对出现,保持了对dll的引用计数不变.只有当对dll的引用计数从0变为1时,才会以DLL_PROCESS_ATTACH调用DLLMain函数,只有dll的引用计数从1变为0时,才会以DLL_PROCESS_DETACH调用DLLMain函数.上面的代码中,除了加载卸载DLL外,还有一次对dll中函数InitCommonControlsEx的调用,正是这个调用引起了系统额外的一次LoadLibrary的调用(注意,如前所述,MFC对这个DLL使用了延迟加载技术,因此,dll不会在程序一启动就被加载,而是延迟到第一次访问dll中的任何函数或数据).这个额外的调用使得对通用控件的注册并没有被后面的FreeLibrary取消.因此,程序在这以后就可以生成通用控件的窗口了.

至于,MFC为何时而采用直接调用,时而采用取函数地址的方法调用InitCommonControlsEx,这个在函数的注释里说的很清楚,是为了适应各种不同的链接选项而已.

水平有限,如有不当之处,请大家指正。


 
本文章更多内容<<上一页 - 1 - 2
相关文章

浅谈输入法编程
多线程管理类
如何实现由列表控件控制的属性表
动态创建控件支持事件响应并可保存与读取
简单录、放音并保存为wav文件程序
I2C通信
文件过滤系统驱动开发Filemon学习笔记
DynamicLayout-VC 6.0对话框动态布局解决方
用命令模式实现对象存储——对象与关系数据
探讨性能测试中的计时问题
基于GDI+的数字图像处理
运动搜索算法之钻石搜索(Ver1.0)
VC6下的GDI+双缓冲
使用SNMP编辑(添加/删除/修改)ARP表
VC6绘制3D饼状图
强制编译时约束
在C++中实现C#的delegate机制
一个工业控制管道流动控件的实现
Thunk 技术的一个改进
直接调用类成员函数地址

相关评论


本文章所属分类:首页 VC++

  热门关键字: