首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> 關於.NET

WPF 透明瀏覽器窗口實現:WebBrowser 背景融合技術

     編輯:關於.NET

效果預覽

透明瀏覽器窗口效果

基於 WPF、VS2008 SP1 實現。

問題分析

WinForms 只需設 Opacity 或 TransparencyKey。WPF 中設 Window.Opacity 會導致 WebBrowser 整體消失——這是 「空域」問題:WPF 像素與 Win32 HWND 像素無法正確混合。

參考:MSDN Blog

解決思路:視覺欺騙

真正透明難實現,但可做到視覺融合:將網頁背景繪製為被 WebBrowser 覆蓋區域的「應用程式背景截圖」,欺騙眼睛以為透明。

核心技術雙引擎

1. MSHTML + IHTMLPainter:網頁背景自繪

實作 IElementBehavior、IHTMLPainter 掛載至 <body>,在 Draw() 中繪製背景:

[ComVisible(true), Guid("0015EC28-C85F-49a8-9B1A-DC91E6345274"), ClassInterface(ClassInterfaceType.AutoDispatch)]
public class MyGadgetBodyBehavior : IElementBehavior, IHTMLPainter
{
    public void Draw(RECT rcBounds, RECT rcUpdates, int lDrawFlags, IntPtr hdc, IntPtr pvDrawObject)
    {
        using (var g = Graphics.FromHdc(hdc))
        using (var buffer = new Bitmap(width, height))
        using (var gBuffer = Graphics.FromImage(buffer))
        {
            // 1. 截取應用程式背景
            var image = snapHelper.GetScreenSnap();
            gBuffer.DrawImage(image.Bitmap, 0, 0);
            image.Dispose();

            // 2. 處理 CSS background-image
            string imageSrc = ((IHTMLElement2)body).currentStyle.backgroundImage;
            if (!string.IsNullOrEmpty(imageSrc))
            {
                var match = Regex.Match(imageSrc, @"url(""file:///(?.*)"")");
                if (match.Success)
                {
                    imageSrc = match.Groups["path"].Value;
                    using (var bitmap = new Bitmap(imageSrc))
                        gBuffer.DrawImage(bitmap, new Rectangle(0, 0, width, height));
                }
            }
            // 3. 只繪製更新區域
            g.DrawImage(buffer, rcUpdates.left, rcUpdates.top,
                new Rectangle(rcUpdates.left - rcBounds.left, rcUpdates.top - rcBounds.top,
                    rcUpdates.right - rcUpdates.left, rcUpdates.bottom - rcUpdates.top),
                GraphicsUnit.Pixel);
        }
    }
}

2. RenderTargetBitmap:應用程式截圖

internal Image GetScreenSnap(bool isForceRefresh)
{
    if (CheckPositionAndSize() && !isForceRefresh) return screenImage;
    control.Visibility = Visibility.Hidden; // 隱藏 WebBrowser
    var bitmap = new RenderTargetBitmap((int)parentWindow.Width, (int)parentWindow.Height, 96, 96, PixelFormats.Pbgra32);
    bitmap.Render(parentWindow);            // 截取整個視窗
    var bitmapSource = bitmap.CloneCurrentValue();
    var newBitmap = ConvertSourceImageToBitmap(bitmapSource);
    newBitmap = ClipBitmap(newBitmap, new System.Drawing.Rectangle((int)oldPoint.X, (int)oldPoint.Y,
        (int)control.Width, (int)control.Height));
    control.Visibility = Visibility.Visible; // 恢復顯示
    screenImage = new Image(newBitmap, imagePtr);
    return screenImage;
}

技巧:截圖前隱藏 WebBrowser,否則會截到自身內容。

已知缺陷

  • 應用程式背景設為透明時,截圖為透明,網頁背景呈現白色(無法融合)。解決:改截桌面背景。
  • 網頁過大出現滾動條時,未顯示區域無法透明(截圖僅限可視區)。適合本地可控大小的 HTML 頁面。

本文附配套源碼。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved