[Atelier Blue アトリエブルー]HomeプログラミングManaged DirectX3D>スクリーンショット

スクリーンショット

スクリーンショットはフロントバッファ情報をSurfaceとってくることによって実現できます。

ウィンドウモードの場合全面にある他のウィンドウも一緒にキャプチャしてしまいます。

内容

サーフィスを作りそこにフロントバッファの内容をコピーします。そして、コピーした内容をファイルに保存しています。サーフィスはPool.scratchにする必要があるようです。それと、保存形式を指定できるはずなのですが、一部形式では正確に保存できません。情報を横取りして自分で形式を変換するのがよいと思います。最後にこのスクリーンショットはすごく遅いです。私の環境では3秒ほど待ちます。代替案としてシステムの方のプリントスクリーンみたいなのを使うという方法もあると思います。(本当にあるか保証なし)

キー

[Esc]…終了 [F4]…スクリーンモード切り替え [S]…スクリーンショット(連打しないでください。素晴らしいことになります)

ソースコード

using System;
using System.Drawing;
using System.Windows.Forms;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;

namespace Project3
{
    /// <summary>
    /// MD3D3 の概要の説明です。
    /// </summary>
    public class MD3D3:Form
    {
        private Size fullScreenSize = new Size(800,600);
        private Size windowedSize = new Size(800,600);

        public MD3D3():base()
        {
            //最小サイズを設定
            this.MinimumSize=new Size(80,60);

            this.Size = windowedSize;

            //ウィンドウの名前(かっこいいのを付けてあげてください)
            this.Text ="Direct3D-My";
            this.KeyDown+=new KeyEventHandler(MD3D3_KeyDown);
        }

        private Device device_;
        private PresentParameters presentParam_;

        /// <summary>
        /// Direct3Dの初期化を行います。
        /// </summary>
        /// <returns>初期化が成功したかどうか</returns>
        public bool DXInitialize()
        {
            try 
            {
                //プレゼンテーションパラメータを作成
                presentParam_ = new PresentParameters();

                //ウィンドウモード
                presentParam_.Windowed =true;

                //スワップエフェクトを設定。
                presentParam_.SwapEffect = SwapEffect.Discard;


                //デバイスを作成
                device_ = new Device(0,DeviceType.Hardware,this
                    ,CreateFlags.HardwareVertexProcessing,presentParam_);

                creatVertex();

                //初期化成功
                return true;
            }
            catch 
            {
                //初期化失敗
                return false;
            }

        }

        /// <summary>
        /// 頂点バッファ
        /// </summary>
        private VertexBuffer vertexBuffer_;

        /// <summary>
        /// 頂点バッファ作成関数
        /// </summary>
        private void creatVertex()
        {
            //頂点バッファ領域を確保
            vertexBuffer_ = new VertexBuffer(typeof(CustomVertex.TransformedColored),
                6, device_, 0, CustomVertex.TransformedColored.Format, Pool.Managed);

            //バッファをロック
            GraphicsStream stm = vertexBuffer_.Lock(0,0,0);

            //頂点データの配列を作成
            CustomVertex.TransformedColored[] verts = new CustomVertex.TransformedColored[6];

            //頂点データ
            verts[0].X=50;verts[0].Y=250;verts[0].Z=0.5f; verts[0].Rhw=1;
            verts[0].Color = System.Drawing.Color.LightPink.ToArgb();
            verts[1].X=150;verts[1].Y=50;verts[1].Z=0.5f; verts[1].Rhw=1;
            verts[1].Color = System.Drawing.Color.Aqua.ToArgb();
            verts[2].X=250;verts[2].Y=250;verts[2].Z=0.5f;verts[2].Rhw=1;
            verts[2].Color = System.Drawing.Color.Brown.ToArgb();

            verts[3].X=350;verts[3].Y=50;verts[3].Z=0.5f; verts[3].Rhw=1;
            verts[3].Color = System.Drawing.Color.Black.ToArgb();
            verts[4].X=450;verts[4].Y=250;verts[4].Z=0.5f;verts[4].Rhw=1;
            verts[4].Color = System.Drawing.Color.Red.ToArgb();
            verts[5].X=550;verts[5].Y=50;verts[5].Z=0.5f; verts[5].Rhw=1;
            verts[5].Color = System.Drawing.Color.Green.ToArgb();


            //頂点データをバッファに書き込み
            stm.Write(verts);

            //バッファのロックを解除
            vertexBuffer_.Unlock();
        }

