下面的钩子程序在打开form2的时候,加载钩子;关闭form2的时候,卸载钩子,达到在dhtmledit控件无键盘返回值中用上enter的目的,很好用。 但是当在打开多重窗体的时候,会发生问题。比如打开form2(1),再打开form2(2),则form2(1)的钩子失效。 还有就是,这个时候如果关闭了form2(2),再操作form2(1),会产生错误,程序被全部关闭。 希望哪位大侠帮忙改一改,实现正常使用,非常感谢。 使用键盘钩子
新建一个模块,加入如下代码:
Private Declare Function SetWindowsHookEx Lib "user32" Alias "SetWindowsHookExA" (ByVal idHook As Long, ByVal lpfn As Long, ByVal hmod As Long, ByVal dwThreadId As Long) As Long
Private Declare Function CallNextHookEx Lib "user32" (ByVal hHook As Long, ByVal ncode As Long, ByVal wParam As Long, lParam As Any) As Long
Private Declare Function UnhookWindowsHookEx Lib "user32" (ByVal hHook As Long) As Long
Dim hHook As Long Public Sub BeginHook()
'调用API函数设置钩子函数,2表示键盘钩子
hHook = SetWindowsHookEx(2, AddressOf HookFunc, 0, App.ThreadID)
End Sub
Public Function HookFunc(ByVal ncode As Long, ByVal Key As Long, ByVal Shift As Long) As Long
'如果按键是回车就调用Form里面的函数,13是VK_ENTER的值
If Key = 13 Then
Form1.OnEnter Shift
'返回1表示此消息已经被处理过,并且不调用CallNext...屏蔽后续处理
HookFunc = 1
Else
'不是回车键就调用默认的处理
HookFunc = CallNextHookEx(hHook, ncode, wParam, lParam)
End If
End Function
Public Sub EndHook()
'调用API卸载掉键盘钩子
UnhookWindowsHookEx hHook
End Sub 然后在Form里面增加如下代码:
Private Sub Form_Load()
' 设置钩子函数
BeginHook
End Sub Private Sub Form_Unload(Cancel As Integer)
' 退出前卸载掉钩子
EndHook
End Sub
' 钩子函数会调用此函数通知按键按下
Public Sub OnEnter(ByVal Shift As Long)
MsgBox Shift
End Sub
新建一个模块,加入如下代码:
Private Declare Function SetWindowsHookEx Lib "user32" Alias "SetWindowsHookExA" (ByVal idHook As Long, ByVal lpfn As Long, ByVal hmod As Long, ByVal dwThreadId As Long) As Long
Private Declare Function CallNextHookEx Lib "user32" (ByVal hHook As Long, ByVal ncode As Long, ByVal wParam As Long, lParam As Any) As Long
Private Declare Function UnhookWindowsHookEx Lib "user32" (ByVal hHook As Long) As Long
Dim hHook As Long Public Sub BeginHook()
'调用API函数设置钩子函数,2表示键盘钩子
hHook = SetWindowsHookEx(2, AddressOf HookFunc, 0, App.ThreadID)
End Sub
Public Function HookFunc(ByVal ncode As Long, ByVal Key As Long, ByVal Shift As Long) As Long
'如果按键是回车就调用Form里面的函数,13是VK_ENTER的值
If Key = 13 Then
Form1.OnEnter Shift
'返回1表示此消息已经被处理过,并且不调用CallNext...屏蔽后续处理
HookFunc = 1
Else
'不是回车键就调用默认的处理
HookFunc = CallNextHookEx(hHook, ncode, wParam, lParam)
End If
End Function
Public Sub EndHook()
'调用API卸载掉键盘钩子
UnhookWindowsHookEx hHook
End Sub 然后在Form里面增加如下代码:
Private Sub Form_Load()
' 设置钩子函数
BeginHook
End Sub Private Sub Form_Unload(Cancel As Integer)
' 退出前卸载掉钩子
EndHook
End Sub
' 钩子函数会调用此函数通知按键按下
Public Sub OnEnter(ByVal Shift As Long)
MsgBox Shift
End Sub
解决方案 »
- 送分100分:关于UNION的简单问题
- 怎么样将DBF文件的数据读入到griddata控件中?
- 如何编程创建Access数据库并加上密码保护?
- 可否在vb5里使用ado data控件和datagrid 控件?
- ProgressBar??
- 代码修改很简单的哦,可是我不会:(
- 我创建了一个二维的动态数组,如何动态变化大小?
- 基本问题,怎样去掉窗体左上角的Controlbox?
- 50分大放送!!http://www.csdn.net/expert/Topic/476/476550.shtm!!(这20分照给)。急!!
- 请教VB串口通讯读数据
- DataReport打印图片
- VB如何编写代码绘制饼状图?
if not hooked then
' 设置钩子函数
BeginHook
hooked=true
endif
End Sub 在整个程序退出的时候才unhook.
If Key = 13 Then
Form1.OnEnter Shift‘这里出错
HookFunc = 1
Else
HookFunc = CallNextHookEx(hHook, ncode, wParam, lParam)
End If
End Function 你看这个出错是因为无法获得究竟是哪个窗体form1调用它,因为有好几个form1,有form1(0),form1(1),form1(2)......,如何处理这问题呢。
Public Sub BeginHook(frm As Form4)
Set objFrm = frm
hHook = SetWindowsHookEx(2, AddressOf HookFunc, 0, App.ThreadID)
End Sub上面语句发现定义不了,愿闻其详?
Private Sub Form_Load()
if not hooked then
' 设置钩子函数
BeginHook
hooked=true
endif
End Sub
BeginHook(i)那么模块中如何定义呢?
Private objFrm As Form4
Public Sub BeginHook(frm As Form4)
Set objFrm = frm
Public Function HookFunc(ByVal ncode As Long, ByVal Key As Long, ByVal Shift As Long,byval formindex as long) As Long
BeginHook(i) 那么模块中如何定义呢?
Private objFrm As Form4
Public Sub BeginHook(frm As Form4)
Set objFrm = frm
Public Function HookFunc(ByVal ncode As Long, ByVal Key As Long, ByVal Shift As Long,byval formindex as long) As Long
然后根据formindex传进来的值判断要怎么做。
①如何在多个窗体的无序 BeginHook/EndHook 中只需要一对 SetWindowsHookEx/UnhookWindowsHookEx。
②在 HookFunc 中应该调用哪个窗体的 OnEnter。修改如下
'Module
Option ExplicitPrivate Const WH_KEYBOARD As Long = 2
Private Const VK_RETURN As Long = &HDPrivate Declare Function SetWindowsHookEx Lib "user32" Alias "SetWindowsHookExA" _
(ByVal idHook As Long, ByVal lpfn As Long, ByVal hmod As Long, ByVal dwThreadId As Long) As Long
Private Declare Function CallNextHookEx Lib "user32" _
(ByVal hHook As Long, ByVal ncode As Long, ByVal wParam As Long, lParam As Any) As Long
Private Declare Function UnhookWindowsHookEx Lib "user32" (ByVal hHook As Long) As LongPublic ActiveForm As Form '当前活动窗体Private lHookCount As Long 'BeginHook/EndHook 计数
Private hHook As LongPublic Sub BeginHook()
If lHookCount = 0 Then '仅第一个需要执行挂钩
hHook = SetWindowsHookEx(WH_KEYBOARD, AddressOf HookFunc, 0, App.ThreadID)
Debug.Print "SetWindowsHookEx()"
End If
lHookCount = lHookCount + 1
End SubPublic Sub EndHook()
lHookCount = lHookCount - 1
If lHookCount = 0 Then '仅最后一个才执行解除挂钩
UnhookWindowsHookEx hHook
Debug.Print "UnhookWindowsHookEx()"
End If
End SubPublic Function HookFunc(ByVal ncode As Long, ByVal Key As Long, ByVal Shift As Long) As Long
If (Key = VK_RETURN) And (Not ActiveForm Is Nothing) Then
ActiveForm.OnEnter Shift
HookFunc = 1
Else
HookFunc = CallNextHookEx(hHook, ncode, Key, Shift)
End If
End Function'Form
Option ExplicitPublic Sub OnEnter(ByVal Shift As Long)
MsgBox Shift, , Me.Caption '区分出调用了哪个实例的 OnEnter"
End SubPrivate Sub Form_Activate()
Set ActiveForm = Me
End SubPrivate Sub Form_Deactivate()
Set ActiveForm = Nothing
End SubPrivate Sub Form_Load()
Me.Caption = "hWnd = &H" & Hex(Me.hWnd) '用来标记不同的窗体实例
BeginHook
End SubPrivate Sub Form_Unload(Cancel As Integer)
If ActiveForm Is Me Then
Set ActiveForm = Nothing
End If
EndHook
End Sub
'模块: ########################################################################Option ExplicitPublic mk1(100000) As Integer '窗体名称,用来判断是否打开
Public mk3 As Double '用来对打开的窗体进行转换是哪个
Public mk4 As Double '用来对打开的窗体进行转换是哪个
Public hooked As Boolean '是否有钩子的判断Private Declare Function SetWindowsHookEx Lib "user32" Alias "SetWindowsHookExA" (ByVal idHook As Long, ByVal lpfn As Long, ByVal hmod As Long, ByVal dwThreadId As Long) As Long
Private Declare Function CallNextHookEx Lib "user32" (ByVal hHook As Long, ByVal ncode As Long, ByVal wParam As Long, lParam As Any) As Long
Private Declare Function UnhookWindowsHookEx Lib "user32" (ByVal hHook As Long) As Long
Dim hHook As Long
Private objFrm As Form1
Public Sub BeginHook(frm As Form1)
Set objFrm = frm
'调用API函数设置钩子函数,2表示键盘钩子
hHook = SetWindowsHookEx(2, AddressOf HookFunc, 0, App.ThreadID)
End Sub
Public Function HookFunc(ByVal ncode As Long, ByVal Key As Long, ByVal Shift As Long) As Long
'如果按键是回车就调用Form里面的函数,13是VK_ENTER的值
If Key = 17 Then
objFrm.OnEnter Shift
'返回1表示此消息已经被处理过,并且不调用CallNext...屏蔽后续处理
HookFunc = 1
Else
'不是回车键就调用默认的处理
HookFunc = CallNextHookEx(hHook, ncode, Key, Shift)
End If
End Function
Public Sub EndHook()
'调用API卸载掉键盘钩子
UnhookWindowsHookEx hHook
End Sub
'form2: 一个treeview ############################################################################
Dim newfrm(100) As Form1Private Sub form_load()
For I = 1 To 25
TreeView1.Nodes.Add , tvwChild, "p" & CStr(I), "图书目录索引第" & CStr(I) & "页", 0
Next I
End Sub
Private Sub TreeView1_Click()
mk4 = Right(TreeView1.SelectedItem.Key, Len(TreeView1.SelectedItem.Key) - 1) '用关键字作为窗体名称
If Not mk1(mk4) Then '判断是否已打开此窗体,如果没有打开
mk1(mk4) = True '在全局变量中设置此窗体已打开标志
mk3 = mk4 '将ID值传给全局变量,form1中接收以判断是哪个的ID Set newfrm(mk4) = New Form1
newfrm(mk4).Show
newfrm(mk4).Caption = TreeView1.SelectedItem.Text
End IfEnd Sub'form1: 一个textbox,一个Dhtmledit,一个command ##########################################################################
Dim kis
Dim ss
Private Const WM_PASTE = &H302
Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
Private Declare Function GetKeyState Lib "user32" (ByVal nVirtKey As Long) As Integer
Private Sub form_load()
If Not hooked Then
BeginHook Me ' 设置钩子函数
hooked = True
End IfEnd SubPrivate Sub Form_Unload(Cancel As Integer)
mk1(mk4) = False '退出时将此窗体情况设为非打开状态##########################################
flag = True
For ss = LBound(mk1) To UBound(mk1)
flag = flag And Not (mk1(ss))
If Not (flag) Then
Exit Sub
Else
EndHook '退出前卸载掉钩子
End If
Next ssEnd Sub
' 钩子函数会调用此函数通知按键按下
Public Sub OnEnter(ByVal Shift As Long)
If Shift = -1055064063 And kis = "0" Then '只允许键盘响应一次
kis = "1"
Call comm
Else
kis = "0"
End If
End SubFunction comm()
Text1.Text = "操作的是我"
End FunctionPrivate Sub Command1_Click()
Call comm
End Sub
重新搞了一个,真的可行呀。请高手再说明一下,如何实现选择enter和ctrl操作有效?
而且 OnEnter 中更改了 kis 变量的值看不出什么作用。