最近被一个老掉牙的IE问题困扰了。
原因是这样,webbrowser控件无法响应百度首页那个下拉框。
网上查了下,说是要在消息循环里响应IOleInPlaceActiveObject::TranslateAccelerator
if (CheckMessage(msg)) {
MSG message = msg;
//message.hwnd = g_ie_hwnd_test;
IDispatch* disp = NULL;
if (g_wb->GetWebBrowser()->get_Document(&disp) != S_OK)
continue;
IOleInPlaceActiveObject* oipao = NULL;
if (disp->QueryInterface(IID_IOleInPlaceActiveObject, reinterpret_cast<void**>(&oipao)) == S_OK && oipao != NULL) {
oipao->TranslateAccelerator(&message);
oipao->Release();
}
disp->Release();
照做了以后,发现某些网页的textarea,例如Javascript在线解压缩 - 在线工具
按向下键,光标会下移动两行…
于是我用SetWindowLongPtr,hook了ie的窗口消息响应函数,然后把WM_KEYDOWN给禁用了。
这样做了以后,光标确实不会移动两行,但向下键也不会让页面滚动了。
这块把我卡住很久,甚至还翻了IE源码看了看。最后,我发现mfc里的chtmlview,居然是能正确处理这个问题的。微软这群屌毛,他们自己的东西当然知道怎么处理,但mfc源码那么多,怎么才能找到问题的关键呢?
最后,无意中,我发现MFC里这句话:
没错,这里也是把先把消息派发给TranslateAccelerator。但原来这里是要判断返回值的。也就是说,我刚才没判断返回值,所以TranslateAccelerator处理完后又给IE窗口消息函数了。导致光标被移动了两次。
翻了下ie6源码,我发现TranslateAccelerator里面会处理光标移动,但也会处理页面滚动。我猜测是IE高版本的TranslateAccelerator和ie6的逻辑不一样。高版本的TranslateAccelerator里面不会产生页面滚动。
IE6的堆栈,多亏了我把ie6编译出来:
mshtml.exe!CDispRoot::ScrollRect(const CRec
mshtml.exe!CDispScroller::SetScrollOffset(c
mshtml.exe!CView::SmoothScroll(const tagSIZ
mshtml.exe!CLayout::ScrollTo(const CSize &
mshtml.exe!CLayout::ScrollByPercent(const C
mshtml.exe!CLayout::ScrollByLine(const CSiz
mshtml.exe!CLayout::OnScroll(int iDirection
mshtml.exe!CLayout::HandleScrollbarMessage(
mshtml.exe!CLayout::HandleKeyDown(CMessage
mshtml.exe!CLayout::HandleMessage(CMessage
mshtml.exe!CFlowLayout::HandleMessage(CMess
mshtml.exe!CBodyLayout::HandleMessage(CMess
mshtml.exe!CElement::HandleMessage(CMessage
mshtml.exe!CDoc::PerformTA(CMessage * pMess
mshtml.exe!CDoc::PumpMessage(CMessage * pMe