VB运行时动态注册添加控件的方法

其实我不想写关于此类方法的文章,但是提问者还是不少,因此我还是写出来,发链接算了

 

VB中的控件都是指ActiveX DLL或OCX,这些都是COM组件,如果熟悉API可以调用这个文件输出的注册函数即可。

这个函数是DllRegisterServer,相关的反注册函数是DllUnregisterServer,下面是我写的封装好的函数,在我发布的C/C++的DLL中一般都有输出

//=========================================================================
// 动态注册 ActiveX 控件 LPCTSTR = const char *
//=========================================================================
BOOL __stdcall pfyRegControl(LPCTSTR lpFileName)
{	LPCTSTR lpDllName = lpFileName;				//ActiveX控件的路径及文件名
	HINSTANCE hLib = LoadLibrary(lpDllName);	//装载ActiveX控件
	if (hLib < (HINSTANCE)HINSTANCE_ERROR)
	{	return FALSE;
	}
	FARPROC lpDllEntryPoint;
	lpDllEntryPoint = GetProcAddress(hLib, lpfnRegister);	//获取注册函数DllRegisterServer地址 
	if(lpDllEntryPoint != NULL)					//调用注册函数DllRegisterServer 
	{	if(FAILED((*lpDllEntryPoint)()))
		{	FreeLibrary(hLib); 
			return FALSE; 
		}
		return TRUE;
	}else
	return FALSE; 
} 

//=========================================================================
// 动态卸载 ActiveX 控件
//=========================================================================
BOOL __stdcall pfyUnRegControl(LPCTSTR lpFileName) 
{	LPCTSTR lpDllName = lpFileName;				//ActiveX控件的路径及文件名
	HINSTANCE hLib = LoadLibrary(lpDllName);	//装载ActiveX控件
	if (hLib < (HINSTANCE)HINSTANCE_ERROR)
	{	return FALSE;
	}
	FARPROC lpDllEntryPoint;   
	lpDllEntryPoint = GetProcAddress(hLib, lpfnUnReg);	//获取注册函数DllUnregisterServer地址
	if(lpDllEntryPoint != NULL)					//调用注册函数DllUnregisterServer
	{	if(FAILED((*lpDllEntryPoint)())) 
		{	FreeLibrary(hLib);
			return FALSE; 
		}
		return TRUE; 
	}else
	return FALSE; 
}


对于VB只要用API声明这两个函数即可,按一样的方法调用,当然最简单的是Shell "cmd /c regsvr32 /q abc.dll"之类的命令行

这些也是可以的,重复注册不会造成破坏,只是感觉不爽,因此下面提供一种感觉更舒服的方法

Public Sub Main()   '注意工程的入口函数必须是Sub Main,如果是某个窗体,这个窗体包含未注册的控件则直接出错
    Dim strCom As String
    'frmMain.Controls.Add "MSComctlLib.TreeView", "tv"  '从报错得到progid=MSComctlLib.TreeCtrl.2
    If pfyCheckClass(StrConv("MSComctlLib.TreeCtrl.2", vbUnicode)) = 0 Then
        '类未注册
        strCom = Environ("Windir") & "\mscomctl.ocx"
        If Dir(strCom) = "" Then strCom = Environ("Windir") & "\system32\mscomctl.ocx"
        '不再用Dir函数
        If FileLen(strCom) = 0 Then    '系统没有该文件
            If Dir(App.Path & "\mscomctl.ocx") = "" Then
                MsgBox "缺少组件!程序运行需要如下微软组件:" & vbCrLf & "mscomctl.ocx", vbCritical, "#Error"
                End
            End If
        Else
            FileCopy App.Path & "\mscomctl.ocx", strCom
        End If
        If pfyRegControl("mscomctl.ocx") = 0 Then
            MsgBox "控件: mscomctl.ocx  注册失败!请手动注册该组件!", vbExclamation, "#Error"
            Open App.Path & "\reg.bat" For Output As #1
                Print #1, "rem ======================================"
                Print #1, "rem 游侠组件注册批处理,请双击运行……"
                Print #1, "rem 游侠技术 http://blog.csdn.net/prsniper"
                Print #1, "rem ======================================"
                Print #1, "regsvr32 mscomctl.ocx"
                Print #1, "pause"
            Close #1
            End
        End If
    End If

上面的pfyCheckClass是我封装的根据类名检查某个控件是否注册的函数,其C/C++的源码如下:

//===============================================================
// ActiveX控件类注册状态判断
//===============================================================
INSERT_API BOOL __stdcall pfyCheckClass(const USHORT *lpClass)
{	//S_OK 类标志符检索成功   CO_E_CLASSSTRING 类标志符无效   REGDB_E_WRITEREGDB 写入标志符到注册表出错
	HRESULT hr;
	CLSID clsId;
	hr = CLSIDFromProgID(lpClass, &clsId);
	if(hr == S_OK) return TRUE;
	return FALSE;
}


因为博客改向的原因,VB的代码我就不翻译出来,确实想学习而又不懂C/C++可以联系老朽做交流,呵呵……

 

对于怎么得到类名,除了上面VB代码的测试法,还可以在VB的IDE中点击对象浏览器可以查看到,或者点【查看(View)】->【对象浏览器(Object Browser)】或者按F2

新手要理解本文很费力哦,多努力学习吧,理解力也就学会了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值