Domanda

Can one render text using DirectWrite to a PictureBox in a WinForm app?

I'm using SharpDX and have gone through the DirectWrite samples trying to build the simplest working case I can.

I created a Form and added only a pictureBox to it. Then the following code. The form displays, but nothing visible with the PictureBox.

Any guidance would be much appreciated.

Thanks!

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
//using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using SharpDX.Direct2D1;
using SharpDX.DXGI;
using SharpDX;
using SharpDX.DirectWrite;

using AlphaMode = SharpDX.Direct2D1.AlphaMode;
using Factory = SharpDX.Direct2D1.Factory;

namespace d2dwTextEdit
{
public partial class Form1 : Form
{
    public Factory Factory2D { get; private set; }
    public SharpDX.DirectWrite.Factory FactoryDWrite { get; private set; }
    public WindowRenderTarget RenderTarget2D { get; private set; }
    public SolidColorBrush SceneColorBrush { get; private set; }
    public TextFormat TextFormat { get; private set; }
    public SharpDX.RectangleF ClientRectangle { get; private set; }


    public Form1()
    {
        InitializeComponent();
        Initialize();
        Render();
    }

    protected void Initialize()
    {
        Factory2D = new SharpDX.Direct2D1.Factory();
        FactoryDWrite = new SharpDX.DirectWrite.Factory();

        HwndRenderTargetProperties properties = new HwndRenderTargetProperties();
        properties.Hwnd = pictureBox1.Handle;
        properties.PixelSize = new System.Drawing.Size(pictureBox1.Width, pictureBox1.Height);
        properties.PresentOptions = PresentOptions.None;

        TextFormat = new TextFormat(FactoryDWrite, "Calibri", 30) { TextAlignment = TextAlignment.Center, ParagraphAlignment = ParagraphAlignment.Center };

        RenderTarget2D = new WindowRenderTarget(Factory2D, new RenderTargetProperties(new PixelFormat(Format.Unknown, AlphaMode.Premultiplied)), properties);
        RenderTarget2D.AntialiasMode = AntialiasMode.PerPrimitive;
        RenderTarget2D.TextAntialiasMode = TextAntialiasMode.Cleartype;

        ClientRectangle = new RectangleF(0, 0, pictureBox1.Width, pictureBox1.Height);

        SceneColorBrush = new SolidColorBrush(RenderTarget2D, Colors.White);
        SceneColorBrush.Color = Colors.Black;               


    }

    private void Render()
    {
        RenderTarget2D.Clear(Colors.White);
        RenderTarget2D.DrawText("Hello Marshall", TextFormat, ClientRectangle, SceneColorBrush);
    }

}
}
È stato utile?

Soluzione

Hi I sort of followed your question example but I finally managed to work it out as I would like to independently start writing games, all the draw methods have to be within the beginDraw and endDraw methods of the RenderTarget class'. you also need to implement the RenderLoop class this will give you the callback loop delegate. Apologies for the crudeness of my code.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using SharpDX.Direct3D;
using SharpDX.Direct2D1;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
using SharpDX.DXGI;
using SharpDX;
using SharpDX.Windows;
using System.Globalization;


using SharpDX.DirectWrite;

namespace dx11
{


    public partial class Form1 : Form
    {
        private SharpDX.Direct3D10.Device _mDevice = null;
        WindowRenderTarget wndRender = null;
        SharpDX.Direct2D1.Factory fact = new SharpDX.Direct2D1.Factory(SharpDX.Direct2D1.FactoryType.SingleThreaded);
        SolidColorBrush scenebrush;
        RenderTargetProperties rndTargProperties;
        HwndRenderTargetProperties hwndProperties;
        SharpDX.Windows.RenderForm form = new RenderForm();
        RenderLoop.RenderCallback callback;

        public Form1()
        {
            InitializeComponent();

            SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint, true);

            form.Width = 600;
            form.Height = 600;
            test();
            callback = new RenderLoop.RenderCallback(Render);

            RenderLoop.Run(form, callback);                            
        }

        private void test()
        {
                rndTargProperties = new RenderTargetProperties(new PixelFormat(Format.B8G8R8A8_UNorm, AlphaMode.Premultiplied));

                hwndProperties = new HwndRenderTargetProperties();
                hwndProperties.Hwnd = form.Handle;
                hwndProperties.PixelSize = new SharpDX.DrawingSize(form.ClientSize.Width, form.ClientSize.Height);
                hwndProperties.PresentOptions = PresentOptions.None;
                wndRender = new WindowRenderTarget(fact, rndTargProperties, hwndProperties);
                scenebrush = new SolidColorBrush(wndRender, Colors.Red);
               // scenebrush.Color = Colors.Cornsilk;
                form.Show();
        }

        public void Render()
        {    

            wndRender.BeginDraw();
            wndRender.Clear(Colors.DarkBlue);
            wndRender.DrawRectangle(new SharpDX.RectangleF(10, 10, 50, 50), scenebrush, 2.00F);
            wndRender.Flush();
               wndRender.EndDraw();
        }

    }
}

This should create a blue form with a red square in the top left corner.

Altri suggerimenti

You don't actually want to render "into the PictureBox" with an HwndRenderTarget. You actually want to render into the Bitmap that the PictureBox has the job of rendering. You can do that by creating a "shared bitmap" (I'm not familiar with SharpDX specifically but the underlying method is ID2D1RenderTarget::CreateSharedBitmap()), rendering into that, and then invalidating the PictureBox after you call EndDraw().

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top