SQLの窓

2017年11月26日


C# でDXライブラリを使って簡単なシューティングをクラス化して標準化 / メインループとプレイヤー (4)



C# でDXライブラリを使って簡単なシューティングをクラス化して標準化 / メインループとプレイヤー (3) で、Game、Player という二つのクラスで、左右の矢印キーでプレイヤーの画像が左右に動く処理を標準化しました。

この Player クラスの機能をそのまま使って、背景を表示する Background クラスを追加します。背景画像はこちらからダウンロードできますが、サイズは 1007x1007 という中途半端なサイズになっています。

この画像はパターン画像で、左端が右端に続き、上端が下端に続く画像で、適当に作ったのでこのようなサイズになっています。ただ、1007 の幅なので、ゲーム画面の幅はこれ以内でないとうまく動作しないので注意して下さい。

Background クラス

背景は、プレイヤーの動きと逆に動くようになっています。また、背景は常に画面いっぱいに表示されるので、DrawRectGraph で描画しています。左端と右端を同時に更新する必要があるのですが、パターン画像なので、二つのエリアに分けて描画します。(矢印キーをずっと押し続けると、プレイヤーは画面の端で止まりますが、背景はずっと横スクロールし続けます)

現在横の動きだけなので二つの DrawRectGraph を使用していますが、縦の動きを入れる場合はさらに二つの DrawRectGraph が必要になる予定です。
		// *******************
		// コンストラクタ
		// *******************
		public Background(Game game, string name, int offset) {

			this.game = game;

			// 画像の読み込み
			image = DX.LoadGraph(name);

			// 画像のサイズを取得
			int w, h;
			DX.GetGraphSize(image, out w, out h);
			graph_w = w;
			graph_h = h;

			// 背景の初期位置
			x = 0;
			y = 0;

			move_offset = offset;

		}

		public int image { get; set; }
		public int graph_w { get; set; }
		public int graph_h { get; set; }
		public int x { get; set; }
		public int y { get; set; }
		public int move_offset { get; set; }
		public Game game { get; set; }

		// *******************
		// 描画
		// *******************
		internal void draw() {

			DX.DrawRectGraph(0, 0, this.graph_w - this.x, this.y, this.x, this.graph_h - this.y, this.image, 0, 0);
			DX.DrawRectGraph(this.x, 0, 0, this.y, this.graph_w, this.graph_h - this.y, this.image, 0, 0);

		}

		// *******************
		// 左移動
		// *******************
		internal void left() {

			this.x -= this.move_offset;

			// 背景は一周する
			if (this.x < 0) {
				// 左へ消えた部分は、右から出て来る
				this.x = this.graph_w;
			}

		}

		// *******************
		// 右移動
		// *******************
		internal void right() {

			this.x += 5;

			// 背景は一周する
			if (this.x >= this.graph_w) {
				// 右へ消えた部分は、左から出て来る
				this.x = 0;
			}

	
		}
	}


Background クラスを追加したメイン処理( Program クラス内 ) は以下のようになります

Program 内の処理

処理としては逆向きのメソッドをそれぞれ配置しただけのものになっています
			// メインゲームインスタンス作成
			Game game = new Game(800, 600);

			// 初期化
			game.init();

			// 背景インスタンス作成
			Background background = new Background(game, "field.png", 5);

			// プレイヤーインスタンス作成
			Player player = new Player(game, "player.png", 5);

			game.start(
				// *******************
				// 主処理
				// *******************
				(int counter) => {

					// 右矢印キー
					if (DX.CheckHitKey(DX.KEY_INPUT_RIGHT) == 1) {

						player.right();
						// player と 逆向き
						background.left();

					}

					// 左矢印キー
					if (DX.CheckHitKey(DX.KEY_INPUT_LEFT) == 1) {

						player.left();
						// player と 逆向き
						background.right();

					}

				},
				// *******************
				// 描画処理
				// *******************
				() => {

					background.draw();
					player.draw();

				}

			);



posted by lightbox at 2017-11-26 20:17 | Comment(0) | VS(C#) | このブログの読者になる | 更新情報をチェックする

C# でDXライブラリを使って簡単なシューティングをクラス化して標準化 / メインループとプレイヤー (3)



C# でDXライブラリを使って簡単なシューティングをクラス化して標準化 / メインループとプレイヤー (2) では、Player クラスを作成し、Player に依存する情報を Player クラス内にプロパティとして保存しました。

以下では、そのプロパティを使って、Player クラス内でデータを処理する為の right、left、draw メソッドを作成しています。

Player クラス
	class Player {

		// *******************
		// コンストラクタ
		// *******************
		public Player(Game game, string name, int offset) {

			this.game = game;

			// 画像の読み込み
			image = DX.LoadGraph(name);

			// 画像のサイズを取得
			int w, h;
			DX.GetGraphSize(image, out w, out h);
			graph_w = w;
			graph_h = h;

			// プレーヤーの初期位置
			x = game.screen_w / 2 - h / 2;
			y = game.screen_h - 70;

			move_offset = offset;

		}

		public int image { get; set; }
		public int graph_w { get; set; }
		public int graph_h { get; set; }
		public int x { get; set; }
		public int y { get; set; }
		public int move_offset { get; set; }
		public Game game { get; set; }

		// *******************
		// 描画
		// *******************
		internal void draw() {

			DX.DrawGraph(this.x, this.y, this.image, DX.TRUE);

		}

		// *******************
		// 右移動
		// *******************
		internal void right() {

			this.x += this.move_offset;
			if (this.x + this.graph_w > game.screen_w) {
				this.x = game.screen_w - this.graph_w;
			}

		}

		// *******************
		// 左移動
		// *******************
		internal void left() {

			this.x -= this.move_offset;
			if (this.x < 0) {
				this.x = 0;
			}

		}
	}


そして、以下ではこの Player クラスのメソッドを使用して、Program クラス内の記述を簡略化しています。
			// メインゲームインスタンス作成
			Game game = new Game(800, 600);

			// 初期化
			game.init();

			// プレイヤーインスタンス作成
			Player player = new Player(game, "player.png", 5);

			game.start(
				// *******************
				// 主処理
				// *******************
				(int counter) => {

					// 右矢印キー
					if (DX.CheckHitKey(DX.KEY_INPUT_RIGHT) == 1) {

						player.right();

					}

					// 左矢印キー
					if (DX.CheckHitKey(DX.KEY_INPUT_LEFT) == 1) {

						player.left();

					}

				},
				// *******************
				// 描画処理
				// *******************
				() => {

					player.draw();

				}

			);

関連する記事

C# でDXライブラリを使って簡単なシューティングをクラス化して標準化 / メインループとプレイヤー (4)




posted by lightbox at 2017-11-26 17:51 | Comment(0) | VS(C#) | このブログの読者になる | 更新情報をチェックする

C# でDXライブラリを使って簡単なシューティングをクラス化して標準化 / メインループとプレイヤー (2)



C# でDXライブラリを使って簡単なシューティングをクラス化して標準化 / メインループとプレイヤー (1) では、メインループと初期化部分を Game クラスとしてクラス化しました。(Game クラスの start メソッド内で、キーアクションの処理部分と描画部分を分けて、start の引数の無名ブロックを呼び出すようにしました。)

今回は、それに引き続いてプレイヤーを左右矢印キーで左右に動くようにしている部分をクラス化し、Player クラスを作成します。

プレイヤーの初期処理は、使用する画像の決定と一回のキー押下でどのくらい移動するかの距離を設定する事にしました。また、初期位置を画面下部中央に設置する為に、スクリーンサイズが必要になるので、Game クラスのインスタンスも同時に引き渡しています。

Player クラス
ここでは情報をプロパティとして定義しています。

1) image : 画像ハンドル
2) graph_w : 画像幅
3) graph_h : 画像高さ
4) x : 描画座標
5) y : 描画座標
6) move_offset : キー押下による移動距離
7) game : Game クラスのインスタンス
	class Player {

		// *******************
		// コンストラクタ
		// *******************
		public Player(Game game, string name, int offset) {

			this.game = game;

			// 画像の読み込み
			image = DX.LoadGraph(name);

			// 画像のサイズを取得
			int w, h;
			DX.GetGraphSize(image, out w, out h);
			graph_w = w;
			graph_h = h;

			// プレーヤーの初期位置
			x = game.screen_w / 2 - h / 2;
			y = game.screen_h - 70;

			// キー押下による移動距離
			move_offset = offset;

		}

		public int image { get; set; }
		public int graph_w { get; set; }
		public int graph_h { get; set; }
		public int x { get; set; }
		public int y { get; set; }
		public int move_offset { get; set; }
		public Game game { get; set; }
	}


次に、この Player クラスを使用して、Program クラスの記述を変更すると以下のようになります。

ただ、この時点ではまだ Player の処理が Program クラス での記述に依存してしまっているので、キーの処理と描画の処理を Player クラスのメソッドとして変更する必要があります
			// メインゲームインスタンス作成
			Game game = new Game(800, 600);

			// 初期化
			game.init();

			// プレイヤーインスタンス作成
			Player player = new Player(game, "player.png", 5);

			game.start(
				// *******************
				// 主処理
				// *******************
				(int counter) => {

					// 右矢印キー
					if (DX.CheckHitKey(DX.KEY_INPUT_RIGHT) == 1) {
						player.x += player.move_offset;
						if (player.x + player.graph_w > game.screen_w) {
							player.x = game.screen_w - player.graph_w;
						}
					}

					// 左矢印キー
					if (DX.CheckHitKey(DX.KEY_INPUT_LEFT) == 1) {
						player.x -= player.move_offset;
						if (player.x < 0) {
							player.x = 0;
						}
					}

				},
				// *******************
				// 描画処理
				// *******************
				() => {

					DX.DrawGraph(player.x, player.y, player.image, DX.TRUE);

				}

			);

関連する記事

C# でDXライブラリを使って簡単なシューティングをクラス化して標準化 / メインループとプレイヤー (3)



