SharpDX, DirectWrite and Windows Forms

vocalionecho picture vocalionecho · Mar 25, 2012 · Viewed 7.9k times · Source

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);
    }

}
}

Answer

Dan picture Dan · Jun 14, 2012

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.