最近一直在想一个特效,如何达到拖一个文件到网页里,浏览器不自动跳转,并且读出这个文件的信息.呵呵,原本想用javascript的,但是想了想,实在是没什么头绪啊,貌似单纯的javascript很难实现浏览器和系统的交互,于是乎我想起了bho这个玩意,以前一直也没怎么重视,不过看来这次要靠他了.
我想大家一直对一些特效很感兴趣,比如网页一打开就会弹出一个广告,或者一点网页上的某个链接,就会自动打开某个程序(比如迅雷),那么他们是如何实现的呢,其中很多功能的实现都离不开bho.
关于bho,大家可以百度下,这里就不细说了,那么谈谈如何用vb写bho吧,其实大多的bho都是用c++或者delphi来实现的,vb的长项不是这个,但是也不是不可以,用vb就是用com嘛,呵呵,废话少说,看具体步骤:
先用文本编辑器写一个odl文件,保存为IObjectWithSiteTLB.odl,内容如下:
[
uuid(CF9D9B76-EC4B-470D-99DC-AEC6F36A9261),
helpstring("VB IObjectWithSite Interface"),
version(1.0)
]
library IObjectWithSiteTLB
{
importlib("stdole2.tlb");
typedef [public] long GUIDPtr;
typedef [public] long VOIDPtr;
[
uuid(00000000-0000-0000-C000-000000000046),
odl
]
interface IUnknownVB
{
HRESULT QueryInterface(
[in] GUIDPtr priid,
[out] VOIDPtr *pvObj
);
long AddRef();
long Release();
}
[
uuid(FC4801A3-2BA9-11CF-A229-00AA003D7352),
odl
]
interface IObjectWithSite:IUnknown
{
typedef IObjectWithSite *LPOBJECTWITHSITE;
HRESULT SetSite([in] IUnknownVB* pSite);
HRESULT GetSite([in] GUIDPtr priid, [in, out] VOIDPtr* ppvObj);
}
}
代码的大概意思就是导入库,并且声明接口,具体的可以查下odl语法参考.
接着将这个文件拖到MKTYPLIB.EXE(这个文件应该在vb的tools里,没有的可以从网上下个)上,记下生成的IObjectWithSiteTLB.tlb文件地址.
下面打开vb6,新建一个activex dll,引用microsoft internet controls和
你刚才生成的IObjectWithSiteTLB.tlb.
编写下面代码:
Implements IObjectWithSiteTLB.IObjectWithSite
Dim WithEvents IE As InternetExplorer
Dim M_Site As IUnknownVB
Private Sub IE_BeforeNavigate2(ByVal pDisp As Object, URL As Variant, Flags As Variant, TargetFrameName As Variant, PostData As Variant, Headers As Variant, Cancel As Boolean)
If InStr(IE.LocationURL, "http://") Then
If InStr(CStr(URL), ":/") Then
Cancel = True
IE.Document.body.innerhtml = IE.Document.body.innerhtml + CStr(URL)
End If
End IfEnd Sub
Private Sub IObjectWithSite_GetSite(ByVal Priid As IObjectWithSiteTLB.GUIDPtr, PPVobj As IObjectWithSiteTLB.VOIDPtr)
M_Site.QueryInterface Priid, PPVobj
End Sub
Private Sub IObjectWithSite_SetSite(ByVal pSite As IObjectWithSiteTLB.IUnknownVB)
Set M_Site = pSite
Set IE = pSite
End Sub
第一行就是对IObjectWithSiteTLB.IObjectWithSite的接口继承,其他的就是定义类型或者实例化,注意Private Sub IE_BeforeNavigate2里的代码就是我要处理文件拖到网页里的代码,注意url就是即将跳转的地址,在这里就是你拖的文件的文件路径.
写完编译成dll文件,并且用regsvr32注册,注册完后在注册表里的HKCR/clisd/下找到你注册的dll的clisd,在HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/Windows/CurrentVersion/Explorer/Browser Helper Objects/下新建一下以刚才那个dll的clisd为名称的项,这样就算大功告成了,当你再次打开浏览器的时候就会看到效果了.
不过话说回来,从注册到找clisd再到新建的过程是不是有点麻烦啊,其实这些都是可以用代码搞定的,下面我给出代码,一次性解决问题:
在vb6里新建一个exe工程,引用windows script host object model对象,
然后编写以下代码:
Dim wsh As New WshShell
Dim ta As New TLI.TLIApplication, ti As TLI.TypeLibInfo, tc As TLI.CoClassInfo
Private Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, ByVal dwProcessId As Long) As Long
Private Declare Function WaitForSingleObject Lib "kernel32" (ByVal hHandle As Long, ByVal dwMilliseconds As Long) As Long
Private Const PROCESS_ALL_ACCESS = &H1F0FFF
Private Sub Form_Load()
On Error Resume Next
Me.Visible = False
Dim cl As String, pid As Long, h As Long
cl = Command
pid = Shell("cmd /c regsvr32 /s " + cl, vbHide)
h = OpenProcess(PROCESS_ALL_ACCESS, False, pid)
WaitForSingleObject h, -1
cl = Replace(cl, """", "")
Set ti = ta.TypeLibInfoFromFile(cl)
Dim clisd As String
For Each tc In ti.CoClasses
clisd = tc.Guid
wsh.RegWrite "HKLM/SOFTWARE/Microsoft/Windows/CurrentVersion/Explorer/Browser Helper Objects/" + clisd + "/", Null
Next
MsgBox "complete"
End
End Sub
代码都是关于com的调用,很好理解,编译成exe,使用的时候只需将dll文件拖到这个exe上,它便会为你的dll自动注册成bho,然后你再打开浏览器就行了,很方便吧!
当你想删除这个bho的时候,只点击 浏览器工具栏里的 工具-----管理加载项-----启用或禁用加载项,再里面找到你要禁用的bho,点禁用即可.或者直接到注册表的HKLM/SOFTWARE/Microsoft/Windows/CurrentVersion/Explorer/Browser Helper Objects/下删除相应dll的clisd即可.
有关vb编写bho就说到这里了,有什么好的方法和经验还望各位多多分享与交流啊,限于本人水平有限,代码不妥之处,还望赐教.