解决 WPF 自绘窗体 AllowsTransparency = true 和 Webbrowser 等内置窗体显示冲突的办法和思路

来源:互联网 发布:nba纳什数据 编辑:程序博客网 时间:2024/05/26 02:20

       示例代码在这里:http://download.csdn.net/source/2731942

       上述示例程序的几个关键点:

  1. WPF 窗体为主窗体,窗体风格为 AllowsTransparency = true
  2. 分别对主窗体内置 WPF 的 Webbrowser 控件和 Winform 的 Webbrowser 控件进行了演示
  3. 完美的窗体缩放、移动、最大化等操作
  4. 演示随意调整窗体背景透明度
  5. 示例代码简单易操作,是可以找得到的最完美,而且的确是完美的解决办法

       山寨关键点

       一、关键代码如下:

WPF

WebBrowserOverlay wbo = new WebBrowserOverlay(_webBrowserPlacementTarget);
System.Windows.Controls.WebBrowser wb = wbo.WebBrowser;
wb.Navigate(new Uri(“
http://blog.csdn.net/hikaliv/”));

Winform

WebBrowserOverlayWF wbo = new WebBrowserOverlayWF(_webBrowserPlacementTarget);
System.Windows.Forms.WebBrowser wb = wbo.WebBrowser;
wb.Navigate(new Uri(“
http://blog.csdn.net/hikaliv”));

       这两段代码分别是你在程序里面安置 WPF 的 Webbrowser 控件或 Winform 的 Webbrowser 控件的方法——关键在你不能放错地方。注意:代码你只能放在主窗体的构造函数处,InitializeComponent() 方法之后。

       二、别忘了在工程 References 里面添加 System.Windows.Presentation.dll,若要用到 Winform 的控件,还需要添加 System.Windows.Forms.dll 引用。

       三、不得设置 WindowStartupLocation 属性。


       这不是我的方法和示例代码,这是微软工程师的方法和示例代码,详见我转载他们的几篇关键文章:

       1、《WebBrowser control on transparent WPF window》
       2、《Transparent Windows in WPF》
       3、《Technology Regions Overview》

       此示例完整地诠释了一种最可取的办法——在主窗体上划出一块区域,由一块 FrameworkELement Object 的可视域(CompositionTarget)来呈现浏览器控件所属的顶级窗体——重点是这个“顶级窗体(Top-Level Window)”——以实现”视觉上”浏览器“内嵌”在主窗体。

       此法三个关键点用红字标出。这三个关键点也道出了此法作为最可取之法——其实也是唯一可取之法的原因。或许还有其它办法,但效果一定都不理想,灵活性也差。最终的效果是需要“视觉上内嵌”,而事实上并不需要逻辑上内嵌——因为逻辑内嵌的结果是不想要的,否则也不会有这个困难了。这个问题出现的关键在于上面第三篇文章介绍的内容,还有一点是 WPF(DirectX)和 Win32(GDI)的渲染顺序——其实这些倒并不恶心,真正恶心的地方在于 Webbrowser 这个控件……你会发现 template 对它无用,而且用你能找到的最强大的内查工具看它是铅板一块,透视不得。WPF 的 Webbrowser 到底是个什么神秘的东西需要这么保密?——不仅神秘,而且古老——关键是古老,Winform 和 WPF 其实都没有对它进行重写以使它至少在 UI 上可以更强大,不,不仅 UI 体验上没有加强,而且事实功能上反而一代比一代更加弱小——建议大伙儿彻底放弃 system.windows.controls.webbrowser 好了,当它根本没存在过,视而不见,只用 system.windows.forms.webbrowser,或者直接用 MFC 的,反正只不过需要加层 WindowsHost 或者 HWNDSOURCE 而已。

       正因为 Webbrowser 的恶心,因此唯一正确的思路则是必须将它和 WPF 主窗体逻辑解体。否则只能取缔 WPF 窗体的 AllowsTransparency = true 属性约束,使 WPF 的 Transparent/Alpha 通道渲染和这个控件的底层渲染不冲突。想闯闯没有 AllowsTransparency = true 属性约束的 WPF 自制窗体吗?自己去处理无尽的 WINDOWS MESSAGE 麻烦吧——友情提示一声—— WPF 渲染和系统(GDI)渲染是两层,截消息的办法是行不通的……如果你还想再架层 DWM 渲染的话……祝你愉快。

       总之,WPF 自制窗体“内嵌”Webbrowser 控件必须的两点:

  1. AllowsTransparency = true。这简简单单一句话……其实背后的水很深很深……没它你试试……
  2. 控件与主窗体必须逻辑解体。

       问题症结

       一句话概括就是“窗体的逻辑和渲染冲突”。我不知道非 WIN 系统是否会存在这个问题,然而在 WINDOWS 系统上,这是一个很恶心的问题。而且这也并非是个案,因为说得不好听点儿,这根本就是版本间不可兼容的事儿,是微软产品的通病。我不了解 Apple 的 MAC 系统是如何渲染的,但我体会到了 WPF 渲染的代价——这么多层、重复渲染、渲染冲突,而且还不如 MAC 的效果好,对硬件宽容,性能高……唉……


       抱怨一下,为何微软的 WPF 开发团队这么“懒”呢?把 system.windows.controls.webbrowser 写得比 system.windows.forms.webbrowser 要差,残废,而且 WPF 下面的 Datagrid 也远不如 Winform 的 Datagridview。MS 平台软件开发的方向,从 MFC 的实打实,经过 Winform 越来越向 WPF 的华而不实的方向走……WPF 确立了一种全新的窗体组织形式,让 UI 和控件开发实现了松耦合、自动化,但不能用实用性的缺失为交换。记得 .net framework 刚出来的时候,全新的 C#.net 体验让学长传达给我他在微软工程院从工程师那里听到的一句话——MFC 的末日到了……效率不效率的其实并非重点,重点是新框架下的控件比旧框架下的控件不实用……那又如何宣判得了旧框架的死刑呢?

原创粉丝点击