今天遇到了一个奇怪的问题。
问题重现:
在xp系统上,浏览器版本是IE7,使用CHtmlView控件,也就是WebBrowser2控件 。加载一个html文件,这个html中有一个iframe,这个iframe的内容根据页面的响应加载不同的框架html。 在加载之前会在这个CHtmlView控件之上绘制一个窗口, 通知用户等待。 每次切换iframe的src都会有这个等待窗口。 但是当等待窗口隐藏之后,iframe的上一次显示的页面和这一次显示的页面有问题: 上一次显示的页面在这一次显示的页面之上,重合了。 上次的页面只有画面,不能进行控件操作。 这严重影响了用户体验。
过程是在CHtmlView中截获DocumentComplete,根据加载的不同页面给主窗口发送不同的消息,进行数据的获取。 获取完数据再通过调用iframe页面的js进行交互。
经过测试,这个问题在Win7上没有。
记录一下以下几个方面的测试。
经过下面的修改,不会出现这个问题:
a. 将DocumentComplete中的消息发送注释
b.将等待窗口这个功能取消
c.将等待窗口的窗口透明效果取消
经过下面的修改,测试无效:
a.将等待窗口放在主线程中.
b.将iframe动态创建, 切换时销毁.
c.强制刷新CHtmlView窗口
猜测结果:
由于切换iframe的内容所获取的数据是在主线程里,可能因为CHtmlView的重绘消息被阻塞了,而其重绘消息的优先级很低,所以造成了这个原因。解决方法可能是将主线程的数据获取放到其他线程中去,这个方法没有测试,因为它将修改大量的代码。
解决办法:
//在等待窗口隐藏的时候, 查找出Internet Explorer_Server这个窗口,然后强制刷新
CComPtr<IWebBrowser2> web2=NULL;
m_pBrowserApp->QueryInterface(IID_IWebBrowser2,(void**)&web2);
if(web2==NULL)
{
return;
}
HWND handle=NULL;
CComPtr<IServiceProvider> psp;
bbb->QueryInterface(IID_IServiceProvider,(void**)&psp);
CComPtr<IOleWindow> pow;
psp->QueryService(SID_SShellBrowser,IID_IOleWindow, (void**)&pow);
if(pow!=NULL)
{
//this is “Shell Embedding”.
pow->GetWindow(&handle);
}
TCHAR szClassName[MAX_PATH];
HWND hwnd=handle;
while(true)
{
::GetClassName(hwnd,szClassName,MAX_PATH);
if(::_wcsicmp(L"Internet Explorer_Server",szClassName)==0)
{
break;
}
//
hwnd=::GetWindow(hwnd,GW_CHILD);
if(hwnd==NULL)
break;
}
::InvalidateRect((HWND)hwnd,NULL,FALSE);
::UpdateWindow(hwnd);