2013年1月1日火曜日

WPF + DxLib (C#)

いつの間にかDxLib(C#)でバックバッファが取得出来るようになっていたので、WPFとの組み合わせを試してみる。
※→ 修正版記事


1.新しいプロジェクトからWPFアプリケーションを選択して作成。

2.D3DImageを継承してDxLibImageを作成。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Interop;
using System.Windows.Media;
using System.Diagnostics;
using DxLibDLL;
namespace WpfApplication1
{
public class DxLibImage : D3DImage
{
public const int BUFFER_WIDTH = 800;
public const int BUFFER_HEIGHT = 600;
public event EventHandler Reset;
public event EventHandler Render;
DX.SetRestoreGraphCallbackCallback RestoreGraphCallback;
/// <summary>
/// DxLibの初期化
/// </summary>
public void Init_DxLib()
{
if (DX.DxLib_IsInit() == DX.TRUE)
return;
int width = double.IsNaN(Width) ? BUFFER_WIDTH : (int)Width;
int height = double.IsNaN(Height) ? BUFFER_HEIGHT : (int)Height;
HwndSource hwnd = new HwndSource(0, 0, 0, 0, 0, "DxLib", IntPtr.Zero);
DX.SetUserWindow(hwnd.Handle); // 描画ウィンドウの設定
DX.SetGraphMode(width, height, 32); // グラフィックモードの設定
DX.SetAlwaysRunFlag(DX.TRUE); // 非アクティブ時も処理続行
DX.SetDrawScreen(DX.DX_SCREEN_BACK); // 描画先をバックバッファへ設定
DX.SetUseFPUPreserveFlag(DX.TRUE); // FPUの精度を落とさない
DX.SetWaitVSyncFlag(DX.FALSE); // VSync同期を無効
DX.SetOutApplicationLogValidFlag(DX.FALSE); // ログ出力停止
DX.SetDoubleStartValidFlag(DX.TRUE); // 多重起動を許可
DX.SetUseIMEFlag(DX.TRUE); // IMEを有効
DX.SetBackgroundColor(0, 0, 0);
if (DX.DxLib_Init() == -1)
{
throw new Exception("Dxlib_Init");
}
// GC対策(不要?)
DX.SetUseGraphBaseDataBackup(DX.FALSE); // 自分ででデバイスロスト時の処理を行う
RestoreGraphCallback = RestoreGraph;
DX.SetRestoreGraphCallback(RestoreGraphCallback); // デバイスリセット時のイベントを設定
CompositionTarget.Rendering += CompositionTarget_Rendering;
IsFrontBufferAvailableChanged += d3dImage_IsFrontBufferAvailableChanged;
SetBackBuffer();
}
/// <summary>
/// デバイスリセット発生
/// </summary>
void RestoreGraph()
{
OnReset();
}
/// <summary>
/// バックバッファの設定
/// </summary>
void SetBackBuffer()
{
Lock();
SetBackBuffer(D3DResourceType.IDirect3DSurface9, DX.GetUseDirect3D9BackBufferSurface());
Unlock();
}
/// <summary>
/// 表示の更新
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void CompositionTarget_Rendering(object sender, EventArgs e)
{
try
{
if (IsFrontBufferAvailable)
{
Lock();
SetBackBuffer(D3DResourceType.IDirect3DSurface9, DX.GetUseDirect3D9BackBufferSurface());
{
// ここで描画
DX.ClearDrawScreen();
OnRender();
DX.ScreenFlip();
}
AddDirtyRect(new Int32Rect(0, 0, PixelWidth, PixelHeight));
Unlock();
}
}
catch (Exception ex)
{
Trace.WriteLine(ex.ToString());
}
}
/// <summary>
/// フロントバッファの更新
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void d3dImage_IsFrontBufferAvailableChanged(object sender, DependencyPropertyChangedEventArgs e)
{
if (IsFrontBufferAvailable)
{
CompositionTarget.Rendering += CompositionTarget_Rendering;
}
else
{
CompositionTarget.Rendering -= CompositionTarget_Rendering;
}
}
/// <summary>
/// デバイスロスト発生
/// </summary>
public virtual void OnReset()
{
if (Reset != null)
Reset(null, EventArgs.Empty);
}
/// <summary>
/// 描画処理
/// </summary>
public virtual void OnRender()
{
if (Render != null)
Render(null, EventArgs.Empty);
}
/// <summary>
/// DxLibの開放
/// </summary>
public void End_DxLib()
{
if (DX.DxLib_IsInit() != DX.TRUE)
return;
DX.DxLib_End();
}
}
}
view raw gistfile1.cs hosted with ❤ by GitHub
※D3DImageは詳しい使い方も理解せず適当に使っている為、間違っている箇所がある可能性があります。詳しい使い方はD3DImageでググってちょ。

3.MainWindowのデザイナーからDxLibImageとそのイベントを追加。

<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:me="clr-namespace:WpfApplication1"
Title="MainWindow" Loaded="Window_Loaded" Closed="Window_Closed" Width="800" Height="600">
<Grid>
<Image>
<Image.Source>
<me:DxLibImage x:Name="dxImage" Render="dxImage_Render" Reset="dxImage_Reset" />
</Image.Source>
</Image>
</Grid>
</Window>
view raw gistfile1.xml hosted with ❤ by GitHub
4.MainWindowのコードを記述。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Interop;
using DxLibDLL;
namespace WpfApplication1
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
// DxLibの初期化
dxImage.Init_DxLib();
}
private void Window_Closed(object sender, EventArgs e)
{
// DxLibの開放
dxImage.End_DxLib();
}
private void dxImage_Reset(object sender, EventArgs e)
{
// デバイスリセット
}
private void dxImage_Render(object sender, EventArgs e)
{
// 描画
DX.DrawBox(50, 50, 100, 100, DX.GetColor(0, 255, 0), DX.TRUE);
}
}
}
view raw gistfile1.txt hosted with ❤ by GitHub
5.実行結果。


WPFコントロールがそのまま使えるのでGUI作成が楽ちん。

0 件のコメント:

コメントを投稿