如何打印渲染到SurfaceImageSource的内容?

时间:2012-12-12 13:20:37

标签: c# printing windows-runtime directx sharpdx

我正在使用SharpDx在WinRt的Image控件中渲染一些形状。如何打印呈现给打印机的内容?

private void RenderGraphics()
    {
        KSurfaceImageSourceManager _pKSurfaceImageSourceManager = new KSurfaceImageSourceManager();

        SurfaceImageSource _pSurfaceImageSource = _pKSurfaceImageSourceManager.NewSurfaceImageSource((int)imageCtrl.Width, (int)imageCtrl.Height);
        int _w = 0;
        int _h = 0;
        _pKSurfaceImageSourceManager.GetSurfaceImageSourceSize(_pSurfaceImageSource, out _w, out _h);

        this.imageCtrl.Source = _pSurfaceImageSource;
        int _retcode = _pKSurfaceImageSourceManager.ClearSurfaceImageSource(_pSurfaceImageSource, 1, 1, 1, 1);

        int _hrenderTarget = 0;
        int _offsetx = 0;
        int _offsety = 0;
        int _surfacewidth = 0;
        int _surfaceheight = 0;            
        try
        {
            // initiating a Direct2D drawing session: BeginDraw2D 
            _hrenderTarget = _pKSurfaceImageSourceManager.BeginDraw2D(_pSurfaceImageSource, out _offsetx, out _offsety, out _surfacewidth, out _surfaceheight);

            // connecting the _hrenderTarget handle returned by BeginDraw2D to a RenderTarget instance
            _pRenderTarget = new RenderTarget(new IntPtr(_hrenderTarget));

            // Direct2D drawing session targetting _pRenderTarget
            _pRenderTarget.BeginDraw();
            SharpDX.Direct2D1.SolidColorBrush _brush = null;

            int _left = _offsetx;
            int _top = _offsety;
            int _right = _surfacewidth;
            int _bottom = _surfaceheight;

            // border
            _brush = new SharpDX.Direct2D1.SolidColorBrush(_pRenderTarget, new SharpDX.Color4(1, 0, 0, 1));
            _pRenderTarget.FillRectangle(new SharpDX.RectangleF(_left, _top, _right, _bottom), _brush);

            // fill
            int _border = 2;

            _brush = new SharpDX.Direct2D1.SolidColorBrush(_pRenderTarget, new SharpDX.Color4(1, 1, 1, 1));

            _pRenderTarget.FillRectangle(new SharpDX.RectangleF(_left + _border, _top + _border, _right - 2 * _border, _bottom - 2 * _border), _brush);
            _pRenderTarget.DrawEllipse(new SharpDX.Direct2D1.Ellipse(new DrawingPointF(50, 80), 50, 50), new SharpDX.Direct2D1.SolidColorBrush(_pRenderTarget, Color.SlateBlue));

        }
        catch (Exception E)
        {
        }
        finally
        {
            _pKSurfaceImageSourceManager.EndDraw2D(_pSurfaceImageSource);
        }

    }

我试图在不执行这些渲染操作的情况下打印图像控件的内容,但它确实有效。当我在调用此方法后尝试相同时,它会打印为空白。

1 个答案:

答案 0 :(得分:1)

我还没有在Windows 8中进行打印,但您可能需要使用BitmapImage或WriteableBitmap。 WinRT XAML工具包中有一些代码尚未以最佳性能方式执行,但应该适用于打印。它基本上归结为:

public static class WriteableBitmapRenderExtensions
{
    public static async Task Render(this WriteableBitmap wb, FrameworkElement fe)
    {
        var ms = RenderToStream(fe);
        var msrandom = new MemoryRandomAccessStream(ms);
        await wb.SetSourceAsync(msrandom);
    }

    public static MemoryStream RenderToStream(FrameworkElement fe)
    {
        return new CompositionEngine().RenderToPngStream(fe);
    }
}


public class CompositionEngine
{
    private readonly ImagingFactory _wicFactory;
    private readonly SharpDX.Direct2D1.Factory _d2DFactory;
    private readonly SharpDX.DirectWrite.Factory _dWriteFactory;

    public CompositionEngine()
    {
        _wicFactory = new ImagingFactory();
        _d2DFactory = new SharpDX.Direct2D1.Factory();
        this._dWriteFactory = new SharpDX.DirectWrite.Factory();
    }

    public ImagingFactory WicFactory
    {
        get
        {
            return this._wicFactory;
        }
    }

    public SharpDX.Direct2D1.Factory D2DFactory
    {
        get
        {
            return this._d2DFactory;
        }
    }

    public SharpDX.DirectWrite.Factory DWriteFactory
    {
        get
        {
            return this._dWriteFactory;
        }
    }

    public MemoryStream RenderToPngStream(FrameworkElement fe)
    {
        var width = (int)Math.Ceiling(fe.ActualWidth);
        var height = (int)Math.Ceiling(fe.ActualHeight);

        // pixel format with transparency/alpha channel and RGB values premultiplied by alpha
        var pixelFormat = WicPixelFormat.Format32bppPRGBA;

        // pixel format without transparency, but one that works with Cleartype antialiasing
        //var pixelFormat = WicPixelFormat.Format32bppBGR;

        var wicBitmap = new Bitmap(
            this.WicFactory,
            width,
            height,
            pixelFormat,
            BitmapCreateCacheOption.CacheOnLoad);

        var renderTargetProperties = new RenderTargetProperties(
            RenderTargetType.Default,
            new D2DPixelFormat(Format.R8G8B8A8_UNorm, AlphaMode.Premultiplied),
            //new D2DPixelFormat(Format.Unknown, AlphaMode.Unknown), // use this for non-alpha, cleartype antialiased text
            0,
            0,
            RenderTargetUsage.None,
            FeatureLevel.Level_DEFAULT);
        var renderTarget = new WicRenderTarget(
            this.D2DFactory,
            wicBitmap,
            renderTargetProperties)
        {
            //TextAntialiasMode = TextAntialiasMode.Cleartype // this only works with the pixel format with no alpha channel
            TextAntialiasMode = TextAntialiasMode.Grayscale // this is the best we can do for bitmaps with alpha channels
        };




        Compose(renderTarget, fe);




        // TODO: There is no need to encode the bitmap to PNG - we could just copy the texture pixel buffer to a WriteableBitmap pixel buffer.
        var ms = new MemoryStream();

        var stream = new WICStream(
            this.WicFactory,
            ms);

        var encoder = new PngBitmapEncoder(WicFactory);
        encoder.Initialize(stream);

        var frameEncoder = new BitmapFrameEncode(encoder);
        frameEncoder.Initialize();
        frameEncoder.SetSize(width, height);
        var format = WicPixelFormat.Format32bppBGRA;
        //var format = WicPixelFormat.FormatDontCare;
        frameEncoder.SetPixelFormat(ref format);
        frameEncoder.WriteSource(wicBitmap);
        frameEncoder.Commit();

        encoder.Commit();

        frameEncoder.Dispose();
        encoder.Dispose();
        stream.Dispose();

        ms.Position = 0;
        return ms;
    }

    public void Compose(RenderTarget renderTarget, FrameworkElement fe)
    {
        renderTarget.BeginDraw();




        Do your rendering here




        renderTarget.Clear(new Color(0, 0, 0, 0));
        Render(renderTarget, fe, fe);
        renderTarget.EndDraw();
    }
}