加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

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

发布时间:2020-12-16 22:47:14 所属栏目:大数据 来源:网络整理
导读:其实我不想写关于此类方法的文章,但是提问者还是不少,因此我还是写出来,发链接算了 VB中的控件都是指ActiveX DLL或OCX,这些都是COM组件,如果熟悉API可以调用这个文件输出的注册函数即可。 这个函数是DllRegisterServer,相关的反注册函数是DllUnregiste

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

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 /qabc.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") & "system32mscomctl.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,"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

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

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读