其实我不想写关于此类方法的文章,但是提问者还是不少,因此我还是写出来,发链接算了
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
新手要理解本文很费力哦,多努力学习吧,理解力也就学会了。