HOOK 实现剪贴板功能异常。

sky_9933 2018-01-28 03:48:53
我想实现一个功能:通过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
...全文
954 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
舉杯邀明月 2018-01-30
  • 打赏
  • 举报
回复
你4楼的代码: my_result = my_copy_string 这儿 my_copy_string 是一个变量,还是一个函数? 如果是“变量”,你要考虑其值是否会是之前存储的结果; 如果是“函数”(就是相当于你主贴中代码“执行结果”),那么你得认真考虑我在6楼说的那些。
舉杯邀明月 2018-01-30
  • 打赏
  • 举报
回复
我感觉你说的“滞后”就不合理! 你可以试试,在你的 SetCursorPos x, y 那儿“清空”剪贴板,会不会在“操作结束”之后,根本没有复制到东西? 你可以试下:在你的“程序”执行后,再在“记事本”中Ctrl+V,   看看有没有文本粘贴出来?是不是你在网页中选定的内容? 尤其要注意一点:保证你“被操作的网页”,在你程序操作之前,没有“选定内容”。 如果你说的“滞后”现象,是你连续几次“程序操作”造成的,我很怀疑实际是“网页全选”的操作滞后造成。
舉杯邀明月 2018-01-29
  • 打赏
  • 举报
回复
我觉得不必调用 EmptyClipboard 。 你的思路是“全选”、Ctrl+C复制到剪贴板、再获取“剪贴板文本内容”吧! 用 Ctrl+C,是通过“系统机制”来操作的,它会处理好这些,不会有误。   我只发现 VB6的“剪贴板对象”才有这个“不可靠”的问题,在用它来修改“剪贴板内容”时,有时候“不成功”;   但如果先“清空”剪贴板、再“放入新内容”,似乎没有失败的情况。 而你这段代码,值得我“怀疑”的,是你的“鼠标三连击”…… 应该是:第1次点击,激活窗口;然后“双击”实现全选 吧! 我觉得你这样的三连击似乎有问题:这个“时间”太短,被操作窗口来不及响应(有可能“漏消息”),   也不排除是“消息翻译”不恰当,导致不能正确操作的可能。你的三连击变成了双击+单击了。 我建议,你在第1次鼠标按下/放开之后,Sleep 500ms以上(系统默认的“双击时间间隔”好像是500ms,可按系统实际值调整),   并且可以在Sleep之后加句 DoEvents。后两次“双击”之间,也许可以不用延时,或可试下延时10到30ms。 你后面的“键盘操作”,不必每次延时100ms,前两个改为延时20ms足够了;“放开按键”的那两步,可不用延时。
sky_9933 2018-01-29
  • 打赏
  • 举报
回复
原因:hMem = GetClipboardData(CF_UNICODETEXT) ,这条指令得到的是前一个剪切板中的内容,而前一条语句发出的"CTRL+C"事件,,操作系统将这步操作给缓存下来了,它没有立即执行复制字符串到剪切板的操作,而是先执行了“hMem = GetClipboardData(CF_UNICODETEXT) ”,这行代码。或者认为CTRL+C 事件发生后,操作系统是需要一定的时间将选定的字符串从进程A复制到剪切板中,而下面的GetClipboardData,执行的极快,所以得到的还是旧的。这样一分析就对上账了,肯定是会有滞后的现象发生。还请高手指正我的分析是否有道理 ?
sky_9933 2018-01-29
  • 打赏
  • 举报
回复
问题不在这里。事实上CTRL+C操作,已经将内容复制到剪切板里了,下次我再按F4就是我前一次点F4复制的内容。 我确认它已经是成功复制了指定的字符串,但就是滞后了一次。每次都是获取到前一次剪切板中的内容。此规律我已经反复试验过了,100%是这样的。我怀疑这个与钩子机制有关。 键盘钩子回调函数: 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
sky_9933 2018-01-28
  • 打赏
  • 举报
回复
确认与这个mouse_event无关。我就是想让它点3下鼠标,将字符串全选。这步是我预期的,没有问题。我还发现一个规律,我点F4,时,它复制到变量中的不是我选中并按CTRL+C的内容,而是点F4之前,先前的剪切板内容中的原有内容,而再点F4,就是我预期字符串,其实是上一步点F4 复制的内容。请问在 OpenClipboard 调用前,是要先调用一下:“EmptyClipboard”吗 ?
舉杯邀明月 2018-01-28
  • 打赏
  • 举报
回复
你的连续几个mouse_event,这有问题吧! 我觉得应该有“时间间隔”才行。 还有,你在这之前的 SetCursorPos x, y ,传递的坐标值是否正确呢?

2,462

社区成员

发帖
与我相关
我的任务
社区描述
VBA(Visual Basic for Applications)是Visual Basic的一种宏语言,是在其桌面应用程序中执行通用的自动化(OLE)任务的编程语言。
社区管理员
  • VBA
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