一般來說,一個瀏覽器中大致會存在哪些鍵盤訊息呢?
1、視窗的快速鍵(如菜單上的快速鍵);
2、地址欄等的鍵盤訊息;
3、瀏覽器視窗內。
據此,一個比較理想的方法流程是:用SetWindowsHookEx安裝WH_GETMESSAGE鉤子。這樣可以鉤住進程內所有鍵盤和滑鼠訊息,在得到訊息後,鍵盤訊息和滑鼠訊息分開處理。對於鍵盤訊息,先判斷當前的訊息是否是視窗快速鍵,是的話,執行相應代碼,不是的話,允許存取。然後再看瀏覽器視窗當前是否獲得了焦點,若是的話,再檢查當前訊息是不是瀏覽器內“ActiveObject”的快速鍵,不是的話,允許存取。若瀏覽器視窗沒有得到焦點,那麼直接允許存取。
說了這麼多,到底怎麼做呢?
關鍵點之一,就是要在瀏覽器視窗、地址欄、搜尋欄(假設有)等得到焦點的時候做個標記。這樣在處理鍵盤訊息的時候就根據焦點來決定如何處理。
比如“判斷當前的訊息是否是視窗快速鍵”怎麼實現?
一般用Public Declare Function CreateAcceleratorTable Lib "user32.dll" Alias "CreateAcceleratorTableA" (ByVal lpaccl As Long, ByVal cEntries As Long) As Long
這個函數來建立快速鍵列表。然後用Public Declare Function TranslateAccelerator Lib "user32.dll" Alias "TranslateAcceleratorA" (ByVal hWnd As Long, ByVal hAccTable As Long, ByRef lpMsg As MSG) As Long來檢測。
然而又如何判斷“訊息是不是瀏覽器內的快速鍵”呢?
可用IOleInPlaceActiveObject的TranslateAccelerator來獲得。大致如下:
Public Function FrmTranslateAccelerator(mMsg As Long) As Boolean
Static tMSG As olelib.MSG
Dim tobj As olelib.IOleInPlaceActiveObject
Set tobj = WB
If tobj Is Nothing Then
FrmTranslateAccelerator = False
Else
CopyMemory tMSG, ByVal mMsg, Len(tMSG)
FrmTranslateAccelerator = (tobj.TranslateAccelerator(tMSG) = 0)
End If
End Function
到此為止,如果你很好的記住了當前是哪個對象獲得了焦點,那麼,上述思路即可很好的解決鍵盤訊息難題。
WH_GETMESSAGE鉤子同時得到滑鼠訊息,如需要處理一些滑鼠訊息,這裡是最佳途徑。比如判斷當前滑鼠是否在非客戶區右鍵等等。甚至,流行的“滑鼠手勢”也可在這裡處理。
在上一篇文章中,涉及了IOleInPlaceSite介面。要配合上述代碼,IOleInPlaceSite_GetWindowContext中只需要處理ppDoc As olelib.IOleInPlaceUIWindow即可。因為我們已經處理了需要的鍵盤訊息,所以不需要處理ppFrame As olelib.IOleInPlaceFrame,否則會出現問題。並且有一個嚴重的問題,假設你沒用上述鉤子,使用MDI設計瀏覽器,若不處理ppFrame,則瀏覽器視窗所有快速鍵失效!若處理ppFrame,網頁開啟過程中,會搶佔菜單的焦點。所以,為瞭解決這個辦法,目前看來,最佳途徑就是這個鉤子了。