我想实现一个功能:通过HOOK API ,截获键盘消息"F4",并执行自己的代码,这段代码将自动点击鼠标去复制,某网页上的某个字符串,(全选,并按CTRL+C),然后将剪切板内容复制到内存变量当中。.我这段码是通过EXCEL VBA实现的,调用WINDOWS API 实现。但总是不稳定,我发现有时能复制过来,有时复制不过来,有时确时当前窗口人工选择某字符串时按的CTRL+C 复制内容,不是预期的目标网页上的字符串。问题出在哪呢?? 一直没有想明白。请高手分析一下。多谢!之前是选中字符串的鼠标代码和发送CTRL+C的代码,后面是剪切板内存 SetCursorPos X, y Const MOUSEEVENTF_LEFTDOWN = &H2
Const MOUSEEVENTF_LEFTUP = &H4
Const MOUSEEVENTF_RIGHTDOWN = &H8
Const MOUSEEVENTF_RIGHTUP = &H10
mouse_event MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0
mouse_event MOUSEEVENTF_LEFTUP, 0, 0, 0, 0
mouse_event MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0
mouse_event MOUSEEVENTF_LEFTUP, 0, 0, 0, 0
mouse_event MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0
mouse_event MOUSEEVENTF_LEFTUP, 0, 0, 0, 0 'Sleep 4000
Call keybd_event(17, 0, 0, 0) '//按下ctrl
Call Delay(100)
Call keybd_event(67, 0, 0, 0) '//按下c
Call Delay(100)
Call keybd_event(67, 0, 2, 0) '//松开c
Call Delay(100)
Call keybd_event(17, 0, 2, 0) '//松开ctrl OpenClipboard ByVal 0&
If IsClipboardFormatAvailable(CF_UNICODETEXT) Then
hMem = GetClipboardData(CF_UNICODETEXT)
lpData = GlobalLock(hMem)
nSize = GlobalSize(hMem)
destnation_string= String(nSize, 0)
CopyMemory ByVal StrPtr(destnation_string), ByVal lpData, ByVal nSize
GlobalUnlock hMem
eoms_id = left(eoms_id, InSt(destnation_string, Chr(0)) - 1)
End If
Debug.Print destnation_string
CloseClipboard
Const MOUSEEVENTF_LEFTUP = &H4
Const MOUSEEVENTF_RIGHTDOWN = &H8
Const MOUSEEVENTF_RIGHTUP = &H10
mouse_event MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0
mouse_event MOUSEEVENTF_LEFTUP, 0, 0, 0, 0
mouse_event MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0
mouse_event MOUSEEVENTF_LEFTUP, 0, 0, 0, 0
mouse_event MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0
mouse_event MOUSEEVENTF_LEFTUP, 0, 0, 0, 0 'Sleep 4000
Call keybd_event(17, 0, 0, 0) '//按下ctrl
Call Delay(100)
Call keybd_event(67, 0, 0, 0) '//按下c
Call Delay(100)
Call keybd_event(67, 0, 2, 0) '//松开c
Call Delay(100)
Call keybd_event(17, 0, 2, 0) '//松开ctrl OpenClipboard ByVal 0&
If IsClipboardFormatAvailable(CF_UNICODETEXT) Then
hMem = GetClipboardData(CF_UNICODETEXT)
lpData = GlobalLock(hMem)
nSize = GlobalSize(hMem)
destnation_string= String(nSize, 0)
CopyMemory ByVal StrPtr(destnation_string), ByVal lpData, ByVal nSize
GlobalUnlock hMem
eoms_id = left(eoms_id, InSt(destnation_string, Chr(0)) - 1)
End If
Debug.Print destnation_string
CloseClipboard
我觉得应该有“时间间隔”才行。还有,你在这之前的 SetCursorPos x, y ,传递的坐标值是否正确呢?
你的思路是“全选”、Ctrl+C复制到剪贴板、再获取“剪贴板文本内容”吧!
用 Ctrl+C,是通过“系统机制”来操作的,它会处理好这些,不会有误。
我只发现 VB6的“剪贴板对象”才有这个“不可靠”的问题,在用它来修改“剪贴板内容”时,有时候“不成功”;
但如果先“清空”剪贴板、再“放入新内容”,似乎没有失败的情况。
而你这段代码,值得我“怀疑”的,是你的“鼠标三连击”……
应该是:第1次点击,激活窗口;然后“双击”实现全选 吧!
我觉得你这样的三连击似乎有问题:这个“时间”太短,被操作窗口来不及响应(有可能“漏消息”),
也不排除是“消息翻译”不恰当,导致不能正确操作的可能。你的三连击变成了双击+单击了。
我建议,你在第1次鼠标按下/放开之后,Sleep 500ms以上(系统默认的“双击时间间隔”好像是500ms,可按系统实际值调整),
并且可以在Sleep之后加句 DoEvents。后两次“双击”之间,也许可以不用延时,或可试下延时10到30ms。
你后面的“键盘操作”,不必每次延时100ms,前两个改为延时20ms足够了;“放开按键”的那两步,可不用延时。
键盘钩子回调函数:
Public Function KeyboardCallback(ByVal Code As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
If wParam = WM_KEYUP Then
If Hookstruct.vkCode = VK_F4 Then
my_result = my_copy_string
End If
End Function
end if
你可以试试,在你的 SetCursorPos x, y 那儿“清空”剪贴板,会不会在“操作结束”之后,根本没有复制到东西?
你可以试下:在你的“程序”执行后,再在“记事本”中Ctrl+V,
看看有没有文本粘贴出来?是不是你在网页中选定的内容?
尤其要注意一点:保证你“被操作的网页”,在你程序操作之前,没有“选定内容”。
如果你说的“滞后”现象,是你连续几次“程序操作”造成的,我很怀疑实际是“网页全选”的操作滞后造成。
这儿 my_copy_string 是一个变量,还是一个函数?
如果是“变量”,你要考虑其值是否会是之前存储的结果;
如果是“函数”(就是相当于你主贴中代码“执行结果”),那么你得认真考虑我在6楼说的那些。