ofscreen を使って図形を描画する

C# の Direct Draw で ofscreen Surface を使って図形を描画します。
これで画面の「チラツキ」を無くすことが出来ました。

前田稔(Maeda Minoru)の超初心者のプログラム入門

プロジェクトの設定

  1. ウインドウを表示 に習って、空のプロジェクトから作成します。
    前回作成したプロジェクトをフォルダーごとコピーして、フォルダー名を変更すると便利です。
    次のファイルを格納して下さい。
    /********************************************************/
    /*★ Direct Draw で offscreen に図形を描画    前田 稔 ★*/
    /********************************************************/
    using System;
    using System.Drawing;
    using System.ComponentModel;
    using System.Windows.Forms;
    using Microsoft.DirectX;
    using Microsoft.DirectX.DirectDraw;
    
    namespace DXDraw
    {
        public class DXDraw : System.Windows.Forms.Form
        {
            private Device draw = null;         // DrawDevice object.
            private Surface primary = null;     // primary destination surface.
            private Surface offscreen = null;   // offscreen surface(bitmap loaded).
            private Rectangle destination = new Rectangle();
    
            public DXDraw()
            {
                this.ClientSize = new System.Drawing.Size(400, 320);
                this.Text = "DXDraw";
                this.Resize += new System.EventHandler(this.DXDraw_SizeChanged);
                this.SizeChanged += new System.EventHandler(this.DXDraw_SizeChanged);
                this.Paint += new System.Windows.Forms.PaintEventHandler(this.DXDraw_Paint);
    
                CreateSurfaces();               // Call creates the surface objects.
            }
    
            //☆ Main() メソッド
            static void Main() 
            {
                // using で資源の解放を確実に行う
                using(DXDraw mf = new DXDraw())
                {   Application.Run(mf);
                }
            }
    
            private void DXDraw_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
            {
                Draw();
            }
    
            private void DXDraw_SizeChanged(object sender, System.EventArgs e)
            {
                Draw();
            }
    
            // This function Draws the offscreen bitmap surface to the primary visible surface.
            private void Draw()
            {
                if (null == primary)    return;
                if (FormWindowState.Minimized == WindowState)   return;
                Height = Height < 50 ? 50 : Height;
    
                // Get the new client size to Draw to.
                destination = new Rectangle(PointToScreen(new Point(0,0)), ClientSize);
    
                try
                {
                    primary.Draw(destination, offscreen, DrawFlags.Wait);
                }
                catch(SurfaceLostException)
                {
                    CreateSurfaces(); // Surface was lost. Recreate them.
                }
            }
    
            // This function is where the surfaces and clipper object are created.
            private void CreateSurfaces()
            {
                // Create new DrawDevice.
                draw = new Device();
                // coop level normal windowed mode.
                draw.SetCooperativeLevel(this, CooperativeLevelFlags.Normal);
                // Create new primary surface.
                SurfaceDescription description = new SurfaceDescription();
                description.SurfaceCaps.PrimarySurface = true;
                primary = new Surface(description, draw);
    
                // Clear offscreen Surface
                description.Clear();
                description.SurfaceCaps.OffScreenPlain = true;
                description.Width = 400;
                description.Height = 320;
                offscreen = new Surface(description, draw);
                offscreen.ColorFill(Color.White);
                offscreen.FillColor = Color.Blue;
                offscreen.DrawEllipse(50, 20, 350, 200);
                offscreen.FillColor = Color.Red;
                offscreen.DrawBox(50, 220, 350, 300);
            }
        }
    }
    
  2. draw は Direct Draw Device の定義です。
    primary は primary surface の定義です。
    offscreen は、直接画面と結び付けられていない surface です。
    今回は offscreen にウインドウに表示するイメージを作成して、一挙に primary surface に転送します。
    destination はウインドウのサイズを取得する矩形領域です。
        private Device draw = null;         // DrawDevice object.
        private Surface primary = null;     // primary destination surface.
        private Surface offscreen = null;   // offscreen surface(bitmap loaded).
        private Rectangle destination = new Rectangle();
        
  3. surface を取得する CreateSurfaces です。
    SurfaceDescription を設定して new Surface() で primary surface を取得します。
    次に幅と高さを設定して offscreen surface を取得します。
    offscreen surface にウインドウに表示する楕円と矩形を描画します。
    このメソッドは Surface を消失したときにも呼び出されます。
        private void CreateSurfaces()
        {
            // Create new DrawDevice.
            draw = new Device();
            // coop level normal windowed mode.
            draw.SetCooperativeLevel(this, CooperativeLevelFlags.Normal);
            // Create new primary surface.
            SurfaceDescription description = new SurfaceDescription();
            description.SurfaceCaps.PrimarySurface = true;
            primary = new Surface(description, draw);
    
            // Clear offscreen Surface
            description.Clear();
            description.SurfaceCaps.OffScreenPlain = true;
            description.Width = 400;
            description.Height = 320;
            offscreen = new Surface(description, draw);
            offscreen.ColorFill(Color.White);
            offscreen.FillColor = Color.Blue;
            offscreen.DrawEllipse(50, 20, 350, 200);
            offscreen.FillColor = Color.Red;
            offscreen.DrawBox(50, 220, 350, 300);
        }
        
  4. primary surface に offscreen surface を転送する Draw() メソッドです。
    primary が null のときやウインドウが最小化されているときはパスします。
    ウインドウの高さがゼロになると異常終了するので、50以下にならないようにしています。
    destination にウインドウサイズを取得します。
    primary.Draw() で offscreen surface から描画イメージを転送します。
        private void Draw()
        {
            if (null == primary)    return;
            if (FormWindowState.Minimized == WindowState)   return;
            Height = Height < 50 ? 50 : Height;
    
            // Get the new client size to Draw to.
            destination = new Rectangle(PointToScreen(new Point(0,0)), ClientSize);
    
            try
            {
                primary.Draw(destination, offscreen, DrawFlags.Wait);
            }
            catch(SurfaceLostException)
            {
                CreateSurfaces(); // Surface was lost. Recreate them.
            }
        }
        

【演習】

  1. 図形に加えて TEXT を表示して下さい。
    DrawText() が TEXT を表示するソースコードです。
    40, 50 が TEXT の座標ですが、座標を指定するときは false にして下さい。
    true にすると座標は無視されます。 (^_^;)
    offscreen.DrawText(40, 50, "DirectX Draw Text", true);
  2. 表示する文字の色を変えてみて下さい。
        offscreen.ForeColor = Color.Green;
        

超初心者のプログラム入門(C# Frame Work)