我想實作一個功能:通過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
uj5u.com熱心網友回復:
你的連續幾個mouse_event,這有問題吧!我覺得應該有“時間間隔”才行。
還有,你在這之前的 SetCursorPos x, y ,傳遞的坐標值是否正確呢?
uj5u.com熱心網友回復:
確認與這個mouse_event無關。我就是想讓它點3下滑鼠,將字串全選。這步是我預期的,沒有問題。我還發現一個規律,我點F4,時,它復制到變數中的不是我選中并按CTRL+C的內容,而是點F4之前,先前的剪切板內容中的原有內容,而再點F4,就是我預期字串,其實是上一步點F4 復制的內容。請問在 OpenClipboard 呼叫前,是要先呼叫一下:“EmptyClipboard”嗎 ?uj5u.com熱心網友回復:
我覺得不必呼叫 EmptyClipboard 。你的思路是“全選”、Ctrl+C復制到剪貼板、再獲取“剪貼板文本內容”吧!
用 Ctrl+C,是通過“系統機制”來操作的,它會處理好這些,不會有誤。
我只發現 VB6的“剪貼板物件”才有這個“不可靠”的問題,在用它來修改“剪貼板內容”時,有時候“不成功”;
但如果先“清空”剪貼板、再“放入新內容”,似乎沒有失敗的情況。
而你這段代碼,值得我“懷疑”的,是你的“滑鼠三連擊”……
應該是:第1次點擊,激活視窗;然后“雙擊”實作全選 吧!
我覺得你這樣的三連擊似乎有問題:這個“時間”太短,被操作視窗來不及回應(有可能“漏訊息”),
也不排除是“訊息翻譯”不恰當,導致不能正確操作的可能。你的三連擊變成了雙擊+單擊了。
我建議,你在第1次滑鼠按下/放開之后,Sleep 500ms以上(系統默認的“雙擊時間間隔”好像是500ms,可按系統實際值調整),
并且可以在Sleep之后加句 DoEvents。后兩次“雙擊”之間,也許可以不用延時,或可試下延時10到30ms。
你后面的“鍵盤操作”,不必每次延時100ms,前兩個改為延時20ms足夠了;“放開按鍵”的那兩步,可不用延時。
uj5u.com熱心網友回復:
問題不在這里。事實上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
uj5u.com熱心網友回復:
原因:hMem = GetClipboardData(CF_UNICODETEXT) ,這條指令得到的是前一個剪切板中的內容,而前一條陳述句發出的"CTRL+C"事件,,作業系統將這步操作給快取下來了,它沒有立即執行復制字串到剪切板的操作,而是先執行了“hMem = GetClipboardData(CF_UNICODETEXT) ”,這行代碼。或者認為CTRL+C 事件發生后,作業系統是需要一定的時間將選定的字串從行程A復制到剪切板中,而下面的GetClipboardData,執行的極快,所以得到的還是舊的。這樣一分析就對上賬了,肯定是會有滯后的現象發生。還請高手指正我的分析是否有道理 ?uj5u.com熱心網友回復:
我感覺你說的“滯后”就不合理!
你可以試試,在你的 SetCursorPos x, y 那兒“清空”剪貼板,會不會在“操作結束”之后,根本沒有復制到東西?
你可以試下:在你的“程式”執行后,再在“記事本”中Ctrl+V,
看看有沒有文本粘貼出來?是不是你在網頁中選定的內容?
尤其要注意一點:保證你“被操作的網頁”,在你程式操作之前,沒有“選定內容”。
如果你說的“滯后”現象,是你連續幾次“程式操作”造成的,我很懷疑實際是“網頁全選”的操作滯后造成。
uj5u.com熱心網友回復:
你4樓的代碼: my_result = my_copy_string這兒 my_copy_string 是一個變數,還是一個函式?
如果是“變數”,你要考慮其值是否會是之前存盤的結果;
如果是“函式”(就是相當于你主貼中代碼“執行結果”),那么你得認真考慮我在6樓說的那些。
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/50033.html
標籤:VBA