posted by lightbox at 2017-11-26 17:06 | Comment(0) | VS(C#) | このブログの読者になる | 更新情報をチェックする

2017年11月25日


C# でDXライブラリを使って簡単なシューティングをクラス化して標準化 / メインループとプレイヤー (1)



まずプロジェクトですが、DXライブラリのダウンロードから、C# 用をダウンロードしてそのまま動作する場合はそれでもいいですが、Visual Studio の 2010 では動かないので普通にプロジェクトを Windows アプリケーションで作成します。

次に、bin の下の実行場所に DxLib.dll と DxLib_x64.dll と DxLibDotNet.dll をコピーして、DxLibDotNet.dll を参照すれば使えるようになります。



以下のソースコードに関しては、player.png が必要ですが、シューティングゲーム用ドット絵フリー素材よりダウンロードして作成しました。


(DxLib.dll と同じ場所に保存します)

こちらはクラス化した C# テンプレートです。プロジェクトをテンプレートで作成したら、DxLib.dll と DxLib_x64.dll と DxLibDotNet.dll と player.png をコピーして DxLibDotNet.dll を参照します


クラス化なしのベタコード

このコードで、自機が左矢印キーと右矢印キーで左右に移動します。
using DxLibDLL;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace DX_001 {

	static class Program {

		[STAThread]
		static void Main() {

			// ウインドウモードで起動( コメントにするとフルスクリーン )
			DX.ChangeWindowMode(DX.TRUE);

			// スクリーンサイズ
			int screen_w = 800, screen_h = 600;
			DX.SetGraphMode(screen_w, screen_h, 32);

			// DXライブラリの初期化
			if (DX.DxLib_Init() < 0) {
				return;
			}

			// 描画先を裏画面に変更
			DX.SetDrawScreen(DX.DX_SCREEN_BACK);

			// 画像の読み込み
			int player = DX.LoadGraph("player.png");

			// 画像のサイズを取得
			int player_graph_w, player_graph_h;
			DX.GetGraphSize(player, out player_graph_w, out player_graph_h);

			// プレーヤーの初期位置
			int x = screen_w / 2 - player_graph_w / 2, y = screen_h - 70;

			int payer_move_offset = 5;

			// メインループ
			while (DX.ProcessMessage() != -1) {

				// ESC で終了
				if (DX.CheckHitKey(DX.KEY_INPUT_ESCAPE) == 1) {
					break;
				}

				// 右矢印キー
				if (DX.CheckHitKey(DX.KEY_INPUT_RIGHT) == 1) {
					x += payer_move_offset;
					if (x + player_graph_w > screen_w) {
						x = screen_w - player_graph_w;
					}
				}
				// 左矢印キー
				if (DX.CheckHitKey(DX.KEY_INPUT_LEFT) == 1) {
					x -= payer_move_offset;
					if (x < 0) {
						x = 0;
					}
				}
				// 上矢印キー
				if (DX.CheckHitKey(DX.KEY_INPUT_UP) == 1) {
				}
				// 下矢印キー
				if (DX.CheckHitKey(DX.KEY_INPUT_DOWN) == 1) {
				}
				// スペースキー
				if (DX.CheckHitKey(DX.KEY_INPUT_SPACE) == 1) {
				}

				// 画面をクリア
				DX.ClearDrawScreen();

				// プレイヤーを描画
				DX.DrawGraph(x, y, player, DX.TRUE);

				// 裏画面の内容を表画面に反映する
				DX.ScreenFlip();
			}

			// DXライブラリの後始末
			DX.DxLib_End();
		}
	}

}


このままいろいろ機能を実装して行くと、とてもメンテしにくいコードになるので、まずゲームの本体である初期化とメインループをクラス化し、メインループ用の start メソッドの引数の無名処理を呼び出すようにしました。

Game クラスを作成して使用
	static class Program {

		[STAThread]
		static void Main() {

			// メインゲームインスタンス作成
			Game game = new Game(800, 600);

			// 初期化
			game.init();

			// 画像の読み込み
			int player = DX.LoadGraph("player.png");

			// 画像のサイズを取得
			int player_graph_w, player_graph_h;
			DX.GetGraphSize(player, out player_graph_w, out player_graph_h);

			// プレーヤーの初期位置
			int x = game.screen_w / 2 - player_graph_w / 2, y = game.screen_h - 70;

			int payer_move_offset = 5;

			game.start(
				// *******************
				// 主処理
				// *******************
				(int counter) => {

					// 右矢印キー
					if (DX.CheckHitKey(DX.KEY_INPUT_RIGHT) == 1) {
						x += payer_move_offset;
						if (x + player_graph_w > game.screen_w) {
							x = game.screen_w - player_graph_w;
						}
					}

					// 左矢印キー
					if (DX.CheckHitKey(DX.KEY_INPUT_LEFT) == 1) {
						x -= payer_move_offset;
						if (x < 0) {
							x = 0;
						}
					}

				},
				// *******************
				// 描画処理
				// *******************
				() => {

					DX.DrawGraph(x, y, player, DX.TRUE);

				}

			);



		}
	}


Game クラス

public void start(main_action call, draw_action draw) として定義されているので、内側から call と draw を呼び出して呼び出し元のコードを実行させます。

こうする事によって、ループ処理の中をキー処理と描画処理を分けて解りやすく記述できるようになります。

呼び出し元は、ラムダ式で単純なブロックを作成して記述が可能です。
class Game {

	// 外部呼出し用
	public delegate void main_action(int counter);
	public delegate void draw_action();

	// メインループカウント
	private int loopCount = 0;

	// スクリーンサイズ
	public int screen_w;
	public int screen_h;

	// *******************
	// コンストラクタ
	// *******************
	public Game(int w, int h) {
		screen_w = w;
		screen_h = h;
	}

	// *******************
	// 初期化
	// *******************
	public void init() {

		// ウインドウモードで起動( コメントにするとフルスクリーン )
		DX.ChangeWindowMode(DX.TRUE);

		// スクリーンサイズ
		DX.SetGraphMode(screen_w, screen_h, 32);

		// DXライブラリの初期化
		if (DX.DxLib_Init() < 0) {
			return;
		}

		// 描画先を裏画面に変更
		DX.SetDrawScreen(DX.DX_SCREEN_BACK);

	}

	// *******************
	// メインループ開始
	// *******************
	public void start(main_action call, draw_action draw) {


		// メインループ
		while (DX.ProcessMessage() != -1) {

			// ESC で終了
			if (DX.CheckHitKey(DX.KEY_INPUT_ESCAPE) == 1) {
				break;
			}

			// 外部を呼び出し
			call(loopCount);
			loopCount++;
			if (loopCount > 100000) {
				loopCount = 0;
			}

			// 画面をクリア
			DX.ClearDrawScreen();

			// 外部を呼び出し(描画処理用)
			draw();

			// 裏画面の内容を表画面に反映する
			DX.ScreenFlip();

		}

		// DXライブラリの後始末
		DX.DxLib_End();

	}

}


関連する記事

C# でDXライブラリを使って簡単なシューティングをクラス化して標準化 / メインループとプレイヤー (2)


posted by lightbox at 2017-11-25 22:07 | Comment(0) | VS(C#) | このブログの読者になる | 更新情報をチェックする

2017年11月06日


Visual Studio 2012 : 表示メニューから、ツールボックス等のコマンドが消えてしまった場合の個別登録

原因は解りませんが、きっとどこかに Visual Studio のデフォルト状態のメニューの定義があると思うのですが、見つける事ができていません。(コマンドの追加に『リセット』とかあるので)

良く使うウインドウ表示コマンドを、自分で登録してみます。

▼ メニューをカスタマイズするコマンドの場所

(これが消えていたら、どうしていいかは現在未調査)

▼ 表示する位置の決定


この Visual Studio は正常なので、『出力』も『ツールボックス』もあります。無い場合はこのあたりを選択してコマンドの追加ボタンをクリックします。

▼ コマンドの選択


ウインドウの表示コマンドは、『表示』の中にあると思います。画像のスクロールバー位置を参考に探して下さい。



posted by lightbox at 2017-11-06 10:47 | Comment(0) | VS(C#) | このブログの読者になる | 更新情報をチェックする

2017年10月29日


C# : Microsoft Access のテーブルとビューの一覧と任意の SQL を実行するテンプレート

Visual Studio 2012 で作成しています。
(C:\Users\ユーザ\Documents\Visual Studio 2012\Templates\ProjectTemplates に保存します)





Access を参照すると、テーブル一覧とビュー一覧が表示され、テーブルまたはビューをダブルクリックすると、行を表示するテンプレートです。

システムテーブル表示をチェックすると、Access のシステムテーブルを表示しますが、ユーザと権限の管理でシステムテーブルへのアクセス権限が設定できるのは、.mdb ファイルのみになります。

サンプルデータ / 販売管理C.accdb と 販売管理C.mdb



以下はシステムテーブルを表示したものですが、表示できないデータは x となっています。



using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Data.OleDb;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace SqlUnitAccess2 {
	public partial class Form1 : Form {

		// ファイル選択用
		private OpenFileDialog ofd = new OpenFileDialog();

		// *********************
		// コンストラクタ
		// *********************
		public Form1() {
			InitializeComponent();
		}

		// *********************
		// 画面初期処理
		// *********************
		private void Form1_Load(object sender, EventArgs e) {

			// *********************
			// タイトル表示変更
			// *********************
			this.Text = "SqlUnitAccess";

		}

		// *********************
		// 参照ボタン
		// *********************
		private void ref_Click(object sender, EventArgs e) {

			// *********************
			// ファイル選択
			// *********************
			ofd.Filter = "Access(*.mdb;*.accdb)|*.mdb;*.accdb|すべてのファイル(*.*)|*.*";
			ofd.FilterIndex = 1;
			ofd.Title = "Access データベースを選択してください";
			ofd.RestoreDirectory = true;

			if (ofd.ShowDialog() != DialogResult.OK) {
				return;
			}

			// *********************
			// タイトル表示変更
			// *********************
			this.Text = ofd.FileName;

			// *********************
			// テーブル一覧表示
			// *********************
			loadTables(ofd.FileName);

		}

		// *********************
		// 実行ボタン
		// *********************
		private void action_Click(object sender, EventArgs e) {

			string sql = textBox1.Text;
			// *********************
			// select 実行
			// *********************
			executeReader(ofd.FileName, sql);

		}

		// *********************
		// テーブル一覧ダブルクリック
		// *********************
		private void tabel_Select(object sender, DataGridViewCellEventArgs e) {

			// *********************
			// table 名取得
			// *********************
			string value = dataGridTables.Rows[e.RowIndex].Cells[0].Value.ToString();
			textBox1.Text = "select * from " + value;

			// *********************
			// select 実行
			// *********************
			executeReader(ofd.FileName, textBox1.Text);

		}

		// *********************
		// テーブル一覧表示
		// *********************
		private void loadTables(string path) {

			dataGridSelect.DataSource = null;

			using (OleDbConnection myCon = new OleDbConnection()) {

				// *********************
				// 接続文字列の作成
				// *********************
				myCon.ConnectionString = string.Format("Provider=Microsoft.ACE.OLEDB.12.0;Data Source={0};", path);

				// *********************
				// 接続
				// *********************
				try {
					// 接続文字列を使用して接続
					myCon.Open();
				}
				catch (Exception ex) {
					MessageBox.Show(this, ex.Message);
					return;
				}

				DataTable dataTable = null;
				if (checkBoxSysTable.Checked) {
					// *********************
					// 全て
					// *********************
					dataTable = myCon.GetOleDbSchemaTable(
						OleDbSchemaGuid.Tables,
						new object[] { null, null, null, null }
					);
				}
				else {
					// *********************
					// TABLE と VIEW をマージ
					// *********************
					dataTable = myCon.GetOleDbSchemaTable(
						OleDbSchemaGuid.Tables,
						new object[] { null, null, null, "TABLE" }
					);
					DataTable dataTable2 = myCon.GetOleDbSchemaTable(
						OleDbSchemaGuid.Tables,
						new object[] { null, null, null, "VIEW" }
					);
					dataTable.Merge(dataTable2);
				}

				// 表示しない列は削除
				dataTable.Columns.Remove("TABLE_CATALOG");
				dataTable.Columns.Remove("TABLE_SCHEMA");
				//dataTable.Columns.Remove("TABLE_TYPE");
				dataTable.Columns.Remove("TABLE_GUID");
				dataTable.Columns.Remove("DESCRIPTION");
				dataTable.Columns.Remove("TABLE_PROPID");
				dataTable.Columns.Remove("DATE_CREATED");
				dataTable.Columns.Remove("DATE_MODIFIED");

				// 表示
				dataGridTables.DataSource = dataTable;

				// 接続解除
				myCon.Close();
			}

			// カラム幅の自動調整
			dataGridSelect.AutoResizeColumns();
		}

		// *********************
		// select 実行
		// *********************
		private void executeReader(string path, string sql) {

			using (OleDbConnection myCon = new OleDbConnection())
			using (OleDbCommand myCommand = new OleDbCommand()) {

				// *********************
				// 接続文字列の作成
				// *********************
				myCon.ConnectionString = string.Format("Provider=Microsoft.ACE.OLEDB.12.0;Data Source={0};", path);

				// *********************
				// 接続
				// *********************
				try {
					// 接続文字列を使用して接続
					myCon.Open();
					// コマンドオブジェクトに接続をセット
					myCommand.Connection = myCon;
					// コマンドを通常 SQL用に変更
					myCommand.CommandType = System.Data.CommandType.Text;
				}
				catch (Exception ex) {
					MessageBox.Show(this, ex.Message);
					return;
				}

				// *********************
				// 実行 SQL
				// *********************
				myCommand.CommandText = sql;

				// *********************
				// レコードセット取得
				// *********************
				try {
					using (OleDbDataReader myReader = myCommand.ExecuteReader()) {

						DataTable dataTable = new DataTable();
						dataTable.Load(myReader);
						dataGridSelect.DataSource = dataTable;

						// リーダを使い終わったので閉じる
						myReader.Close();
					}
				}
				catch (Exception ex) {
					myCon.Close();
					MessageBox.Show(this, ex.Message);
					return;
				}

				// 接続解除
				myCon.Close();

			}

			// カラム幅の自動調整
			dataGridSelect.AutoResizeColumns();
		}

		// *********************
		// システム表の表示エラー対応
		// *********************
		private void dataGridSelect_DataError(object sender, DataGridViewDataErrorEventArgs e) {

		}


	}
}




posted by lightbox at 2017-10-29 02:24 | Comment(0) | VS(C#) | このブログの読者になる | 更新情報をチェックする

2017年10月03日


C# でDXライブラリを使って簡単なシューティング部分を作るサンプル

とても久しぶりに DXライブラリ を覗いてみたら、とても現役で利用されているようなのでVisualC# 用パッケージをダウンロードして、シューティング部分を実装してみました。

C++ で作成したのは、2006年なので、もう11年経ってますが、更新履歴を見たらずっと途切れなくあったので、凄いなぁと感心するばかりです。

ダウンロードしたサンプルは VisualStudio2015 とありますが、手元の VisualStudio2013 で動作しています。まあ、DLL 読んで使ってるだけだから、動くはずですけれど。

以下は Program.cs の中そのままです。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
using DxLibDLL;

namespace VisualStudio2015
{
	static class Program
	{
		const int SHOT_STRAIGHT = 0;
		const int SHOT_LEFT = 1;
		/// <summary>
		/// アプリケーションのメイン エントリ ポイントです。
		/// </summary>
		[STAThread]
		static void Main()
		{
			// ウインドウモードで起動( コメントにするとフルスクリーン )
			DX.ChangeWindowMode(DX.TRUE);

			// DXライブラリの初期化
			if (DX.DxLib_Init() < 0)
			{
				return;
			}

			// 描画先を裏画面に変更
			DX.SetDrawScreen(DX.DX_SCREEN_BACK);

			// 画像の読み込み
			int GraphHandle = DX.LoadGraph("play.bmp");
			// 画像の縦横サイズ
			int gsize = 64;

			// 弾の存在フラグ等の属性を持つクラス
			Shot[] shot = { new Shot(), new Shot() };

			// 初期位置
			int x = 300, y = 400;

			// メインループ
			while (DX.ProcessMessage() != -1)
			{
				// ESC で終了
				if (DX.CheckHitKey(DX.KEY_INPUT_ESCAPE) == 1) {
					break;
				}

				// 右矢印キー
				if (DX.CheckHitKey(DX.KEY_INPUT_RIGHT) == 1) {
					x += 3;
					if (x + gsize > 640) {
						x = 640 - gsize;
					}
				}
				// 左矢印キー
				if (DX.CheckHitKey(DX.KEY_INPUT_LEFT) == 1) {
					x -= 3;
					if (x < 0) {
						x = 0;
					}
				}

				// スペースキー
				if (shot[SHOT_STRAIGHT].exist == 0) {
					if (DX.CheckHitKey(DX.KEY_INPUT_SPACE) == 1) {
						shot[SHOT_STRAIGHT].exist = 1;
						shot[SHOT_STRAIGHT].x = x;
						shot[SHOT_STRAIGHT].y = y;
					}
				}
				// Zキー
				if (shot[SHOT_LEFT].exist == 0) {
					if (DX.CheckHitKey(DX.KEY_INPUT_Z) == 1) {
						shot[SHOT_LEFT].exist = 1;
						shot[SHOT_LEFT].x = x;
						shot[SHOT_LEFT].y = y;
					}
				}

				// 画面をクリア
				DX.ClearDrawScreen();

				// プレイヤーを描画
				DX.DrawGraph(x, y, GraphHandle, DX.TRUE);

				// 弾1を描画
				if (shot[SHOT_STRAIGHT].exist == 1) {
					shot[SHOT_STRAIGHT].y -= 8;
					if (shot[SHOT_STRAIGHT].y < 0 - gsize) {
						shot[SHOT_STRAIGHT].exist = 0;
					}
				}
				if (shot[SHOT_STRAIGHT].exist == 1) {
					DX.DrawGraph(shot[SHOT_STRAIGHT].x, shot[SHOT_STRAIGHT].y, GraphHandle, DX.TRUE);
				}

				// 弾2を描画
				if (shot[SHOT_LEFT].exist == 1) {
					shot[SHOT_LEFT].y -= 8;
					if (shot[SHOT_LEFT].y < 0 - gsize) {
						shot[SHOT_LEFT].exist = 0;
						// 方向を左へリセット
						shot[SHOT_LEFT].direction = 0;
					}
					else {
						if (shot[SHOT_LEFT].direction == 0) {
							shot[SHOT_LEFT].x -= 8;
						}
						if (shot[SHOT_LEFT].direction == 1) {
							shot[SHOT_LEFT].x += 8;
						}
						if (shot[SHOT_LEFT].x < 0) {
							shot[SHOT_LEFT].direction = 1;
						}
						if (shot[SHOT_LEFT].x > 640 - gsize) {
							shot[SHOT_LEFT].direction = 0;
						}
					}
				}
				if (shot[SHOT_LEFT].exist == 1) {
					DX.DrawGraph(shot[SHOT_LEFT].x, shot[SHOT_LEFT].y, GraphHandle, DX.TRUE);
				}


				// 裏画面の内容を表画面に反映する
				DX.ScreenFlip();
			}

			// DXライブラリの後始末
			DX.DxLib_End();
		}

		private class Shot {

			public Shot() {
				this.exist = 0;
				this.direction = 0;
			}

			public int exist { get; set; }
			public int x { get; set; }
			public int y { get; set; }
			public int direction { get; set; }
		}
	}
}

play.bmp は適当に背景透過で 64x64 のサイズのものを使って下さい。元々のサンプルの実行フォルダに Src1.bmp という画像があります。それと同じ場所に置いて下さい。
※ 自分が使っているのは、11年前に作ったドット絵

※ 弾の時に、回転させたりしてたので、いびつな輪郭です。

仕様としては、以下のようなものです。

1) ESC で終了
2) 左右矢印キーで、プレイヤーキャラクタ(画像)を移動できる
3) SPACE キーで直線の弾
4) Zキーで、左斜めへの弾(跳ね返ると右へ)
5) プレイヤーキャラクタと弾の画像は同じ

