如何从Windows窗体控件创建的位图中捕获BitmapSource?

3

我想捕获一个ActiveX导入控件的图像,并在WPF中显示该图像。我之所以不使用Windows Forms宿主,是因为它太慢了(我想创建一个包含这些ActiveX控件的列表):到目前为止,我已经做了以下工作:

    public Bitmap CaptureCtrl(Control ctrl)
    {
        // Ein neues Image mit der grösse des jeweiligen Controls anlegen
        Console.WriteLine("new Bitmap({0:d}, {0:d}, g)", ctrl.Size.Width, ctrl.Size.Height);
        Bitmap newImage = new Bitmap(ctrl.Size.Width, ctrl.Size.Height);

        Graphics memoryGraphics = Graphics.FromImage(newImage);
        //Handle holen
        var hwnd = ctrl.Handle;
        IntPtr src = NativeMethods.GetDC(hwnd);
        IntPtr dest = memoryGraphics.GetHdc();

        // das Handle des Ziels
        // die X Position an der das Bild eingefügt werden soll
        // die Y Position an der das Bild eingefügt werden soll
        // die breite des Bildes
        // die höhe des Bildes
        // das Handle der Quelle
        // die X Position an der das Control liegt
        // die Y Position an der das Control liegt
        // Raster Operation Code an dieser Stelle ist es SRCCOPY
        // Natürlich muß der auf der Seite angegebene Hex wert noch in ein int umgerechnet werden
        // mehr informationen auf http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wceui40/html/_celrfternaryrasteroperations.asp
        Console.WriteLine("BitBlt(dest, 0, 0, {0:d}, {1:d}, src, {2:d}, {3:d}, 13369376)", ctrl.ClientRectangle.Width, ctrl.ClientRectangle.Height, ctrl.Location.X, ctrl.Location.Y);
        NativeMethods.BitBlt(dest, 0, 0, ctrl.ClientRectangle.Width, ctrl.ClientRectangle.Height, src, ctrl.Location.X, ctrl.Location.Y, 13369376);

        // Handles wieder Freigeben
        NativeMethods.ReleaseDC(hwnd, src);
        memoryGraphics.ReleaseHdc(dest);

        return newImage;
    }

并且:

    /// <summary>
    /// Converts a <see cref="System.Drawing.Bitmap"/> into a WPF <see cref="BitmapSource"/>.
    /// </summary>
    /// <remarks>Uses GDI to do the conversion. Hence the call to the marshalled DeleteObject.
    /// </remarks>
    /// <param name="source">The source bitmap.</param>
    /// <returns>A BitmapSource</returns>
    public static System.Windows.Media.Imaging.BitmapSource ToBitmapSource(this System.Drawing.Bitmap source)
    {
        System.Windows.Media.Imaging.BitmapSource bitSrc = null;

        IntPtr hBitmap = source.GetHbitmap();

        try
        {
            bitSrc = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
                hBitmap,
                IntPtr.Zero,
                Int32Rect.Empty,
                System.Windows.Media.Imaging.BitmapSizeOptions.FromEmptyOptions());
        }
        catch (Win32Exception we)
        {
            bitSrc = null;
            Console.WriteLine(we.ToString()+ " data: "+we.Data + " code: " + we.ErrorCode);
        }
        finally
        {
            NativeMethods.DeleteObject(hBitmap);
        }

        return bitSrc;
    }

以及调用代码:

    using (var capture = host.CaptureCtrl(this.control))
    {
         this.image.Source = capture.ToBitmapSource();
    }

NativeMethod调用是从dll中导入的,应该很清楚。 现在的问题是图片只是灰色的,没有填充内容(似乎确实复制了某些东西)。

1个回答

0

我找到了一个解决问题的方法(不一定是当前版本中存在的错误),对于任何感兴趣的人...

如果将捕获方法替换为这个,那么它就像魅力一样工作:

public Bitmap CaptureCtrl(Control ctrl)
{
   // Ein neues Image mit der grösse des jeweiligen Controls anlegen
   Bitmap newImage = new Bitmap(ctrl.Size.Width, ctrl.Size.Height);
   ctrl.DrawToBitmap(newImage, ctrl.ClientRectangle);
   return newImage;
}

我应该提到,我在 Windows 窗体框架中绘制组件,这些组件必须是 Visible=true(否则我会得到一个 OCX 状态异常)。 - Sebastian
我不明白。上面的新CaptureCtrl方法是从控件创建位图的标准方式。这对于ActiveX控件是如何工作的? - adamcodes
ActiveX控件不也是一种控件吗? - Sebastian

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接