分享
 
 
 

Common Control - The VB Way (1)

王朝vb·作者佚名  2006-01-08
窄屏简体版  字體: |||超大  

Common Control: The VB Way!

子夜软件工作室

“救救我!为什么我做的小程序用VB安装向导打包后变得那么大?”我们几乎可以在所有的VB论坛上看到这样的帖子。这个糟糕的结果源自VB方便的开发方式:一些VB程序员几乎毫不节制地使用ActiveX控件,而安装向导只是一个没有知觉的程序,它把那些ActiveX控件全部加入发行包——于是你就会跑到网上发帖子求救。

怎么办?简单的方法是用UPX压缩EXE、DLL,但是治标不治本。这篇文章将告诉你或许可以“治本”的方法——如果你的程序需要用到一些Common Control而不得不带上MSCOMCTL.OCX、MSCOMCT2.OCX,我们可以帮你甩掉这1.22MB的包袱!

这就是Common Control: The VB Way!

一、 准备知识

在具体讲述怎么脱离Microsoft Common Control ActiveX控件创建你想要的东西前,我们需要有一点准备知识。

一、 Windows 消息循环基本原理。

这不是本文的主题,但却是最重要的基础知识,如果你不太明白,最好找基本的C++ for Windows的书看看先。

二、 Visual Basic 变量指针和函数指针。

这么说很勉强,因为在VB中我们只能获得地址,要像C那样灵活使用指针似乎不可能。下面详细介绍三个函数和一个操作符,他们都是VB6内置的,无需声明:

VarPtr(Ptr As Any)函数

这个函数返回一个变量(或者是数组元素)的地址。通过这个地址,我们将能够直接访问里面的内容。参数Ptr是任意变量或者数组元素。对于字符串变量,它返回这个变量的ANSI Buffer地址。

StrPtr(Ptr As String)函数

这个函数返回一个字符串变量的Unicode Buffer地址,请注意和VarPtr()的区别。参数Ptr是任意字符串变量。

ObjPtr(Ptr As Unknown)函数

这个函数专门用来获得VB对象变量的地址。

AddressOf操作符

返回一个标准模块中Sub或Function的地址。使用这个操作符有一个小技巧:这个操作符无法直接赋值给变量(它只能用于函数参数中),所以,为了把一个Function的地址存放在变量中,我们需要这样一个Dummy函数:

Public Function ProcAddr(ByVal lpProc As Long) As Long

ProcAddr = lpProc

End Function

这样,我们就可以把Test()函数的地址保存在lpTest变量中:

lpTest = ProcAddr(AddressOf Test)

三、 API函数、常量的声明

由于篇幅有限,在下文中,所有的API函数、常量我们均不列出声明代码。您可以从http://www.greatmidnight.com/downloads/bintool/wintlb.zip和http://www.greatmidnight.com/downloads/bintool/tl_comctl.zip下载到常用Win32API和Common Control 5.80的函数、常量声明。这是两个Type Library 文件,您可以从VB的“Project(工程)——Reference(引用)”菜单中添加对这两个文件的引用,这样您就无需手工声明常用的Win32 API、Common Control 5.80函数、常量了。

二、 获取当前系统Common Control的版本

在使用Common Control之前,你必须弄清楚当前系统安装的是哪个版本——有许多新特性是自Common Control 5.x之后才加入的,对于旧版本使用这些特性会有什么后果?自己猜猜。本节我们就来讲如何获得ComCtl32.DLL的版本号。

许多Windows Shell的动态连接库都有这么一个函数:DllGetVersion()。我编写了下面这个函数来获得指定Shell动态连接库的版本号:

Public Function GetDllVersion(ByVal DllName As String, _

ByRef MajorVersion As Long, _

ByRef MinorVersion As Long, _

ByRef BuildNumber As Long, _

ByRef PlatformID As Long, _

Optional ByVal bDefaultIE3 As Boolean = True) As Boolean

' 此函数用于获得 Windows 的 Shell32.DLL 等 DLL 的版本信息。

On Local Error GoTo Shell32VerErr

Dim SecurityAttr As SECURITY_ATTRIBUTES

Dim hThread As Long, ThreadID As Long

Dim hModule As Long, lpThreadAddr As Long

Dim VerInfo As DLLVERSIONINFO

Dim ExitCode As Long

Dim ErrorOccurred As Integer

ErrorOccurred = 0

' 先要装入 DLL。

hModule = LoadLibraryEx(DllName, vbNull, 0)

If hModule > 0 Then

' 然后找到函数 DllGetVersion() 的地址。

lpThreadAddr = GetProcAddress(hModule, "DllGetVersion")

If lpThreadAddr > 0 Then

With SecurityAttr

.lpSecurityDescriptor = 0

.bInheritHandle = 0

.nLength = Len(SecurityAttr)

End With

VerInfo.cbSize = Len(VerInfo)

' 真可惜!VB 无法通过地址直接调用函数,所以只好通过建立一个线程的方法来代替。

hThread = CreateThread(SecurityAttr, 0, ByVal lpThreadAddr, _

VerInfo, 0, ThreadID)

If hThread > 0 Then

' 然后等待 DllGetVersion() 返回。

Do

GetExitCodeThread hThread, ExitCode

Loop Until ExitCode <> STILL_ACTIVE

CloseHandle hThread ' 关闭线程。

Else

ErrorOccurred = 3 ' 建立线程出错。

End If

Else

ErrorOccurred = 2 ' 找不到 DllGetVersion() 入口地址。

End If

FreeLibrary hModule ' 释放 DLL。

Else

ErrorOccurred = 1 ' 无法装入 DLL。

End If

If Not ErrorOccurred Then

With VerInfo

MajorVersion = .dwMajorVersion

MinorVersion = .dwMinorVersion

BuildNumber = .dwBuildNumber

PlatformID = .dwPlatformID

End With

ElseIf ErrorOccurred = 2 And bDefaultIE3 Then

' 找不到入口地址,说明是 IE 3.0 的 4.0 版 Shell32。

MajorVersion = 4: MinorVersion = 0: BuildNumber = 0: PlatformID = -1

Else

GoTo Shell32VerErr ' 无法预料的错误……

End If

GetDllVersion = True

Exit Function

Shell32VerErr:

GetDllVersion = False

End Function

使用“comctl32.dll”作为第一个参数调用这个函数,我们就可以获得它的版本号了。在我的系统中,MajorVersion、MinorVersion、BuildNumber将分别是:5、81、4522,即Common Control版本:5.81.4522。

在确认系统中的Common Control是5.x版本后,我们就可以开始下面的正活儿了!

(待续……)

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有