通過SDK方式或者Atl方式添加的IE控件(WebBrowser控件)無法響應鍵盤的tab消息,這在輸入表單的時候非常不方便,每次都需要鼠標點擊輸入框,我在網上看過一些文章,據說可以通過IE控件的IDocHostShowUI接口和IDocHostUIHandler2接口獲取響應的消息,不過我試過這些方法,沒成功~_~.於是采用了一種比較偏門的方法:掛鈎鍵盤消息。
首先,設置鍵盤消息處理函數,該函數的功能是獲取鍵盤的輸入鍵信息,如果該鍵是tab鍵,並且是按下狀態,則將該消息發送給IE控件的快捷鍵處理函數進行快捷鍵處理,同樣的,為了能通過回車鍵提交html表單,判斷輸入鍵是回車鍵,並且是按鍵釋放時,將該消息發送給IE控件的快捷鍵處理函數進行快捷鍵處理。
先聲明一個全局的HHOOK句柄
HHOOK h_Keyboard;
消息處理函數如下:
LRESULT CALLBACK KeyboardProc( int code, // hook code WPARAM wParam, // virtual-key code LPARAM lParam // keystroke-message information ) { if(wParam==VK_TAB && GetKeyState(wParam)< 0) { //按下tab鍵 //::MessageBox(NULL, _T("TAB"), _T(""), 0); //以下是獲取瀏覽器對象並像對象發送快捷鍵的代碼,我這里的m_wndIE是AxWindow類型,如果直接用SDK創建IE控件的話,前面的代碼有所不同,但后面的獲取接口的方式是一致的 CWebWindow* pWebWindow = g_webWindow; MSG msg; msg.hwnd = pWebWindow->m_wndIE.m_hWnd; msg.message = WM_KEYDOWN; msg.lParam = lParam; msg.wParam = wParam; HRESULT hr = S_OK; IWebBrowser2Ptr browser; hr = pWebWindow->m_wndIE.QueryControl(__uuidof(IWebBrowser2), (void**)&browser); ATLASSERT(SUCCEEDED(hr)); CComPtr<IDispatch> disp; hr = browser->get_Document(&disp); ATLASSERT(SUCCEEDED(hr)); //CComPtr<IHTMLDocument2> doc; CComQIPtr<IOleInPlaceActiveObject> spInPlace; hr = disp->QueryInterface(__uuidof(IOleInPlaceActiveObject), (void**)&spInPlace); ATLASSERT(SUCCEEDED(hr)); if (spInPlace) bool bRet = (spInPlace->TranslateAccelerator(&msg) == S_OK) ? TRUE : FALSE; } else if (wParam == VK_RETURN && GetKeyState(wParam)> 0) { ///釋放回車鍵 //::MessageBox(NULL, _T("ENTER"), _T(""), 0); ////以下是獲取瀏覽器對象並像對象發送快捷鍵的代碼,我這里的m_wndIE是AxWindow類型,如果直接用SDK創建IE控件的話,前面的代碼有所不同,但后面的獲取接口的方式是一致的 CWebWindow* pWebWindow = g_webWindow; MSG msg; msg.hwnd = pWebWindow->m_wndIE.m_hWnd; msg.message = WM_KEYUP; msg.lParam = lParam; msg.wParam = wParam; HRESULT hr = S_OK; IWebBrowser2Ptr browser; hr = pWebWindow->m_wndIE.QueryControl(__uuidof(IWebBrowser2), (void**)&browser); ATLASSERT(SUCCEEDED(hr)); CComPtr<IDispatch> disp; hr = browser->get_Document(&disp); ATLASSERT(SUCCEEDED(hr)); //CComPtr<IHTMLDocument2> doc; CComQIPtr<IOleInPlaceActiveObject> spInPlace; hr = disp->QueryInterface(__uuidof(IOleInPlaceActiveObject), (void**)&spInPlace); ATLASSERT(SUCCEEDED(hr)); if (spInPlace) bool bRet = (spInPlace->TranslateAccelerator(&msg) == S_OK) ? TRUE : FALSE; } //返回非0值,表示我們已處理此鍵盤消息了 return CallNextHookEx(h_Keyboard,code,wParam,lParam); }
然后,就是設置掛鈎函數,這個放在主函數的初始化部分:
h_Keyboard=SetWindowsHookEx(WH_KEYBOARD,KeyboardProc,hInstance,0);
最后,釋放掛鈎,這個放在主函數的退出之前:
UnhookWindowsHookEx(h_Keyboard);