        public void Render()
        {
            if(device_==null)return;
            if(this.WindowState ==FormWindowState.Minimized)return;


            //クリア処理
            device_.Clear(ClearFlags.Target,Color.Blue,1.0f,0);

            //描画開始
            device_.BeginScene();


            //頂点バッファをセット
            device_.SetStreamSource(0,vertexBuffer_,0);
            //頂点バッファのフォーマットをセット
            device_.VertexFormat = CustomVertex.TransformedColored.Format;
            //描画
            device_.DrawPrimitives(PrimitiveType.TriangleStrip,0,4);


            //描画終わり
            device_.EndScene();

            try 
            {
                //更新
                device_.Present();
            }
            catch(DeviceLostException ex)
            {
                resetDevice();
            }

        }

        /// <summary>
        /// デバイスのリセットを行う
        /// </summary>
        private void resetDevice()
        {
            int result;
            if(!device_.CheckCooperativeLevel(out result))
            {
                if(result ==(int)ResultCode.DeviceLost)
                {
                    //ちょっと待つ
                    System.Threading.Thread.Sleep(10);
                }
                else if(result ==(int)ResultCode.DeviceNotReset)
                {
                    device_.Reset(presentParam_);
                }
            }
        }

        /// <summary>
        /// キー入力に反応
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void MD3D3_KeyDown(object sender, KeyEventArgs e)
        {
            if(e.KeyCode ==Keys.Escape)this.Close();
            if(e.KeyCode == Keys.F4)this.changeMode();
            if(e.KeyCode == Keys.S)this.screenShot();
        }



        /// <summary>
        /// モードチェンジを行います。
        /// </summary>
        private void changeMode()
        {
            if(presentParam_.Windowed)
            {
                this.windowedSize = this.Size;

                this.FormBorderStyle = FormBorderStyle.None;
                this.Size = fullScreenSize;

                presentParam_.Windowed = false;
                presentParam_.BackBufferHeight = fullScreenSize.Height;
                presentParam_.BackBufferWidth = fullScreenSize.Width;

                presentParam_.BackBufferFormat =Format.X8R8G8B8;
                presentParam_.FullScreenRefreshRateInHz =60;
                device_.Reset(presentParam_);
            }
            else 
            {
                presentParam_ = new PresentParameters();
                presentParam_.Windowed = true;
                presentParam_.SwapEffect = SwapEffect.Discard;

                device_.Reset(presentParam_);
                this.FormBorderStyle = FormBorderStyle.Sizable;
                this.Size = this.windowedSize;
            }
        }

        /// <summary>
        /// スクリーンショットをとります。
        /// </summary>
        private  void screenShot()
        {
            if(device_ == null)return;

            DisplayMode dispMode =  Manager.Adapters[0].CurrentDisplayMode;

            Surface ss =device_.CreateOffscreenPlainSurface(
                //ClientSize.Width,ClientSize.Height,
                dispMode.Width,dispMode.Height,
                Format.A8R8G8B8,Pool.Scratch);

            try 
            {
                device_.GetFrontBufferData(0,ss);
            }
            catch 
            {
                MessageBox.Show("キャプチャ失敗");
            }

            String path = System.IO.Path.GetDirectoryName(
                System.Reflection.Assembly.GetExecutingAssembly().Location);

            string fileName = DateTime.Now.ToString().Replace('/','-').Replace(':','-');

            if(presentParam_.Windowed)
            {
                Rectangle rect =new Rectangle(this.PointToScreen(new Point(0,0)),this.ClientSize);
                SurfaceLoader.Save(path +@"\"+fileName + ".bmp",ImageFileFormat.Bmp,ss,rect); 
            } else {
                SurfaceLoader.Save(path +@"\"+fileName + ".bmp",ImageFileFormat.Bmp,ss);
            }

            ss.Dispose();
        }
    }

    /// <summary>
    /// エントリクラス
    /// </summary>
    class Program
    {
        public static void Main()
        {
            using(MD3D3 dxform =new MD3D3())
            {
                if(!dxform.DXInitialize())
                {
                    MessageBox.Show("Direct3Dの初期化に失敗しました。","初期化の失敗");
                    return;
                }

                dxform.Show();

                while(dxform.Created)
                {
                    dxform.Render();
                    Application.DoEvents();
                }
            }

        }
    }
}



ページの一番上へ
前のページへ 一覧に戻る 次のページへ
初版2006-3-14
[Atelier Blue アトリエブルー]HomeプログラミングManaged DirectX3D>スクリーンショット