首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > VC/MFC >

如何在layeredwindow下半透明显示WebBrowser控件

2013-03-01 
怎么在layeredwindow上半透明显示WebBrowser控件?创建了一个layered window然后调用UpdateLayeredWindow函

怎么在layeredwindow上半透明显示WebBrowser控件?
创建了一个layered window然后调用UpdateLayeredWindow函数可以进行alpha混合半透明显示图片、flash等元素,但是不知道怎么半透明显示WebBrowser控件;试过用显示flash的方式,行不通。分析了一下原因:
flash显示方式:网上抄了一个OleContainer模板,

              

这种效果还是可行的,2011年已经实现了,但是实现原理很特别,而且不同IE的版本处理方式也不同,REDUI源码里有实现(很多人有源码,但恐怕愿意看的人没几个),不过暂时只针对IE9,其它版本IE会崩溃,知道原因,懒得改。
以前写的帖子在这里:带浏览器控件的透明窗口演示
[解决办法]


粗略的看了下你的源代码,不知道我说的对不对:



BOOL iGdiTexture::__IsPaintMsg(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT& lResult)
{
if (!m_device->IsLayeredWindow() 
[解决办法]
 !m_msgHooks.HasMessage(uMsg))
return FALSE;

HDC hdc = m_alpha ? getDC() : getTexDC();
lResult = ::CallWindowProcW(m_oldProc, hWnd, uMsg, wParam, lParam);

if (m_renderType==5 && m_oleObject) // Ole
{
// 浏览器控件的典型样式:
//<object progid="Shell.Explorer"浏览器控件的PROGID
//bind-class="Internet Explorer_Server"改变到HOOK这个类名的窗口
//bind-type="5"绑定方式
//bind-messages="0x0118 timer"HOOK这些消息
//style="width:100%;height:180;"
//location="www.baidu.com"初始化打开的网址
//title="WebBrowser">haha</object>

CComQIPtr<IViewObject> vo = m_oleObject;
if (vo.p)
{
RECTL rc = {0,0,(LONG)m_width,(LONG)m_height};
HRESULT hr = vo.p->Draw(DVASPECT_CONTENT, -1, NULL, NULL, NULL, hdc, (RECTL*) &rc, NULL, NULL, NULL); 


}
}
else
{
switch (m_renderType)
{
case 0: // WM_PAINT
::CallWindowProcW(m_oldProc, hWnd, WM_PAINT, (WPARAM)hdc, lParam);
break;
case 1: // WM_PRINT
::CallWindowProcW(m_oldProc, hWnd, WM_PRINT, (WPARAM)hdc, (LPARAM)(PRF_CHECKVISIBLE
[解决办法]
PRF_NONCLIENT
[解决办法]
PRF_CLIENT
[解决办法]
PRF_ERASEBKGND
[解决办法]
PRF_CHILDREN
[解决办法]
PRF_OWNED));
break;
case 2: // WM_PRINTCLIENT
::CallWindowProcW(m_oldProc, hWnd, WM_PRINTCLIENT, (WPARAM)hdc, (LPARAM)(PRF_CHECKVISIBLE
[解决办法]
PRF_NONCLIENT
[解决办法]
PRF_CLIENT
[解决办法]
PRF_ERASEBKGND
[解决办法]
PRF_CHILDREN
[解决办法]
PRF_OWNED));
break;
default:
::CallWindowProcW(m_oldProc, hWnd, WM_PAINT, (WPARAM)hdc, lParam);
}

//::SendMessage(m_pWin->m_hWnd, WM_PAINT, (WPARAM)hdc, 0);
//::SendMessage(hWnd, WM_PRINT, (WPARAM)hdc, (LPARAM)(PRF_CHECKVISIBLE
[解决办法]
PRF_NONCLIENT
[解决办法]
PRF_CLIENT
[解决办法]
PRF_ERASEBKGND
[解决办法]
PRF_CHILDREN
[解决办法]
PRF_OWNED));
//::SendMessage(m_hWnd, WM_PRINTCLIENT, (WPARAM)hdc, (LPARAM)(/*PRF_CHECKVISIBLE
[解决办法]
*/PRF_NONCLIENT
[解决办法]
PRF_CLIENT
[解决办法]
PRF_ERASEBKGND
[解决办法]
PRF_CHILDREN
[解决办法]
PRF_OWNED));
}

if (m_alpha)
releaseDC(hdc);
else
releaseTexDC(hdc);
m_dirty = FALSE;
m_device->render();

return TRUE;
}



通过拦截相就窗口的WM_PAINT消息,通过替换HDC,将窗口内容绘制在自己的DC上面。
不过这种方案也有很大的限制,就是不通过InvalidateRect进行刷新的控件就无法在分层窗口上面及时更新了,例如:
1. 光标。 它是直接画在窗口DC上的,同样,网页上面的光标也都无法刷新出来
2. EDIT。 将Demo中的class="button"换成edit,刷新不正常,从SPY上没有看到WM_PAINT消息,
3. SCROLLBAR。 它应该也是自己绘制而不通过WM_PAINT
(另外我测试我发现好像没有做裁剪,只在一个按钮上移动时,其它区域也会刷新 )

因此建议LZ还是先分成两个窗口实现,这样说不定能先完成任务,两个窗口的同步其实不难,拦截OnWindowPosChanging消息,再加上 BeginDefWindow...就能搞定
------解决方案--------------------


楼上好样的,居然找到关键代码了。确实如楼上所说,这种方案有很多不足:
1、光标显示不出来。在分层窗口下,所有的光标都必须自己实现,但我没有为浏览器控件单独实现光标。
2、EDIT是早期方案,因为很难看,已经废弃不用,改成用Windowless RichEdit了,它的光标和滚动条都是自己实现的。
3、REDUI中的滚动条是用桌面主题自绘的,没有使用滚动条窗口;RICHEDIT中的滚动条也是自绘的;浏览器控件中的滚动条本身就是自绘的,没用窗口,所以都能正常显示。

关于没有做裁剪和刷新的问题,这是设计使然,用DX作为渲染工具时都是全局刷新重绘,不需要设置无效区域(设了也没用)。

到目前为止,最简洁、效果最好的方案还是双窗口解决方案,唯一的麻烦是消息处理得多一点。

热点排行