2013年1月21日月曜日

WPF + DxLib (C#) - その3

WPF+DxLibでコーディングを進めていく上でちょっと問題が発生。
どうやらSetUserWindowを使用している場合、DirectInput系が上手く動かない事があるみたい。
と、言う訳でその対応おば。

で、対応方法ですが・・・面倒いので他のライブラリで対応。
ググった結果MOISなる素敵な入力ライブラリを発見。
で、コード作成。

1. まず、MOIS.dllを参照設定に追加。

2. キーボード入力用コード。

using System;
using System.Windows.Media;
using System.Windows.Interop;
namespace MOIS
{
/// <summary>
/// キーボード
/// </summary>
public class MOIS_Keyboard : IDisposable
{
private const int KEY_MAX = 256;
private Keyboard keyb;
private bool[][] buff = new bool[2][];
public MOIS_Keyboard()
{
buff[0] = new bool[KEY_MAX];
buff[1] = new bool[KEY_MAX];
}
/// <summary>
/// 初期化処理
/// </summary>
/// <param name="visual"></param>
public void CreateInput(Visual visual)
{
HwndSource source = (HwndSource)HwndSource.FromVisual(visual);
ParamList pl = new ParamList();
pl.Insert("WINDOW", source.Handle.ToString());
pl.Insert("w32_keyboard", "DISCL_NONEXCLUSIVE");
pl.Insert("w32_keyboard", "DISCL_FOREGROUND");
InputManager mgr = InputManager.CreateInputSystem(pl);
keyb = (Keyboard)mgr.CreateInputObject(Type.OISKeyboard, true);
keyb.KeyPressed += keyb_KeyPressed;
keyb.KeyReleased += keyb_KeyReleased;
}
/// <summary>
/// キーが押された
/// </summary>
/// <param name="arg"></param>
/// <returns></returns>
bool keyb_KeyPressed(KeyEvent arg)
{
buff[0][(int)arg.key] = true;
return true;
}
/// <summary>
/// キーが離れた
/// </summary>
/// <param name="arg"></param>
/// <returns></returns>
bool keyb_KeyReleased(KeyEvent arg)
{
buff[0][(int)arg.key] = false;
return true;
}
/// <summary>
/// 状態の更新
/// </summary>
public void Capture()
{
buff[0].CopyTo(buff[1], 0);
if (keyb != null)
{
keyb.Capture();
}
}
/// <summary>
/// キーが押されたか確認
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public bool KeyDown(KeyCode key)
{
return (buff[0][(int)key] && !buff[1][(int)key]);
}
/// <summary>
/// キーが押されたままか確認
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public bool KeyPress(KeyCode key)
{
return (buff[0][(int)key] && buff[1][(int)key]);
}
/// <summary>
/// キーが離されたか確認
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public bool KeyUp(KeyCode key)
{
return (!buff[0][(int)key] && buff[1][(int)key]);
}
/// <summary>
/// キーが押されたままか確認
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public bool KeyPush(KeyCode key)
{
return (KeyDown(key) || KeyPress(key));
}
/// <summary>
/// 開放処理
/// </summary>
public void Dispose()
{
if (keyb != null)
{
keyb.Dispose();
}
}
}
}
view raw gistfile1.cs hosted with ❤ by GitHub


3. マウス入力用コード。

using System;
using System.Collections.Generic;
using System.Windows.Interop;
using System.Windows.Media;
namespace MOIS
{
/// <summary>
/// マウス
/// </summary>
public class MOIS_Mouse : IDisposable
{
const int DOUBLE_CLICK_FRAMES = 10;
private Mouse mouse;
private int[] x = new int[2];
private int[] y = new int[2];
private int[] z = new int[2];
private Dictionary<MouseButtonID, bool>[] buff = new Dictionary<MouseButtonID, bool>[2];
private Dictionary<MouseButtonID, int> frames = new Dictionary<MouseButtonID, int>();
private Dictionary<MouseButtonID, bool> dclick = new Dictionary<MouseButtonID, bool>();
public int X_Abs { get { return x[0]; } }
public int Y_Abs { get { return y[0]; } }
public int Z_Abs { get { return z[0]; } }
public int X_Rel { get { return x[0] - x[1]; } }
public int Y_Rel { get { return y[0] - y[1]; } }
public int Z_Rel { get { return z[0] - z[1]; } }
public MOIS_Mouse()
{
buff[0] = new Dictionary<MouseButtonID, bool>();
buff[1] = new Dictionary<MouseButtonID, bool>();
int min = (int)MouseButtonID.MB_Left;
int max = (int)MouseButtonID.MB_Button7;
for (int i = min; i <= max; i++)
{
buff[0].Add((MouseButtonID)i, false);
buff[1].Add((MouseButtonID)i, false);
frames.Add((MouseButtonID)i, 0);
dclick.Add((MouseButtonID)i, false);
}
}
/// <summary>
/// 初期化処理
/// </summary>
/// <param name="visual"></param>
/// <param name="width"></param>
/// <param name="height"></param>
public void CreateInput(Visual visual, int width, int height)
{
HwndSource source = (HwndSource)HwndSource.FromVisual(visual);
ParamList pl = new ParamList();
pl.Insert("WINDOW", source.Handle.ToString());
pl.Insert("w32_mouse", "DISCL_NONEXCLUSIVE");
pl.Insert("w32_mouse", "DISCL_FOREGROUND");
InputManager mgr = InputManager.CreateInputSystem(pl);
mouse = (Mouse)mgr.CreateInputObject(Type.OISMouse, true);
mouse.MouseMoved += mouse_MouseMoved;
mouse.MousePressed += mouse_MousePressed;
mouse.MouseReleased += mouse_MouseReleased;
MouseState_NativePtr state = mouse.MouseState;
state.width = width - 1;
state.height = height - 1;
}
/// <summary>
/// ボタンが押された
/// </summary>
/// <param name="arg"></param>
/// <param name="id"></param>
/// <returns></returns>
bool mouse_MousePressed(MouseEvent arg, MouseButtonID id)
{
buff[0][id] = true;
return true;
}
/// <summary>
/// ボタンが離された
/// </summary>
/// <param name="arg"></param>
/// <param name="id"></param>
/// <returns></returns>
bool mouse_MouseReleased(MouseEvent arg, MouseButtonID id)
{
buff[0][id] = false;
return true;
}
/// <summary>
/// マウスが動いた
/// </summary>
/// <param name="arg"></param>
/// <returns></returns>
bool mouse_MouseMoved(MouseEvent arg)
{
x[0] = arg.state.X.abs;
y[0] = arg.state.Y.abs;
if (arg.state.Z.rel < 0)
{
z[0]--;
}
else if (arg.state.Z.rel > 0)
{
z[0]++;
}
return true;
}
/// <summary>
/// マウスの状態を更新
/// </summary>
void UpdateState()
{
int min = (int)MouseButtonID.MB_Left;
int max = (int)MouseButtonID.MB_Button7;
for (int i = min; i <= max; i++)
{
MouseButtonID b = (MouseButtonID)i;
if (ButtonDown(b))
{
// 指定フレーム内に次のクリックがきたらダブルクリック
dclick[b] = (frames[b] < DOUBLE_CLICK_FRAMES);
frames[b] = 0;
}
else
{
frames[b]++;
dclick[b] = false;
}
buff[0][b] = buff[1][b];
}
x[1] = x[0];
y[1] = y[0];
z[1] = z[0];
}
/// <summary>
/// マウスの状態を更新
/// </summary>
public void Capture()
{
UpdateState();
if (mouse != null)
{
mouse.Capture();
}
}
/// <summary>
/// ボタンが押されたか確認
/// </summary>
/// <param name="button"></param>
/// <returns></returns>
public bool ButtonDown(MouseButtonID button)
{
return (buff[0][button] && !buff[1][button]);
}
/// <summary>
/// ボタンが押されたままか確認
/// </summary>
/// <param name="button"></param>
/// <returns></returns>
public bool ButtonPress(MouseButtonID button)
{
return (buff[0][button] && buff[1][button]);
}
/// <summary>
/// ボタンが押されたままか確認
/// </summary>
/// <param name="button"></param>
/// <returns></returns>
public bool ButtonPush(MouseButtonID button)
{
return (ButtonDown(button) || ButtonPress(button));
}
/// <summary>
/// ボタンが離されたか確認
/// </summary>
/// <param name="button"></param>
/// <returns></returns>
public bool ButtonUp(MouseButtonID button)
{
return (!buff[0][button] && buff[1][button]);
}
/// <summary>
/// ボタンがダブルクリックされたか確認
/// </summary>
/// <param name="button"></param>
/// <returns></returns>
public bool DoubleClick(MouseButtonID button)
{
return dclick[button];
}
/// <summary>
/// 開放処理
/// </summary>
public void Dispose()
{
if (mouse != null)
{
mouse.Dispose();
}
}
}
}
view raw gistfile1.cs hosted with ❤ by GitHub


4. ジョイスティック入力用コード。

using System;
using System.Windows.Interop;
using System.Windows.Media;
namespace MOIS
{
/// <summary>
/// ジョイスティック
/// </summary>
public class MOIS_JoyStick : IDisposable
{
private const int AXIS_ZERO_ZONE = 3000;
private const int AXIS_MAX = 1000;
private JoyStick[] joy;
private bool[][][] btnState = new bool[2][][];
private int[][] povState = new int[2][];
private int[][] axisLState = new int[2][];
private int[][] axisRState = new int[2][];
private int[][] sliderState = new int[2][];
private Vector3[] vec;
public MOIS_JoyStick()
{
}
/// <summary>
/// 初期化処理
/// </summary>
/// <param name="visual"></param>
public void CreateInput(Visual visual)
{
HwndSource source = (HwndSource)HwndSource.FromVisual(visual);
ParamList pl = new ParamList();
pl.Insert("WINDOW", source.Handle.ToString());
pl.Insert("w32_mouse", "DISCL_NONEXCLUSIVE");
pl.Insert("w32_mouse", "DISCL_FOREGROUND");
InputManager mgr = InputManager.CreateInputSystem(pl);
int numJoy = mgr.GetNumberOfDevices(Type.OISJoyStick);
joy = new JoyStick[numJoy];
btnState[0] = new bool[numJoy][];
btnState[1] = new bool[numJoy][];
povState[0] = new int[numJoy];
povState[1] = new int[numJoy];
axisLState[0] = new int[numJoy];
axisLState[1] = new int[numJoy];
axisRState[0] = new int[numJoy];
axisRState[1] = new int[numJoy];
sliderState[0] = new int[numJoy];
sliderState[1] = new int[numJoy];
vec = new Vector3[numJoy];
for (int i = 0; i < numJoy; i++)
{
joy[i] = (JoyStick)mgr.CreateInputObject(Type.OISJoyStick, true);
joy[i].AxisMoved += joy_AxisMoved;
joy[i].ButtonPressed += joy_ButtonPressed;
joy[i].ButtonReleased += joy_ButtonReleased;
joy[i].PovMoved += joy_PovMoved;
joy[i].SliderMoved += joy_SliderMoved;
joy[i].Vector3Moved += joy_Vector3Moved;
btnState[0][i] = new bool[joy[i].JoyStickState.ButtonCount];
btnState[1][i] = new bool[joy[i].JoyStickState.ButtonCount];
}
}
/// <summary>
/// Pov移動イベント
/// </summary>
/// <param name="arg"></param>
/// <param name="index"></param>
/// <returns></returns>
bool joy_PovMoved(JoyStickEvent arg, int index)
{
if ((arg.state.get_mPOV(index).direction & Pov_NativePtr.East) != 0)
{
povState[0][index] = 1;
}
else if ((arg.state.get_mPOV(index).direction & Pov_NativePtr.West) != 0)
{
povState[0][index] = -1;
}
if ((arg.state.get_mPOV(index).direction & Pov_NativePtr.South) != 0)
{
povState[1][index] = 1;
}
else if ((arg.state.get_mPOV(index).direction & Pov_NativePtr.North) != 0)
{
povState[1][index] = -1;
}
if (arg.state.get_mPOV(index).direction == Pov_NativePtr.Centered)
{
povState[0][index] = 0;
povState[1][index] = 0;
}
return true;
}
/// <summary>
/// ボタン押しイベント
/// </summary>
/// <param name="arg"></param>
/// <param name="button"></param>
/// <returns></returns>
bool joy_ButtonPressed(JoyStickEvent arg, int button)
{
btnState[0][arg.device.ID][button] = true;
return true;
}
/// <summary>
/// ボタン離れイベント
/// </summary>
/// <param name="arg"></param>
/// <param name="button"></param>
/// <returns></returns>
bool joy_ButtonReleased(JoyStickEvent arg, int button)
{
btnState[0][arg.device.ID][button] = false;
return true;
}
/// <summary>
/// アナログ移動イベント
/// </summary>
/// <param name="arg"></param>
/// <param name="axis"></param>
/// <returns></returns>
bool joy_AxisMoved(JoyStickEvent arg, int axis)
{
Axis_NativePtr state = arg.state.GetAxis(axis);
if (state.abs > AXIS_ZERO_ZONE || state.abs < -AXIS_ZERO_ZONE)
{
double d = (double)AXIS_MAX / (Int16.MaxValue - AXIS_ZERO_ZONE);
double v = (state.abs > 0) ?
(state.abs - AXIS_ZERO_ZONE) * d :
(state.abs + AXIS_ZERO_ZONE) * d;
if (axis < 2)
{
axisLState[axis][arg.device.ID] = (int)v;
}
else if (axis < 4)
{
axisRState[axis - 2][arg.device.ID] = (int)v;
}
}
else
{
if (axis < 2)
{
axisLState[axis][arg.device.ID] = 0;
}
else if (axis < 4)
{
axisRState[axis - 2][arg.device.ID] = 0;
}
}
return true;
}
/// <summary>
/// 3軸移動イベント
/// </summary>
/// <param name="arg"></param>
/// <param name="index"></param>
/// <returns></returns>
bool joy_Vector3Moved(JoyStickEvent arg, int index)
{
vec[index] = arg.state.GetVector(index);
return true;
}
/// <summary>
/// スライダー移動イベント
/// </summary>
/// <param name="arg"></param>
/// <param name="index"></param>
/// <returns></returns>
bool joy_SliderMoved(JoyStickEvent arg, int index)
{
Slider_NativePtr state = arg.state.get_mSliders(index);
sliderState[0][index] = state.abX;
sliderState[1][index] = state.abY;
return true;
}
/// <summary>
/// スライダー座標の取得
/// </summary>
/// <param name="id"></param>
/// <param name="x"></param>
/// <param name="y"></param>
public void GetSlider(int id, out int x, out int y)
{
if (0 <= id && id < joy.Length)
{
x = sliderState[0][id];
y = sliderState[1][id];
}
else
{
x = 0;
y = 0;
}
}
/// <summary>
/// 3軸座標の取得
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public Vector3 GetVector3(int id)
{
if (0 <= id && id < joy.Length)
{
return vec[id];
}
else
{
return new Vector3();
}
}
/// <summary>
/// 左アナログ座標の取得
/// </summary>
/// <param name="id"></param>
/// <param name="x"></param>
/// <param name="y"></param>
public void GetAxisL(int id, out int x, out int y)
{
if (0 <= id && id < joy.Length)
{
x = axisLState[0][id];
y = axisLState[1][id];
}
else
{
x = 0;
y = 0;
}
}
/// <summary>
/// 右アナログ座標の取得
/// </summary>
/// <param name="id"></param>
/// <param name="x"></param>
/// <param name="y"></param>
public void GetAxisR(int id, out int x, out int y)
{
if (0 <= id && id < joy.Length)
{
x = axisRState[0][id];
y = axisRState[1][id];
}
else
{
x = 0;
y = 0;
}
}
/// <summary>
/// Pov座標の取得
/// </summary>
/// <param name="id"></param>
/// <param name="x"></param>
/// <param name="y"></param>
public void GetPov(int id, out int x, out int y)
{
if (0 <= id && id < joy.Length)
{
x = povState[0][id];
y = povState[1][id];
}
else
{
x = 0;
y = 0;
}
}
/// <summary>
/// 上ボタンが押されたか確認
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public bool UpButtonDown(int id)
{
if (0 <= id && id < joy.Length)
{
int button = joy[id].JoyStickState.ButtonCount - 4;
return ButtonDown(id, button);
}
return false;
}
/// <summary>
/// 上ボタンが押されたままか確認
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public bool UpButtonPress(int id)
{
if (0 <= id && id < joy.Length)
{
int button = joy[id].JoyStickState.ButtonCount - 4;
return ButtonPress(id, button);
}
return false;
}
/// <summary>
/// 上ボタンが離れたか確認
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public bool UpBottonUp(int id)
{
if (0 <= id && id < joy.Length)
{
int button = joy[id].JoyStickState.ButtonCount - 4;
return ButtonUp(id, button);
}
return false;
}
/// <summary>
/// 上ボタンが押されたままか確認
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public bool UpButtonPush(int id)
{
return UpButtonDown(id) || UpButtonPress(id);
}
/// <summary>
/// 右ボタンが押されたか確認
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public bool RightButtonDown(int id)
{
if (0 <= id && id < joy.Length)
{
int button = joy[id].JoyStickState.ButtonCount - 3;
return ButtonDown(id, button);
}
return false;
}
/// <summary>
/// 右ボタンが押されたままか確認
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public bool RightButtonPress(int id)
{
if (0 <= id && id < joy.Length)
{
int button = joy[id].JoyStickState.ButtonCount - 3;
return ButtonPress(id, button);
}
return false;
}
/// <summary>
/// 右ボタンが離された確認
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public bool RightButtonUp(int id)
{
if (0 <= id && id < joy.Length)
{
int button = joy[id].JoyStickState.ButtonCount - 3;
return ButtonUp(id, button);
}
return false;
}
/// <summary>
/// 右ボタンが押されたままか確認
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public bool RightButtonPush(int id)
{
return RightButtonDown(id) || RightButtonPress(id);
}
/// <summary>
/// 下ボタンが押されたか確認
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public bool DownButtonDown(int id)
{
if (0 <= id && id < joy.Length)
{
int button = joy[id].JoyStickState.ButtonCount - 2;
return ButtonDown(id, button);
}
return false;
}
/// <summary>
/// 下ボタンが押されたままか確認
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public bool DownButtonPress(int id)
{
if (0 <= id && id < joy.Length)
{
int button = joy[id].JoyStickState.ButtonCount - 2;
return ButtonPress(id, button);
}
return false;
}
/// <summary>
/// 下ボタンが離された確認
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public bool DownButtonUp(int id)
{
if (0 <= id && id < joy.Length)
{
int button = joy[id].JoyStickState.ButtonCount - 2;
return ButtonUp(id, button);
}
return false;
}
/// <summary>
/// 下ボタンが押されたままか確認
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public bool DownButtonPush(int id)
{
return DownButtonDown(id) || DownButtonPress(id);
}
/// <summary>
/// 左ボタンが押されたか確認
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public bool LeftButtonDown(int id)
{
if (0 <= id && id < joy.Length)
{
int button = joy[id].JoyStickState.ButtonCount - 1;
return ButtonDown(id, button);
}
return false;
}
/// <summary>
/// 左ボタンが押されたままか確認
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public bool LeftButtonPress(int id)
{
if (0 <= id && id < joy.Length)
{
int button = joy[id].JoyStickState.ButtonCount - 1;
return ButtonPress(id, button);
}
return false;
}
/// <summary>
/// 左ボタンが離されたか確認
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public bool LeftButtonUp(int id)
{
if (0 <= id && id < joy.Length)
{
int button = joy[id].JoyStickState.ButtonCount - 1;
return ButtonUp(id, button);
}
return false;
}
/// <summary>
/// 左ボタンが押されたままか確認
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public bool LeftButtonPush(int id)
{
return LeftButtonDown(id) || LeftButtonPress(id);
}
/// <summary>
/// ボタンが押されたか確認
/// </summary>
/// <param name="id"></param>
/// <param name="button"></param>
/// <returns></returns>
public bool ButtonDown(int id, int button)
{
if (0 <= id && id < joy.Length && 0 <= button && button < btnState[0][0].Length)
{
return (btnState[0][id][button] && !btnState[1][id][button]);
}
return false;
}
/// <summary>
/// ボタンが押されたままか確認
/// </summary>
/// <param name="id"></param>
/// <param name="button"></param>
/// <returns></returns>
public bool ButtonPress(int id, int button)
{
if (0 <= id && id < joy.Length && 0 <= button && button < btnState[0][0].Length)
{
return (btnState[0][id][button] && btnState[1][id][button]);
}
return false;
}
/// <summary>
/// ボタンが離されたか確認
/// </summary>
/// <param name="id"></param>
/// <param name="button"></param>
/// <returns></returns>
public bool ButtonUp(int id, int button)
{
if (0 <= id && id < joy.Length && 0 <= button && button < btnState[0][0].Length)
{
return (!btnState[0][id][button] && btnState[1][id][button]);
}
return false;
}
/// <summary>
/// ボタンが押されたままか確認
/// </summary>
/// <param name="id"></param>
/// <param name="button"></param>
/// <returns></returns>
public bool ButtonPush(int id, int button)
{
return ButtonDown(id, button) || ButtonPress(id, button);
}
/// <summary>
/// 状態の更新
/// </summary>
public void Capture()
{
for (int i = 0; i < joy.Length; i++)
{
btnState[0][i].CopyTo(btnState[1][i], 0);
if (joy[i] != null)
{
joy[i].Capture();
}
}
}
/// <summary>
/// 開放処理
/// </summary>
public void Dispose()
{
for (int i = 0; i < joy.Length; i++)
{
if (joy[i] != null)
{
joy[i].Dispose();
}
}
}
}
}
view raw gistfile1.cs hosted with ❤ by GitHub


5. 大体の使い方。

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.Interop;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using DxLibDLL;
using MOIS;
namespace test002
{
public partial class MainWindow : Window
{
const int SCREEN_W = 800;
const int SCREEN_H = 600;
MOIS_Keyboard keybd = new MOIS_Keyboard();
MOIS_Mouse mouse = new MOIS_Mouse();
MOIS_JoyStick joy = new MOIS_JoyStick();
public MainWindow()
{
InitializeComponent();
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
keybd.CreateInput(this);
mouse.CreateInput(this, SCREEN_W, SCREEN_H);
joy.CreateInput(this);
dxImage.Init_DxLib(SCREEN_W, SCREEN_H);
}
private void Window_Closed(object sender, EventArgs e)
{
keybd.Dispose();
mouse.Dispose();
joy.Dispose();
dxImage.End_DxLib();
}
private void dxImage_Reset(object sender, EventArgs e)
{
// リセット処理
}
private void dxImage_Update(object sender, EventArgs e)
{
Title = dxImage.Fps;
keybd.Capture();
mouse.Capture();
joy.Capture();
// プログラム更新処理
}
private void dxImage_Render(object sender, EventArgs e)
{
// 描画処理
}
}
}
view raw gistfile1.cs hosted with ❤ by GitHub


以上。


0 件のコメント:

コメントを投稿