※ 弾は二種類で、それぞれキーに依存。
※ 弾が画面内に一つある場合、二つ目は打てない
※ 違うキーの弾は同一画面に存在できる

なので、キーを増やして弾の種類を増やすのは比較的容易なはずです。ただ、ソースコードが長くなるので、それぞれはメソッドやクラスに変えるべきですけれど。

画像は弾毎に変えればいいし、左から右へ移動するだけの敵を作成して、あたり判定して爆破するのもそう難しくは無いと思います。

仕上げとしては、爆発アニメーションを組み込んで、背景を組み込んで左右のキーで背景を反対方向に移動させるとそれなりに見えると思います。



posted by lightbox at 2017-10-03 15:32 | Comment(0) | VS(C#) | このブログの読者になる | 更新情報をチェックする

2017年09月28日


Microsoft Access に対してSQLを入力してその結果を DataGridView に表示する最も簡単なコード



最初に .accdb か .mdb を選択しておいて、自由な SQL をタイプしてその結果をそのまま Excel のごとく DataGridView に表示します。

DataGridView に表示するデータは全て文字列扱いとして、ArrayList に随時行を追加して、Rows.Add に、ToArray() したものをセットします。

一応表示のみを想定しているので、以下の設定を最初にします


表示件数は多すぎると時間がかかりすきるので、固定で 100 件にしています。
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Data.OleDb;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WinApp1 {
	public partial class Form1 : Form {

		private OpenFileDialog ofd = new OpenFileDialog();

		public Form1() {
			InitializeComponent();
		}

		private void button1_Click(object sender, EventArgs e) {

			using (OleDbConnection myCon = new OleDbConnection())
			using (OleDbCommand myCommand = new OleDbCommand()) {

				// *********************
				// 接続文字列の作成
				// *********************
				myCon.ConnectionString = string.Format("Provider=Microsoft.ACE.OLEDB.12.0;Data Source={0};", ofd.FileName);
				Debug.WriteLine(myCon.ConnectionString);

				// *********************
				// 接続
				// *********************
				try {
					// 接続文字列を使用して接続
					myCon.Open();
					// コマンドオブジェクトに接続をセット
					myCommand.Connection = myCon;
					// コマンドを通常 SQL用に変更
					myCommand.CommandType = System.Data.CommandType.Text;
				}
				catch (Exception ex) {
					MessageBox.Show(this,ex.Message);
					return;
				}

				// *********************
				// 実行 SQL
				// *********************
				myCommand.CommandText = textBox1.Text;

				// *********************
				// レコードセット取得
				// *********************
				try {
					using (OleDbDataReader myReader = myCommand.ExecuteReader()) {

						// *********************
						// 列数
						// *********************
						int nCols = myReader.FieldCount;

						// DataGridView 初期化
						dataGridView1.Columns.Clear();
						dataGridView1.ColumnCount = nCols;		// カラム数

						Type fldType;
						ArrayList rowData = new ArrayList();

						// データ取得と表示
						int maxCount = 0;
						while (myReader.Read()) {

							// 行データをセットする ArrayList をクリア
							rowData.Clear();

							maxCount++;
							if ( maxCount > 100 ) {
								break;
							}

							// 初回のみ、タイトル文字列を設定
							if (maxCount == 1) {
								for (int idx = 0; idx < nCols; idx++) {
									dataGridView1.Columns[idx].Name = myReader.GetName(idx);
								}
							}

							// 行データの作成( ArrayList で作成して ToArray() したものを Rows.Add )
							for (int idx = 0; idx <nCols; idx++) {

								// NULL でない場合
								if (!myReader.IsDBNull(idx)) {
									// 列のデータ型を取得
									fldType = myReader.GetFieldType(idx);

									// 文字列
									if (fldType.Name == "String") {
										rowData.Add(myReader.GetValue(idx).ToString());
									}
									else if (fldType.Name == "Int32") {
										rowData.Add(myReader.GetInt32(idx).ToString());
									}
									else if (fldType.Name == "DateTime") {
										rowData.Add(myReader.GetDateTime(idx).ToString());
									}
									else {
										rowData.Add(myReader.GetValue(idx).ToString());
									}

								}
								else {
									rowData.Add("");
								}
							}

							// 行追加 ( BuildArray() は配列を作成する為のメソッド )
							dataGridView1.Rows.Add(rowData.ToArray());

						}

						// リーダを使い終わったので閉じる
						myReader.Close();
					}
				}
				catch (Exception ex) {
					myCon.Close();
					MessageBox.Show(this, ex.Message);
					return;
				}

				myCon.Close();

				// カラム幅の自動調整
				dataGridView1.AutoResizeColumns();

			}		// 最外の using の終わり

		}

		private void button2_Click(object sender, EventArgs e) {

			// *********************
			// ファイル選択
			// *********************
			ofd.Filter = "Excel(*.mdb;*.accdb)|*.mdb;*.accdb|すべてのファイル(*.*)|*.*";
			ofd.FilterIndex = 1;
			ofd.Title = "Access データベースを選択してください";
			ofd.RestoreDirectory = true;

			if (ofd.ShowDialog() != DialogResult.OK) {
				return;
			}


		}		// click イベントの終わり

	}		// class の終わり
}


※ テーブル・ビュー一覧は以下のようにして簡単に表示できます
			using (OleDbConnection myCon = new OleDbConnection())
			using (OleDbCommand myCommand = new OleDbCommand()) {

				// *********************
				// 接続文字列の作成
				// *********************
				myCon.ConnectionString = string.Format("Provider=Microsoft.ACE.OLEDB.12.0;Data Source={0};", ofd.FileName);
				Debug.WriteLine(myCon.ConnectionString);

				// *********************
				// 接続
				// *********************
				try {
					// 接続文字列を使用して接続
					myCon.Open();
					// コマンドオブジェクトに接続をセット
					myCommand.Connection = myCon;
					// コマンドを通常 SQL用に変更
					myCommand.CommandType = System.Data.CommandType.Text;
				}
				catch (Exception ex) {
					MessageBox.Show(this,ex.Message);
					return;
				}

				DataTable dataTable = myCon.GetOleDbSchemaTable(
					OleDbSchemaGuid.Tables,
					new object[] { null, null, null, null }
				);
				// TABLE のみの場合は以下( 上記は 全て )
				//	new object[] { null, null, null, "TABLE" }

				dataGridView1.DataSource = dataTable;

				myCon.Close();

				// カラム幅の自動調整
				dataGridView1.AutoResizeColumns();

			}		// 最外の using の終わり

さらに SQL の実行結果は、データの途中加工が全くできなくなりますが、DataTable を使って以下のようにさらに短く記述する事ができます
				// *********************
				// 実行 SQL
				// *********************
				myCommand.CommandText = textBox1.Text;

				try
				{
					using (OleDbDataReader myReader = myCommand.ExecuteReader())
					{
						DataTable dataTable = new DataTable();

						dataTable.Load(myReader);

						dataGridView1.DataSource = dataTable;
		
						myReader.Close();
					}

				}
				catch (Exception ex)
				{
					myCon.Close();
					MessageBox.Show(this, ex.Message);
					return;
				}

DataSource プロパティを使用した場合、新たに直接データをセットしていきたい場合は、いったん DataSource プロパティに null を設定しておく必要があります。



posted by lightbox at 2017-09-28 19:53 | Comment(0) | VS(C#) | このブログの読者になる | 更新情報をチェックする

2017年09月19日


System.Data.OleDb で select into 構文を使って簡単に Microsoft Access のデータを他の データベースにエクスポートする

結論から言うと、System.Data.OleDb と ADO で Microsoft Access に接続すると同等の処理ができます。元々、ADO で可能だった処理を System.Data.OleDb で可能かどうか確認し、System.Data.Odbc でとこまで同じ事が可能か試してみました。

結果的に、System.Data.Odbc では ODBC の動的接続では処理不可で、DSN を作成すると可能でした。

テスト用コード
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Data.Odbc;
using System.Data.OleDb;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace OdbcAccessTest {
	public partial class Form1 : Form {

		// *************************************
		// System.Data.Odbc
		// *************************************
		private OdbcConnection myCon;
		private OdbcCommand myCommand;
		private OdbcDataReader myReader;

		// *************************************
		// System.Data.OleDb
		// *************************************
		private OleDbConnection myConAccess;

		// *************************************
		// ADO
		// *************************************
		private dynamic objAdoCon;

		public Form1() {
			InitializeComponent();
		}

		// *************************************
		// System.Data.Odbc で Access データの読み込み
		// *************************************
		private void button1_Click(object sender, EventArgs e) {

			string myQuery = "SELECT * from 社員マスタ";

			using (myCommand = new OdbcCommand()) {
				// 実行する為に必要な情報をセット
				myCommand.CommandText = myQuery;
				myCommand.Connection = myCon;

				using (myReader = myCommand.ExecuteReader()) {

					// 読み出し

					while (myReader.Read()) {
						// 文字列
						Console.Write(GetValue(myReader, "社員コード") + " : ");
						Console.Write(GetValue(myReader, "氏名") + " : ");
						Console.Write(GetValue(myReader, "フリガナ") + " : ");
						// 整数
						Console.Write(GetValue(myReader, "給与") + " : ");
						Console.Write(GetValue(myReader, "手当") + " : ");
						// 日付
						Console.Write(GetValue(myReader, "作成日") + " : ");
						Console.Write(GetValue(myReader, "更新日") + " : ");

						Console.WriteLine();

					}

					myReader.Close();
				}

			}

		}

		// *************************************
		// テスト用簡易列データ取得
		// *************************************
		private string GetValue(OdbcDataReader myReader, string p) {

			string ret = "";
			int fld = 0;

			// 指定された列名より、テーブル内での定義順序番号を取得
			fld = myReader.GetOrdinal(p);
			// 定義順序番号より、NULL かどうかをチェック
			if (myReader.IsDBNull(fld)) {
				ret = "";
			}
			else {
				// NULL でなければ内容をオブジェクトとして取りだして文字列化する
				ret = myReader.GetValue(fld).ToString();
			}

			// 列の値を返す
			return ret;
		}

		// *************************************
		// 接続処理
		// *************************************
		private void Form1_Load(object sender, EventArgs e) {

			// *************************************
			// System.Data.Odbc
			// *************************************
			OdbcConnectionStringBuilder builder = new OdbcConnectionStringBuilder();

			builder.Driver = "Microsoft Access Driver (*.mdb, *.accdb)";
			builder.Add("dbq", @"C:\tmp\販売管理C.accdb");
			// 内容を確認
			Console.WriteLine(builder.ConnectionString);

			// 新しい OdbcConnection オブジェクトを作成
			myCon = new OdbcConnection();

			// 接続文字列を設定
			myCon.ConnectionString = builder.ConnectionString;

			// 接続を開く
			try {
				myCon.Open();
			}
			catch (OdbcException ex) {
				MessageBox.Show(this, "接続エラーです:" + ex.Message);
			}

			// *************************************
			// System.Data.OleDb
			// *************************************
			myConAccess = new OleDbConnection();
			myConAccess.ConnectionString = string.Format("Provider=Microsoft.ACE.OLEDB.12.0;Data Source={0};", @"C:\tmp\販売管理C.accdb");
			// 接続を開く
			try {
				myConAccess.Open();
			}
			catch (Exception ex) {
				MessageBox.Show(this, "接続エラーです:" + ex.Message);
			}
	
			// *************************************
			// ADO
			// *************************************
			objAdoCon = Activator.CreateInstance(Type.GetTypeFromProgID("ADODB.Connection"));

			string connectionString = @"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\tmp\001\販売管理C.accdb;";
			try {
				objAdoCon.Open(connectionString);
			}
			catch (Exception ex) {
				MessageBox.Show(this, ex.Message);
			}
		}

		// *************************************
		// 接続解除
		// *************************************
		private void Form1_FormClosed(object sender, FormClosedEventArgs e) {

			myCon.Close();
			myConAccess.Close();
			objAdoCon.Close();

		}

		// *************************************
		// System.Data.OleDb
		// *************************************
		private void button2_Click(object sender, EventArgs e) {

			string myQuery;

			myQuery = @"select * into [Excel 8.0;DATABASE=c:\tmp\販売管理C.xls].商品マスタ_OleDb from 商品マスタ";
			//myQuery = @"select * into [Excel 12.0 xml;DATABASE=c:\tmp\販売管理C.xlsx].商品マスタ_OleDb from 商品マスタ";
			//myQuery = @"select * into [;DATABASE=C:\tmp\データベース1.accdb].商品マスタ_OleDb from 商品マスタ";
			//myQuery = @"select * into [;DATABASE=C:\tmp\データベース1.mdb].商品マスタ_OleDb from 商品マスタ";
			//myQuery = @"select * into [ODBC;DSN=SQS64;Database=lightbox;UID=sa;PWD=password].商品マスタ_OleDb from 商品マスタ";
			//myQuery = @"select * into [ODBC;DSN=SQS32;Database=lightbox;UID=sa;PWD=password].商品マスタ_OleDb from 商品マスタ";
			//myQuery = @"select * into [ODBC;DSN=MYSQL32;Database=lightbox;UID=root;PWD=password].商品マスタ_OleDb from 商品マスタ";
			//myQuery = @"select * into [ODBC;Driver={SQL Server Native Client 11.0};server=layla;database=lightbox;uid=sa;pwd=password].商品マスタ_OleDb from 商品マスタ";
			//myQuery = @"select * into [ODBC;Driver={MySQL ODBC 5.3 Unicode Driver};server=layla;database=lightbox;uid=root;pwd=password].商品マスタ_OleDb from 商品マスタ";

			using (OleDbCommand myCommand = new OleDbCommand()) {

				// *********************
				// 接続
				// *********************
				try {
					// コマンドオブジェクトに接続をセット
					myCommand.Connection = myConAccess;
					myCommand.CommandText = myQuery;
					myCommand.ExecuteNonQuery();

				}
				catch (Exception ex) {
					MessageBox.Show(this, ex.Message);
				}
			}

		}

		// *************************************
		// System.Data.Odbc
		// *************************************
		private void button3_Click(object sender, EventArgs e) {

			string myQuery;

			myQuery = @"select * into [Excel 8.0;DATABASE=c:\tmp\販売管理C.xls].商品マスタ_Odbc from 商品マスタ";
			//myQuery = @"select * into [Excel 12.0 xml;DATABASE=c:\tmp\販売管理C.xlsx].商品マスタ_Odbc from 商品マスタ";
			//myQuery = @"select * into [;DATABASE=C:\tmp\データベース1.accdb].商品マスタ_Odbc from 商品マスタ";
			//myQuery = @"select * into [;DATABASE=C:\tmp\データベース1.mdb].商品マスタ_Odbc from 商品マスタ";
			//myQuery = @"select * into [ODBC;DSN=SQS64;Database=lightbox;UID=sa;PWD=password].商品マスタ_Odbc from 商品マスタ";
			//myQuery = @"select * into [ODBC;DSN=SQS32;Database=lightbox;UID=sa;PWD=password].商品マスタ_Odbc from 商品マスタ";
			//myQuery = @"select * into [ODBC;DSN=MYSQL32;Database=lightbox;UID=root;PWD=password].商品マスタ_Odbc from 商品マスタ";

			using (myCommand = new OdbcCommand()) {

				try {
					// コマンドオブジェクトに接続をセット
					myCommand.Connection = myCon;
					myCommand.CommandText = myQuery;
					myCommand.ExecuteNonQuery();
				}
				catch (Exception ex) {
					MessageBox.Show(this, ex.Message);
				}
			}

		}

		// *************************************
		// ADO を使う場合
		// *************************************
		private void button4_Click(object sender, EventArgs e) {

			string myQuery;

			myQuery = @"select * into [Excel 8.0;DATABASE=c:\tmp\販売管理C.xls].商品マスタ_ADO from 商品マスタ";
			//myQuery = @"select * into [Excel 12.0 xml;DATABASE=c:\tmp\販売管理C.xlsx].商品マスタ_ADO from 商品マスタ";
			//myQuery = @"select * into [;DATABASE=C:\tmp\データベース1.accdb].商品マスタ_ADO from 商品マスタ";
			//myQuery = @"select * into [;DATABASE=C:\tmp\データベース1.mdb].商品マスタ_ADO from 商品マスタ";
			//myQuery = @"select * into [ODBC;DSN=SQS64;Database=lightbox;UID=sa;PWD=password].商品マスタ_ADO from 商品マスタ";
			//myQuery = @"select * into [ODBC;DSN=SQS32;Database=lightbox;UID=sa;PWD=password].商品マスタ_ADO from 商品マスタ";
			//myQuery = @"select * into [ODBC;DSN=MYSQL32;Database=lightbox;UID=root;PWD=password].商品マスタ_ADO from 商品マスタ";
			//myQuery = @"select * into [ODBC;Driver={SQL Server Native Client 11.0};server=layla;database=lightbox;uid=sa;pwd=password].商品マスタ_ADO from 商品マスタ";
			//myQuery = @"select * into [ODBC;Driver={MySQL ODBC 5.3 Unicode Driver};server=layla;database=lightbox;uid=root;pwd=password].商品マスタ_ADO from 商品マスタ";

			try {
				objAdoCon.Execute(myQuery);
			}
			catch (Exception ex) {
				MessageBox.Show(this, ex.Message);
			}

		}

	}
}

ここでは、into 側の表で使用していますが、from 側の表でも使用できるはずです。エクスポートは高速で実行されますが、キーの定義はエクスポートされないので、後から定義する必要があります。

SQL 一覧
@"select * into [Excel 8.0;DATABASE=c:\tmp\販売管理C.xls].商品マスタ_ADO from 商品マスタ";
@"select * into [Excel 12.0 xml;DATABASE=c:\tmp\販売管理C.xlsx].商品マスタ_ADO from 商品マスタ";
@"select * into [;DATABASE=C:\tmp\データベース1.accdb].商品マスタ_ADO from 商品マスタ";
@"select * into [;DATABASE=C:\tmp\データベース1.mdb].商品マスタ_ADO from 商品マスタ";
@"select * into [ODBC;DSN=SQS64;Database=lightbox;UID=sa;PWD=password].商品マスタ_ADO from 商品マスタ";
@"select * into [ODBC;DSN=SQS32;Database=lightbox;UID=sa;PWD=password].商品マスタ_ADO from 商品マスタ";
@"select * into [ODBC;DSN=MYSQL32;Database=lightbox;UID=root;PWD=password].商品マスタ_ADO from 商品マスタ";
@"select * into [ODBC;Driver={SQL Server Native Client 11.0};server=layla;database=lightbox;uid=sa;pwd=password].商品マスタ_ADO from 商品マスタ";
@"select * into [ODBC;Driver={MySQL ODBC 5.3 Unicode Driver};server=layla;database=lightbox;uid=root;pwd=password].商品マスタ_ADO from 商品マスタ";


外部参照部分一覧
[Excel 8.0;DATABASE=c:\tmp\販売管理C.xls].テーブル名
[Excel 12.0 xml;DATABASE=c:\tmp\販売管理C.xlsx].テーブル名
[;DATABASE=C:\tmp\データベース1.accdb].テーブル名
[;DATABASE=C:\tmp\データベース1.mdb].テーブル名
[ODBC;DSN=SQS64;Database=lightbox;UID=sa;PWD=password].テーブル名
[ODBC;DSN=SQS32;Database=lightbox;UID=sa;PWD=password].テーブル名
[ODBC;DSN=MYSQL32;Database=lightbox;UID=root;PWD=password].テーブル名
[ODBC;Driver={SQL Server Native Client 11.0};server=layla;database=lightbox;uid=sa;pwd=password].テーブル名
[ODBC;Driver={MySQL ODBC 5.3 Unicode Driver};server=layla;database=lightbox;uid=root;pwd=password].テーブル名

Excel と Microsoft Access は特殊ですが、ODBC は同じ書式なので他の DB にも使用可能なはずです。接続パラメータは、実際 DSN を作成してから、レジストリを見れば必要なものが全て書かれています。

▼ エクスポートでは使えませんが、以下は Excel を ODBC で定義した場合の例です


PHP で ODBC 接続するとなると、上記データを使って以下のようになります
$ms_excel = "./data/syain.xls";
$ms_excel = realpath($ms_excel);
$excel_dir = dirname($ms_excel);
$connect_string = "Driver={Microsoft Excel Driver (*.xls, *.xlsx, *.xlsm, *.xlsb)};dbq={$ms_excel};DefaultDir={$excel_dir};FIL=Excel 8.0;DriverID=790";$user="";$pass="";




posted by lightbox at 2017-09-19 00:48 | Comment(0) | VS(C#) | このブログの読者になる | 更新情報をチェックする

2017年08月17日


C# : System.Data.OleDb で Microsoft Access のデータを読み取る

出力ウインドウに結果を表示する為に、Debug.WriteLine を使用していますが、他のメッセージが邪魔なので、デバッグ =>オプション の 『出力』で、【全てのデバッグ出力】以外を オフにしています。



元々は、VB.net でしたが、Telerik Code Converter で変換して少し手を加えました。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.OleDb;
using System.Diagnostics;

namespace MsAccess1 {
	class Program {
		static void Main(string[] args) {

			using (OleDbConnection myCon = new OleDbConnection())
			using (OleDbCommand myCommand = new OleDbCommand())
			{
				// SQL文字列格納用
				string myQuery = null;
				string myPath = @"C:\tmp\販売管理C.accdb";
//				string myPath = @"C:\tmp\販売管理C.mdb";	// 古い MsAccess

				// 接続文字列の作成
				myCon.ConnectionString = string.Format("Provider=Microsoft.ACE.OLEDB.12.0;Data Source={0};", myPath);
				// 出力ウインドウに表示
				// デバッグ>オプション の 『出力』で、【全てのデバッグ出力】以外を オフにする
				Debug.WriteLine(myCon.ConnectionString);

				// *********************
				// 接続
				// *********************
				try {
					// 接続文字列を使用して接続
					myCon.Open();
					// コマンドオブジェクトに接続をセット
					myCommand.Connection = myCon;
					// コマンドを通常 SQL用に変更
					myCommand.CommandType = System.Data.CommandType.Text;
				}
				catch (Exception ex) {
					Debug.WriteLine(ex.Message);
					return;
				}

				myQuery = "select * from 社員マスタ";
				myCommand.CommandText = myQuery;

				// *********************
				// レコードセット取得
				// *********************
				try {
					using (OleDbDataReader myReader = myCommand.ExecuteReader())
					{
						// *********************
						// 列数
						// *********************
						int nCols = myReader.FieldCount;
						Type fldType;

						// カラムループ用
						int idx = 0;
						while (myReader.Read()) {

							for (idx = 0; idx <= nCols - 1; idx++) {
								if (idx != 0) {
									Debug.Write(",");
								}

								// NULL でない場合
								if (!myReader.IsDBNull(idx)) {
									// 列のデータ型を取得
									fldType = myReader.GetFieldType(idx);

									// 文字列
									if (fldType.Name == "String") {
										Debug.Write(myReader.GetValue(idx) + "");
										continue;
									}
									if (fldType.Name == "Int32") {
										Debug.Write(myReader.GetInt32(idx).ToString() + "");
										continue;
									}
									if (fldType.Name == "DateTime") {
										Debug.Write(myReader.GetDateTime(idx).ToString() + "");
										continue;
									}

									Debug.Write(myReader.GetValue(idx).ToString() + "");

								}
								else {
									Debug.Write("");
								}
							}
							// 1行の最後
							Debug.WriteLine("");

						}

						// リーダを使い終わったので閉じる
						myReader.Close();
					}
				}
				catch (Exception ex) {
					myCon.Close();
					Debug.WriteLine(ex.Message);
					return;
				}

				myCon.Close();

			}	// 最外の using の終わり

		}	// Main の終わり
	}	// class の終わり
}	// namespace の終わり




posted by lightbox at 2017-08-17 23:15 | Comment(0) | VS(C#) | このブログの読者になる | 更新情報をチェックする

2017年08月06日


C#(VS2010) : dynamic 型を使用して CreateObject と同等に Scripting.FileSystemObject を使用する

ボタンを一つフォームに貼って、固定パスの SHIFT_JIS テキストファイルを読み込んでいます。

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;

namespace WinFormsApp1 {
	public partial class Form1 : Form {

		private dynamic objFile;

		public Form1() {
			InitializeComponent();
		}

		private void button1_Click(object sender, EventArgs e) {

			string buffer;
			try {
				dynamic inFile = objFile.OpenTextFile(@"c:\tmp\help.txt", 1);
				while (!inFile.AtEndOfStream) {
					buffer = inFile.ReadLine();
					Console.Out.WriteLine(buffer);
				}
				inFile.close();
			}
			catch (Exception ex) {
				MessageBox.Show("ファイルが存在しません");
			}

		}

		private void Form1_Load(object sender, EventArgs e) {

			objFile = Activator.CreateInstance(Type.GetTypeFromProgID("Scripting.FileSystemObject"));

		}

		private void Form1_FormClosed(object sender, FormClosedEventArgs e) {

			System.Runtime.InteropServices.Marshal.ReleaseComObject(objFile);

		}
	}
}


参考ページ

C#でCreateObjectと同じことをするには?(dobon.net) のコメント部分

dynamic 型の使用(docs.microsoft.com)



タグ:VS C#
posted by lightbox at 2017-08-06 22:04 | Comment(0) | VS(C#) | このブログの読者になる | 更新情報をチェックする

2017年06月03日


VS(C#) : DataGrid に バインドを使用して JSON データの配列を表示する( Json.NET を使用 )



JSON 文字列を Json.NET で一行でデシリアライズします。その際、バインド用の ObservableCollection に直接セットするので、DataGrid には、DataContext にセットするだけで、表示用の列と行は自動作成されます

外部ライブラリ

JSON データの扱いには、Json.NET を使用します。ダウンロードして、Bin フォルダにある自分の環境に該当するフレームワークフォルダを ソリューションの中に置いて参照設定を行います。
※ net45 フォルダをコピーして使用しました / VS2012

JSON データ

https://lightbox.sakura.ne.jp/demo/json/syain_json.php

このデータを扱う為に以下のクラスを作成しています

Syain.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace WpfAppDataGridFromWeb {
	class Syain {
		public string 社員コード { get; set; }
		public string 氏名 { get; set; }

		public string フリガナ { get; set; }
		public string 所属 { get; set; }

		private string _性別;
		public string 性別 {
			get {
				if (this._性別 == "0") {
					return "男";
				}
				else {
					return "女";
				}
			}
			set {
				this._性別 = value;
			}
		}
		public int 給与 { get; set; }
		public int? 手当 { get; set; }
		public string 管理者 { get; set; }

		public string 作成日 { get; set; }
		public string 更新日 { get; set; }

	}
}


画面

デフォルトで True になっていますが、バインドで列を自動作成させる為に 『AutoGenerateColumns="True"』を DataGrid に設定しています
<Window
	x:Class="WpfAppDataGridFromWeb.MainWindow"
	xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
	xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
	Title="MainWindow"
	Height="857.456"
	Width="1191.774">
	<Grid>
		<Button
			Content="Button"
			HorizontalAlignment="Left"
			Height="24"
			Margin="27,29,0,0"
			VerticalAlignment="Top"
			Width="122"
			Click="Button_Click" />
		<DataGrid
			x:Name="dataGrid"
			HorizontalAlignment="Left"
			Height="720"
			Margin="27,71,0,0"
			VerticalAlignment="Top"
			Width="1124"
			ItemsSource="{Binding}"
			IsReadOnly="True"
			MouseDoubleClick="dataGrid_MouseDoubleClick" />

	</Grid>
</Window>


処理
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Data;
using System.Data.Odbc;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
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;

namespace WpfAppDataGridFromWeb {

	public partial class MainWindow : Window {

		public MainWindow() {
			InitializeComponent();
			// ウインドウを中央へ
			this.WindowStartupLocation = WindowStartupLocation.CenterScreen;
		}

		private void Button_Click(object sender, RoutedEventArgs e) {

			dataGrid.Columns.Clear();

			Console.WriteLine("クリックされました");
			Console.WriteLine(Directory.GetCurrentDirectory());

			string url = "https://lightbox.sakura.ne.jp/demo/json/syain_json.php";
			string result = "[\"error\"]";

			// 信頼性のある WebClient で インターネットアクセス
			WebClient wc = new System.Net.WebClient();
			wc.Encoding = System.Text.Encoding.UTF8;
			try {
				// 読み込み
				result = wc.DownloadString(url);
			}
			catch( Exception ex) {
				Console.WriteLine("WebClient エラー:" + ex.ToString());
			}

			// JSON オブジェクト配列 Newtonsoft.Json( net45 )
			ObservableCollection<Syain> syain_data = JsonConvert.DeserializeObject<ObservableCollection<Syain>>(result);
			// DataGrid にバインド
			dataGrid.DataContext = syain_data;

		}

		// DataGrid をダブルクリックした時の行データの取得
		private void dataGrid_MouseDoubleClick(object sender, MouseButtonEventArgs e) {
			int row = dataGrid.SelectedIndex;
			if ( row >= 0 ) {
				Syain syain = (Syain)dataGrid.Items.GetItemAt(row);
				Debug.WriteLine(syain.社員コード + "|" + syain.氏名);

				MessageBox.Show(syain.社員コード + "|" + syain.氏名,
					"確認",
					MessageBoxButton.OK,
					MessageBoxImage.Information);
			}
		}

	}
}

※ HttpClient はバグがあるという話なので使用していません。

関連する記事

Swing の JTable に 1) WEBのJSON2次元配列。2) WEB の JSON配列 を取り込んで表示する( Google Gson と okhttp を使用 )

補足

以下の例では、AutoGenerateColumns="False" に設定して、列の定義をプログラムで行っています。このほうがアプリケーションとしては、列単位で仕様を決定しやすいので自由度が増すはずです。

※ データは JSON の2次元配列を使用しています
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Data;
using System.Data.Odbc;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
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;

namespace WpfAppDataGridFromWeb {

	public partial class MainWindow : Window {

		private DataGridTextColumn col;
		private ObservableCollection<Syain> syain_list = null;

		public MainWindow() {
			InitializeComponent();
			// ウインドウを中央へ
			this.WindowStartupLocation = WindowStartupLocation.CenterScreen;
		}

		private void Button_Click(object sender, RoutedEventArgs e) {

			dataGrid.Columns.Clear();

			Console.WriteLine("クリックされました");
			Console.WriteLine(Directory.GetCurrentDirectory());

			string url = "https://lightbox.sakura.ne.jp/demo/json/syain_array.php";
			string result = "[\"error\"]";

			// 信頼性のある WebClient で インターネットアクセス
			WebClient wc = new System.Net.WebClient();
			wc.Encoding = System.Text.Encoding.UTF8;
			try {
				// 読み込み
				result = wc.DownloadString(url);
			}
			catch( Exception ex) {
				Console.WriteLine("WebClient エラー:" + ex.ToString());
			}

			// JSON 2次元配列 Newtonsoft.Json( net45 )
			string[][] syain_data = JsonConvert.DeserializeObject<string[][]>(result);

			// バインド用クラス
			Syain syain;
			// 列用
			col = null;
			// バインド用コレクション
			syain_list = new ObservableCollection<Syain>();

			foreach (string[] syain_row in syain_data) {

				// 初回
				if (col == null) {
					foreach (string syain_col in syain_row) {
						col = new DataGridTextColumn();
						col.Header = syain_col;
						col.Binding = new Binding(syain_col);
						dataGrid.Columns.Add(col);
					}
					continue;
				}

				syain = new Syain();
				syain.社員コード = syain_row[0];
				syain.氏名 = syain_row[1];
				syain.フリガナ = syain_row[2];
				syain.所属 = syain_row[3];
				syain.性別 = syain_row[4];
				syain.給与 = int.Parse(syain_row[7]);
				syain.手当 = (syain_row[8] == "" ? 0 : int.Parse(syain_row[8]));
				syain.管理者 = syain_row[9];
				syain.作成日 = syain_row[5];
				syain.更新日 = syain_row[6];
				// observablecollection に追加
				syain_list.Add(syain);

			}

			//// DataGrid にバインド
			dataGrid.DataContext = syain_list;

		}

		// DataGrid をダブルクリックした時の行データの取得
		private void dataGrid_MouseDoubleClick(object sender, MouseButtonEventArgs e) {
			int row = dataGrid.SelectedIndex;
			if ( row >= 0 ) {
				Syain syain = (Syain)dataGrid.Items.GetItemAt(row);
				Debug.WriteLine(syain.社員コード + "|" + syain.氏名);

				MessageBox.Show(syain.社員コード + "|" + syain.氏名,
					"確認",
					MessageBoxButton.OK,
					MessageBoxImage.Information);
			}
		}

	}
}




タグ:C# Json.NET JSON
posted by lightbox at 2017-06-03 20:31 | Comment(0) | VS(C#) | このブログの読者になる | 更新情報をチェックする

2017年04月18日


csc.exe を使用して、コマンドプロンプトから C# 5 のアプリケーションをビルドする



32ビット用 : %windir%\Microsoft.NET\Framework\v4.0.30319
64ビット用 : %windir%\Microsoft.NET\Framework64\v4.0.30319

以下64ビット環境です。
※ Windows10 でも動作していますが、以下のメッセージが出力されます
This compiler is provided as part of the Microsoft (R) .NET Framework, but only supports language versions up to C# 5, which is no longer the latest version.
csc.exe は、c# 用のコンパイラです。面倒な場所ではあるので、以下のスクリプトで簡単にプロンプトが作成できます
<JOB>
<RESOURCE id="commandList">
<![CDATA[
mode con: cols=120
set PATH=%windir%\Microsoft.NET\Framework64\v4.0.30319;%PATH%
prompt C#$G
]]>
</RESOURCE>

<OBJECT id="WshShell" progid="WScript.Shell" />
<OBJECT id="Fso" progid="Scripting.FileSystemObject" />

<SCRIPT language=VBScript>
' ***********************************************************
' 処理開始
' ***********************************************************

strPath = WScript.ScriptFullName
Set obj = Fso.GetFile( strPath )
Set obj = obj.ParentFolder
WshShell.CurrentDirectory = obj.Path

aData = Split( GetInline( "commandList" ), vbCrLf )
strCommand = "cmd.exe /k " & aData(0)
For I = 1 to Ubound( aData )
	strCommand = strCommand & "&" & aData(I)
Next
Call WshShell.Run( strCommand, 3 )

' ***********************************************************
' 関数
' ***********************************************************
Function GetInline( strName )

	GetInline = RegTrim( getResource( strName ) ) & vbCrLf

End Function
Function RegTrim( strValue )

	Dim regEx, str

	Set regEx = New RegExp
	regEx.IgnoreCase = True
	regEx.Pattern = "^[ \s]+"
	str = regEx.Replace( strValue, "" )
	regEx.Pattern = "[ \s]+$"
	RegTrim = regEx.Replace( str, "" )

End Function
</SCRIPT>
</JOB>

VBScript で記述されており、通常エクスプローラから実行すると最大化ウインドウでコマンドプロンプトが開くように作成してあります。

コマンドプロンプトからは、csc ソースコード.cs と入力するだけで基本的なビルドはすぐできます。

sample.cs
using System;
using System.IO;

// ********************************************************
// 実行
// ********************************************************
public class App
{

	public static void Main() {

		// PATH 環境変数取得
		String strEnv = Environment.GetEnvironmentVariable( "PATH" );

		// 配列定義
		String delimStr = ";";
		Char[] delimiter = delimStr.ToCharArray();

		String[] split = null;

		// トークン分割
		split = strEnv.Split( delimiter );

		// ソート
		Array.Sort( split, split.GetLowerBound(0), split.Length );

		// 書き込み
		try {
			StreamWriter OutFile = new StreamWriter( @".\result.txt", false );
			foreach (String strValue in split) {
				OutFile.WriteLine( strValue );
			}
			OutFile.Flush();
			OutFile.Close();
	
		}
		catch( Exception e ) {
			Console.WriteLine("エラーの内容 : {0}", e.ToString());
		}
	}

}

オプションは csc /? で表示されます。

mysql.cs( ODBC アクセス )
using Microsoft.VisualBasic;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.Data.Odbc;

public class App
{

	// ********************************************************
	// MySQL / System.Data.Odbc
	// ********************************************************

	public static void Main()
	{
		string myConnectString = "Driver={MySQL ODBC 5.3 Unicode Driver};" + "SERVER=localhost;" + "DATABASE=lightbox;" + "UID=root;" + "PWD=password";

		OdbcConnection myCon = new OdbcConnection();
		myCon.ConnectionString = myConnectString;
		myCon.Open();

		string myQuery = "SELECT 社員マスタ.*,DATE_FORMAT(生年月日,'%Y-%m-%d') as 誕生日" + " from 社員マスタ";
		OdbcCommand myCommand = new OdbcCommand();
		myCommand.CommandText = myQuery;
		myCommand.Connection = myCon;

		OdbcDataReader myReader = default(OdbcDataReader);
		myReader = myCommand.ExecuteReader();


		while (myReader.Read()) {
			// 文字列
			Console.Write(GetValue(myReader, "社員コード") + " : ");
			Console.Write(GetValue(myReader, "氏名") + " : ");

			// 整数
			Console.Write(GetValue(myReader, "給与") + " : ");

			// 日付
			Console.Write(GetValue(myReader, "作成日") + " : ");
			Console.Write(GetValue(myReader, "更新日") + " : ");
			Console.Write(GetValue(myReader, "生年月日") + " : ");
			Console.Write(GetValue(myReader, "誕生日"));
			Console.WriteLine();

		}

		myReader.Close();

		myQuery = "update 社員マスタ set 生年月日 = '1982/01/01'" + " where 社員コード = '0002'";
		Execute(myCon, myQuery);

		myCon.Close();

		myReader.Dispose();
		myCon.Dispose();

	}

	// ********************************************************
	// 列データ取得
	// ********************************************************
	public static string GetValue(OdbcDataReader odr, string strName)
	{

		string ret = "";
		int fld = 0;

		fld = odr.GetOrdinal(strName);
		if (odr.IsDBNull(fld)) {
			ret = "";
		} else {
			ret = odr.GetValue(fld).ToString();
		}

		return ret;

	}

	// ********************************************************
	// 更新処理
	// ********************************************************
	public static int Execute(OdbcConnection cn, string SQL)
	{

		int ret = 0;
		OdbcCommand execCommand = new OdbcCommand();

		execCommand.CommandText = SQL;
		execCommand.Connection = cn;
		try {
			ret = execCommand.ExecuteNonQuery();
		} catch (Exception ex) {
			Console.WriteLine(ex.Message);
		}
		execCommand.Dispose();

		return ret;

	}

}




タグ:C#
posted by lightbox at 2017-04-18 22:08 | Comment(0) | VS(C#) | このブログの読者になる | 更新情報をチェックする

2016年07月01日


キネクトでブラウザを動かす

必要なもの

1) キネクト
2) Visual Studio
3) Kinect for Windows SDK v1.7
4) Kinect PowerPoint Control

Kinect PowerPoint Control の概要

結局のところ、Kinect の基本的な機能のとても簡単なサンプルです( 音声認識部分もありますが、日本語がどうかわからないので試していません )。
Power Point での使用を想定して作られたようですが、右手が頭より、X 軸で(外側に) 45センチ離れたら 右矢印キーを押し、左手が頭より、X 軸で(外側に) 45センチ離れたら 左矢印キーを押すという機能のみ実装されています。

ここでは、3箇所しか認識させていませんが、同様にして 20箇所の人体の部分を認識可能です。

なので、少しコードを触るだけで、ジェスチャーによるキーコマンドをいくつでも追加できます。そして、ブラウザ側では、jQuery を使って .keydown で受ければいろいろな画面展開が可能になるでしょう。

コマンド受付部分(ここを改造)
        private void ProcessForwardBackGesture(Joint head, Joint rightHand, Joint leftHand)
        {
            // 頭と右手が x 座標で 45 センチ離れた場合に 右矢印キーを押した事にする
            if (rightHand.Position.X > head.Position.X + 0.45)
            {
                if (!isForwardGestureActive)
                {
                    isForwardGestureActive = true;
                    System.Windows.Forms.SendKeys.SendWait("{Right}");
                }
            }
            else
            {
                isForwardGestureActive = false;
            }

            // 頭と左手が x 座標で 45 センチ離れた場合に 左矢印キーを押した事にする
            if (leftHand.Position.X < head.Position.X - 0.45)
            {
                if (!isBackGestureActive)
                {
                    isBackGestureActive = true;
                    System.Windows.Forms.SendKeys.SendWait("{Left}");
                }
            }
            else
            {
                isBackGestureActive = false;
            }
        }

※ 各コマンド用のフラグは MainWindow クラスの変数として追加定義します

実際動かすと良く解りますが、頭と手が認識されると赤い丸が表示され、コマンドを送れる位置に移動すると大きな緑の丸に変化します。コマンドは、いったん赤い丸に戻してからでないと、再度実行する事はできません。

また、認識には少なくとも 150センチ離れる必要があり、C キーで認識円の表示を消す事ができるようです。

画面定義
<Window x:Class="KinectPowerPointControl.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Kinect PowerPoint Control"
        Height="480"
        Width="640"
        WindowState="Maximized">
    <Viewbox Stretch="Uniform">
        <Grid>
            <Image Name="videoImage"
                   Width="640"
                   Height="480"></Image>
            <Canvas Background="Transparent">
                <Ellipse Fill="Red"
                         Height="20"
                         Width="20"
                         Name="ellipseLeftHand"
                         Stroke="White" />
                <Ellipse Fill="Red"
                         Height="20"
                         Width="20"
                         Name="ellipseRightHand"
                         Stroke="White" />
                <Ellipse Fill="Red"
                         Height="20"
                         Width="20"
                         Name="ellipseHead"
                         Stroke="White" />
            </Canvas>
        </Grid>
    </Viewbox>
</Window>

※ videoImage に、映像が表示され、最初左上に赤い丸が表示されています。

プログラムの中核となる部分
        void sensor_SkeletonFrameReady(object sender, SkeletonFrameReadyEventArgs e)
        {
            using (var skeletonFrame = e.OpenSkeletonFrame())
            {
                if (skeletonFrame == null)
                    return;

                if (skeletons == null ||
                    skeletons.Length != skeletonFrame.SkeletonArrayLength)
                {
                    skeletons = new Skeleton[skeletonFrame.SkeletonArrayLength];
                }

                skeletonFrame.CopySkeletonDataTo(skeletons);
            }

            Skeleton closestSkeleton = skeletons.Where(s => s.TrackingState == SkeletonTrackingState.Tracked)
                                                .OrderBy(s => s.Position.Z * Math.Abs(s.Position.X))
                                                .FirstOrDefault();

            if (closestSkeleton == null)
                return;

            // 頭
            var head = closestSkeleton.Joints[JointType.Head];
            // 右手
            var rightHand = closestSkeleton.Joints[JointType.HandRight];
            // 左手
            var leftHand = closestSkeleton.Joints[JointType.HandLeft];

            // NotTracked : 追跡していない
            if (head.TrackingState == JointTrackingState.NotTracked ||
                rightHand.TrackingState == JointTrackingState.NotTracked ||
                leftHand.TrackingState == JointTrackingState.NotTracked)
            {
                //Don't have a good read on the joints so we cannot process gestures
                return;
            }

            // MainWindow.xaml に定義された ellipse
            SetEllipsePosition(ellipseHead, head, false);
            SetEllipsePosition(ellipseLeftHand, leftHand, isBackGestureActive);
            SetEllipsePosition(ellipseRightHand, rightHand, isForwardGestureActive);

            ProcessForwardBackGesture(head, rightHand, leftHand);
        }


二つのフラグが立って初めてコマンドを送れるようにも出来ますし、20箇所の場所を使えばいろいろかなりコマンドを作れると思います。また、ブラウザ上の位置とキネクトの座標とを同期させてコマンドを発動する事もできるでしょう。




posted by lightbox at 2016-07-01 07:31 | Comment(0) | VS(C#) | このブログの読者になる | 更新情報をチェックする

2014年09月18日


VS(C#) : Json.NET を使用して文字列形式の JSON をプログラムで参照する具体的な方法

一番可読性の良い、管理しやすい方法は、JSON のフォーマットと同じ項目を持つ『クラス』を作成して一括変換する方法です。JSON の中の階層は、そのまま実装するクラスの中で配列にしたり、さらに細かいクラスを作成して対応します。

手っ取り早い方法は、JObject にパースして、JavaScript 内で参照する方法と同じ書式で参照します。いずれにしても、JavaScript との連携になる場合も考えて、どちらを使うかを決定すればいいと思います。

テスト用 JSON
{
    "id": 91500526,
    "simple_array": [1,2,3,4,5],
    "object_array": [
        {"high":1,"middle":2,"low":3},
        {"high":21,"middle":22,"low":23},
        {"high":31,"middle":32,"low":33}
    ],
    "object_data": {"sworc":"lightbox"},
    "profile_background_tile": false,
    "notifications": false,
    "profile_sidebar_fill_color": "FFF7CC",
    "location": "\u5927\u962a\u5e9c",
    "screen_name": "sworc",
    "profile_image_url": "http:\/\/a0.twimg.com\/profile_images\/2388651010\/zmq5cwm5nsvngpfrtr3f_normal.png"
}
クラスを使った一括変換

元々の JSON に合うフォーマットのクラスを事前に作成して、JsonConvert.DeserializeObject<クラス名>(文字列); で変換します。後は、クラスとして参照するだけです。

Serializing Collections,Deserializing Collections,Deserializing Dictionaries

JObject を使った参照

JObject jo = JObject.Parse(文字列); を実行して、jo を使って参照します。実際の JavaScript と同様の ["文字列"] 形式でプロパティを参照して行きます
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json;

namespace Json130906
{
    class Program
    {
        static string hl = "-----------------------------------------------------";
        static string json = null;
        static void Main(string[] args)
        {
            // 処理全体を簡単に try 〜 catch する為に
            JsonTest jt = new JsonTest();
            try
            {
                jt.Test();

                Console.WriteLine(hl);
                Console.ReadLine();
                // ******************************************
                // クラスを使った一括変換
                // ******************************************
                MyJson data = JsonConvert.DeserializeObject<MyJson>(json);
                Console.WriteLine(data.id.ToString());
                Console.Write(
                    "{0}:{1}:{2}:{3}:{4}\n{5}:{6}:{7}\n{8}:{9}:{10}\n{11}:{12}:{13}\n",
                    data.simple_array[0].ToString(),
                    data.simple_array[1].ToString(),
                    data.simple_array[2].ToString(),
                    data.simple_array[3].ToString(),
                    data.simple_array[4].ToString(),
                    data.object_array[0].high.ToString(),
                    data.object_array[0].middle.ToString(),
                    data.object_array[0].low.ToString(),
                    data.object_array[1].high.ToString(),
                    data.object_array[1].middle.ToString(),
                    data.object_array[1].low.ToString(),
                    data.object_array[2].high.ToString(),
                    data.object_array[2].middle.ToString(),
                    data.object_array[2].low.ToString()
                );
                Console.WriteLine(data.object_data["sworc"]);
                Console.WriteLine(data.profile_background_tile);
                Console.WriteLine(data.notifications);
                Console.WriteLine(data.profile_sidebar_fill_color);
                Console.WriteLine(data.location);
                Console.WriteLine(data.screen_name);
                Console.WriteLine(data.profile_image_url);

            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }

            Console.WriteLine(hl);
            Console.WriteLine("処理を終了しました");
            Console.ReadLine();

        }

        // ******************************************
        // 処理用クラス
        // ******************************************
        private class JsonTest
        {
            public void Test() {
                // 簡単なエントリと、単純配列と、オブジェクト配列を含んだ JSON
                string url = "http://toolbox.winofsql.jp/json/sample1.json";

                // HTTP でのアクセス
                WebClient wc = new WebClient();
                // UTF-8 として取得
                wc.Encoding = Encoding.UTF8;
                // 文字列として取得
                json = wc.DownloadString(url);

                // コマンドプロンプト上に表示して一旦停止
                Console.WriteLine(json);
                Console.WriteLine(hl);
                Console.ReadLine();

                // ******************************************
                // 文字列から JObject を作成
                // ******************************************
                JObject jo = JObject.Parse(json);

                // JProperty で 一覧表示
                foreach (JProperty jp in jo.Properties())
                {
                    // 下位にデータがある場合は、Array または Object と表示されます
                    Console.WriteLine("タイプ : " + jp.Value.Type.ToString());
                    // 一番上位レベルに対する値を文字列で表示
                    Console.WriteLine(jp.Name + " --> " + jp.Value.ToString());
                }

                // コマンドプロンプト上で一旦停止
                Console.WriteLine(hl);
                Console.ReadLine();

                string[] key = {
                               "id","simple_array","object_array","object_data",
                               "profile_background_tile",
                                "notifications",
                                "profile_sidebar_fill_color",
                                "location",
                                "screen_name",
                                "profile_image_url"
                           };

                // JObject でキーを指定して直接参照
                foreach (string value in key)
                {
                    Console.WriteLine(jo[value].ToString());
                }

                // コマンドプロンプト上で一旦停止
                Console.WriteLine(hl);
                Console.ReadLine();

                // ******************************************
                // 下位階層単純配列の直接参照
                // ******************************************
                Console.WriteLine(jo["simple_array"][0].ToString());
                Console.WriteLine(jo["simple_array"][1].ToString());
                Console.WriteLine(jo["simple_array"][2].ToString());
                Console.WriteLine(jo["simple_array"][3].ToString());
                Console.WriteLine(jo["simple_array"][4].ToString());

                // ******************************************
                // 下位階層オブジェクト配列の直接参照
                // ******************************************
                Console.WriteLine(jo["object_array"][0]["high"].ToString());
                Console.WriteLine(jo["object_array"][0]["middle"].ToString());
                Console.WriteLine(jo["object_array"][0]["low"].ToString());
                Console.WriteLine(jo["object_array"][1]["high"].ToString());
                Console.WriteLine(jo["object_array"][1]["middle"].ToString());
                Console.WriteLine(jo["object_array"][1]["low"].ToString());
                Console.WriteLine(jo["object_array"][2]["high"].ToString());
                Console.WriteLine(jo["object_array"][2]["middle"].ToString());
                Console.WriteLine(jo["object_array"][2]["low"].ToString());

                // ******************************************
                // 下位階層オブジェクト直接参照
                // ******************************************
                Console.WriteLine(jo["object_data"]["sworc"].ToString());

            }
        }

        // ******************************************
        // 一括変換用のクラス
        // ******************************************
        private class MyJson
        {
            public int id { get; set; }
            public int[] simple_array { get; set; }
            public Object_Array[] object_array { get; set; }
            public JObject object_data { get; set; }
            public string profile_background_tile  { get; set; }
            public string notifications  { get; set; }
            public string profile_sidebar_fill_color  { get; set; }
            public string location  { get; set; }
            public string screen_name  { get; set; }
            public string profile_image_url { get; set; }
        }
        private class Object_Array
        {
            public int high { get; set; }
            public int middle { get; set; }
            public int low { get; set; }
        }

    }

}

Json.NET

ダウンロード
ドキュメント

ダウンロードしたファイルを解凍するとバイナリがフォルダ毎に別れています。プロジェクトの中にフォルダを作成して、その中へ既存のファイルとして呼び込んでから、そのパスで参照します。
-Net45:
  .NET latest (4.5)

-Net40:
  .NET 4.0

-Net35:
  .NET 3.5

-Net20:
  .NET 2.0

-WinRT:
  Windows 8 Store

-Portable45:
  .NET 4.5, Windows Phone 8, Windows 8 Store

-Portable40:
  .NET 4.0, Windows Phone 7, Windows 8 Store, Silverlight 4
関連する記事 JSONLint サービスを使って、JSON が正しいかどうかをチェックして整形する。
タグ:JSON
posted by lightbox at 2014-09-18 21:47 | VS(C#) | このブログの読者になる | 更新情報をチェックする
Seesaa の各ページの表示について
Seesaa の 記事がたまに全く表示されない場合があります。その場合は、設定> 詳細設定> ブログ設定 で 最新の情報に更新の『実行ボタン』で記事やアーカイブが最新にビルドされます。

Seesaa のページで、アーカイブとタグページは要注意です。タグページはコンテンツが全く無い状態になりますし、アーカイブページも歯抜けページはコンテンツが存在しないのにページが表示されてしまいます。

また、カテゴリページもそういう意味では完全ではありません。『カテゴリID-番号』というフォーマットで表示されるページですが、実際存在するより大きな番号でも表示されてしまいます。

※ インデックスページのみ、実際の記事数を超えたページを指定しても最後のページが表示されるようです

対処としては、このようなヘルプ的な情報を固定でページの最後に表示するようにするといいでしょう。具体的には、メインの記事コンテンツの下に『自由形式』を追加し、アーカイブとカテゴリページでのみ表示するように設定し、コンテンツを用意するといいと思います。


※ エキスパートモードで表示しています

アーカイブとカテゴリページはこのように簡単に設定できますが、タグページは HTML 設定を直接変更して、以下の『タグページでのみ表示される内容』の記述方法で設定する必要があります

<% if:page_name eq 'archive' -%>
アーカイブページでのみ表示される内容
<% /if %>

<% if:page_name eq 'category' -%>
カテゴリページでのみ表示される内容
<% /if %>

<% if:page_name eq 'tag' -%>
タグページでのみ表示される内容
<% /if %>
この記述は、以下の場所で使用します


Windows
container 終わり

フリーフォントで簡単ロゴ作成
フリーフォントでボタン素材作成
フリーフォントで吹き出し画像作成
フリーフォントではんこ画像作成
ほぼ自由に利用できるフリーフォント
フリーフォントの書体見本とサンプル
画像を大きく見る為のウインドウを開くボタンの作成

Android SDK ポケットリファレンス
改訂版 Webデザイナーのための jQuery入門
今すぐ使えるかんたん ホームページ HTML&CSS入門
CSS ドロップシャドウの参考デモ
Google Hosted Libraries
cdnjs
BUTTONS (CSS でボタン)
イラストAC
ぱくたそ
写真素材 足成
フリーフォント一覧
utf8 文字ツール
右サイド 終わり
base 終わり