SQLの窓

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年10月04日


Windows SDK の mt.exe を使用して、既存の exe を常に管理者権限で起動を求めるように変更する

テストしたのは、TeraPad.exe です。ショートカットアイコンを作成するとこんなアイコンになりました。



マニフェストファイルの作成

TeraPad.exe と同じディレクトリに、TeraPad.exe.manifest を作成して以下のような内容を書き込みます
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
<assembly xmlns="urn:schemas-microsoft-com:asm.v1"  
    manifestVersion="1.0"> 
    <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3"> 
    <security> 
        <requestedPrivileges> 
        <requestedExecutionLevel 
        level="requireAdministrator"/> 
        </requestedPrivileges> 
    </security> 
    </trustInfo> 
</assembly>

これに関しては、アプリケーション開発者向け Microsoftレジスタードマーク Windows 7 対応アプリケーションの互換性 で記述されています。

mt.exe で manifest を埋め込めるという事が上記リンクに書かれてあったので、試してみました。コマンドラインは以下のようになっています。
"C:\Program Files\Microsoft SDKs\Windows\v7.0A\bin\mt.exe" -manifest TeraPad.exe.manifest -outputresource:TeraPad.exe
このコマンドラインは、『マニフェストを C/C++ アプリケーションに埋め込む』に書かれています。

変更した exe と 元の exe を fc /b で比較すると、確かに違うものである事が確認されました。さらに、変更された exe を他の場所にコピーして実行しても、管理者である事を確認する『暗転+ダイアログ表示』が実行されることが確認できました。

インストール直後から管理者マーク

つまり、ビルド時にすでにそのような要件の元作成されているアプリケーションは、自動的に管理者の盾マークが表示されているので、それを削除する事は通常できません。



posted by lightbox at 2014-10-04 22:11 | 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#) | このブログの読者になる | 更新情報をチェックする

2014年07月25日


VS2010(C#) : HttpWebRequest クラスを使用して WEBアプリにバイナリデータを POST する

C# のコンソールアプリケーションで一般的に WEB アクセスする為に、HttpWebRequest クラスを使用します。

非同期ですと、いくぶん面倒ですが同期処理だと単純です。ここを参考に PowerShell でも利用できると思います。

▼ 以下関連する近い処理
VS2010(C#) : COMの Msxml2.ServerXMLHTTP を使用して WEBアプリにバイナリデータを POST する

C# ソースコード
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.IO;

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

			HttpWebRequest myReq =
			(HttpWebRequest)WebRequest.Create("http://yourdomain/put/put.php");

			// ****************************
			// ファイルを読み込む為のオブジェクト
			// ****************************
			FileStream fs = new FileStream(
				@"C:\user\web\web\various\put\winofsql.png",
				FileMode.Open, FileAccess.Read);

			// ****************************
			// ファイルを読み込むバイト型配列
			// ****************************
			byte[] bs = new byte[fs.Length];
			// ファイルの内容をすべて読み込む
			fs.Read(bs, 0, bs.Length);
			// 閉じる
			fs.Close();

			myReq.Method = "POST";
			//POST送信するデータの長さを指定
			myReq.ContentLength = bs.Length;

			// ****************************
			// データを書き込む
			// ****************************
			Stream reqStream = myReq.GetRequestStream();
			reqStream.Write(bs, 0, bs.Length);
			reqStream.Close();

			// ****************************
			// 結果を取得
			// ****************************
			WebResponse myRes = myReq.GetResponse();
			Stream resStream = myRes.GetResponseStream();
			StreamReader sr = new StreamReader(resStream, Encoding.UTF8);
			Console.WriteLine(sr.ReadToEnd());
			sr.Close();

			Console.ReadLine();

		}
	}
}

PHP 側については、『VBscript(または JScript) で簡単にバイナリファイルをアップロードする』 を参照して下さい。


関連する記事


タグ:C# framework HTTP
posted by lightbox at 2014-07-25 18:15 | VS(C#) | このブログの読者になる | 更新情報をチェックする

2014年07月24日


VS2010(C#) : COMの Msxml2.ServerXMLHTTP を使用して WEBアプリにバイナリデータを POST する

VB.net(2010) : COMの Msxml2.ServerXMLHTTP を使用して WEBアプリにバイナリデータを POST する
VBscript(または JScript) で簡単にバイナリファイルをアップロードする

いずれも同じ処理です。C# では、VB.net に比べていくぶん表現が厳密になっているのが解ります。文字列に使われている @ は、逐語的リテラル文字列と呼ばれており、使いやすさと読みやすさを考慮しています。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MSXML2;
using System.IO;

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

			// ****************************
			// http 通信用のオブジェクトを作成
			// ****************************
			ServerXMLHTTP60 ServerXML = new ServerXMLHTTP60();

			// ****************************
			// 呼び出す URL を設定
			// ****************************
			String URL  = "http://yourdomain/put/put.php";

			// ****************************
			// POST する為に開く
			// ****************************
			ServerXML.open("POST", URL, false);

			// ****************************
			// タイムアウトの設定
			// ****************************
			int lResolve = 60 * 1000;
			int lConnect = 60 * 1000;
			int lSend = 60 * 1000;
			int lReceive = 60 * 1000;
			ServerXML.setTimeouts(lResolve, lConnect, lSend, lReceive);

			// ****************************
			// ファイルを読み込む為のオブジェクト
			// ****************************
			FileStream fs = new FileStream( 
				@"C:\user\web\web\put\winofsql.png", 
				FileMode.Open, FileAccess.Read);

			// ****************************
			// ファイルを読み込むバイト型配列
			// ****************************
			byte[] bs = new byte[fs.Length];
			// ファイルの内容をすべて読み込む
			fs.Read(bs, 0, bs.Length);
			// 閉じる
			fs.Close();

			// ****************************
			// 送信するデータの長さをヘッダにセット
			// ****************************
			ServerXML.setRequestHeader("Content-Length", bs.Length.ToString());
			// 送信
			ServerXML.send(bs);

			// ****************************
			// 結果の表示
			// ****************************
			Console.WriteLine(ServerXML.responseText);

			Console.ReadLine();

		}
	}
}



関連する記事


タグ:C# com
posted by lightbox at 2014-07-24 21:39 | VS(C#) | このブログの読者になる | 更新情報をチェックする

2014年04月10日


VS2010(C#) : System.Data.Odbc データ取得(SELECT)処理( MySQL )

OneDrive へ移動


スタンダードな C# から ODBC を使用した読み取り処理のテンプレートです。元は VB.net だったものを、Convert VB.NET to C# で変換して作成しています。

※ MySQL ODBC 5.2w Driver は、古いので、MySQL ODBC 5.3 Unicode Driver を使用して下さい( 93行 )
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.Odbc;

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

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

			if (myCon == null) {
				Console.WriteLine("処理が異常終了しました");
				return;
			}

			//---------------------------------------------------

			// レコードセットを取得する為の SQL を準備
			string myQuery = "SELECT `社員マスタ`.*,DATE_FORMAT(`生年月日`,'%Y-%m-%d') as `誕生日`" + " from `社員マスタ`";

			// SELECT 実行用のオブジェクトを作成
			OdbcCommand myCommand = new OdbcCommand();
			// 実行する為に必要な情報をセット
			myCommand.CommandText = myQuery;
			myCommand.Connection = myCon;

			// 実行後にレコードセットを取得する為のオブジェクトを作成
			OdbcDataReader myReader;
			// ここで SELECT を実行してその結果をオブジェクトに格納する
			myReader = myCommand.ExecuteReader();

			// 読み出し
			// Rewad メソッドは、行が存在する場合は true、それ以外の場合は false を返します

			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();
			//---------------------------------------------------

			EndConnection(myCon);

		}

		// ******************************************************
		// 接続終了
		// ******************************************************

		static void EndConnection(OdbcConnection myCon) {
			// 接続を閉じる
			myCon.Close();

			// OdbcConnection オブジェクトに使用されているすべてのリソースを解放
			myCon.Dispose();

			// 処理終了
			Console.WriteLine("処理が終了しました");

			// 一時停止
			Console.Write("Enterキーを押して下さい : ");
			Console.ReadLine();

		}

		// ******************************************************
		// 接続作成
		// ******************************************************
		static OdbcConnection CreateConnection() {

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

			// ドライバ文字列をセット ( 波型括弧{} は必要ありません ) 
			// 文字列を正確に取得するには、レジストリ : HKEY_LOCAL_MACHINE\SOFTWARE\ODBC\ODBCINST.INI
			builder.Driver = "MySQL ODBC 5.2w Driver";

			// 接続用のパラメータを追加
			builder.Add("SERVER", "localhost");
			builder.Add("DATABASE", "lightbox");
			builder.Add("UID", "root");
			builder.Add("PWD", "パスワード");

			// 内容を確認
			Console.WriteLine(builder.ConnectionString);

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

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

			// 接続を開く
			try {
				myCon.Open();
			}
			catch (OdbcException ex) {
				Console.WriteLine("接続エラーです");
				// Console.WriteLine( ex.Message )
				ErrorAction(ex);
				return null;
			}

			return myCon;

		}

		// ******************************************************
		// エラー処理
		// ******************************************************

		static void ErrorAction(OdbcException ex) {
			string CrLf = "\r\n";
			string errorMessages = "";
			int i = 0;

			for (i = 0; i <= ex.Errors.Count - 1; i++) {
				errorMessages += "Index #" + i.ToString() + CrLf + "Message: " + ex.Errors[i].Message + CrLf + "NativeError: " + ex.Errors[i].NativeError.ToString() + CrLf + "Source: " + ex.Errors[i].Source + CrLf + "SQL: " + ex.Errors[i].SQLState + CrLf;
			}

			Console.WriteLine(errorMessages);

		}


		// ********************************************************
		// 列データ取得
		//
		// 列データを文字列として取得しますが、NULL の場合は
		// 空文字列を返します
		// ********************************************************
		static string GetValue(OdbcDataReader myReader, string strName) {

			string ret = "";
			int fld = 0;

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

			// 列の値を返す
			return ret;

		}

	}
}


以下は、show create table で取得した MySQL用の テーブル作成用 SQL です。
CREATE TABLE `社員マスタ` (
  `社員コード` varchar(4) NOT NULL DEFAULT '',
  `氏名` varchar(50) DEFAULT NULL,
  `フリガナ` varchar(50) DEFAULT NULL,
  `所属` varchar(4) DEFAULT NULL,
  `性別` int(11) DEFAULT NULL,
  `作成日` datetime DEFAULT NULL,
  `更新日` datetime DEFAULT NULL,
  `給与` int(11) DEFAULT NULL,
  `手当` int(11) DEFAULT NULL,
  `管理者` varchar(4) DEFAULT NULL,
  `生年月日` datetime DEFAULT NULL,
  PRIMARY KEY (`社員コード`)
)




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

2013年11月04日


VS2010 WPF(C#) DataGrid + データベース バインド / DataGrid に MDB のデータを読み込んで表示するテンプレート

SkyDrive へ移動




解説ページ

DataGrid へデータベースの内容を表示する問い合わせのサンプルですが、XAML を利用する上でデータはバインドでコントロールに表示されます。その為、データベースのデータを扱う為のプライベートクラス( SELECT 文の列リストを格納するクラス )を作成して利用します。

DataGrid は、ある手順を踏むと、そのクラスから自動的に列を作成してくれる上に、バインドの Mode=OneWay のルールで、コレクションの内容を変更するだけでコントロールの表示を変更する事ができます。


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

2013年11月01日


VS2012 WPF(C#) : 『TKMP.DLL を使用したイベントによる非同期メール受信処理を Task(await) を使用して順次処理のように記述する』テンプレート

SkyDrive へ移動


Framework 4.5 では、Task<TResult> クラスによって非同期処理の結果を取得してあたかも同期処理のような記述を行う事ができるようになりましたが、既存の非同期処理をそのように書き換える為に、TaskCompletionSource<TResult> クラスを使用します。

単純に考えると、Task を戻り値とするメソッド内は全て管理されていて、その中で登録されたイベントは全て管理下に置かれるようです。イベントが終了するまで、メソッドが終わる事無く、TaskCompletionSource<TResult> クラスの TrySetResult( SetResult との違いは良く解りません )で、値をセットした時にメソッドが終了するように見えます。

こうする事によって、大きなメリットの一つとして、UI スレッドにふつうに戻って来て処理を行えるところであり、当然ループ内の一部として自然に行を追加しながら非同期を実現する事ができました



MainWindow.xaml.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Net;
using System.Windows;
using System.Windows.Input;
using System.Collections.ObjectModel;
using TKMP.Net;
using System.IO;
using TKMP.Reader;
using System.Threading;
using System.Threading.Tasks;

namespace WPF_DataGrid_MailGet1 {
	public partial class MainWindow : Window {

		private MainViewModel mvm = new MainViewModel();
		private ImapClient client = null;

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

			this.dataGrid1.DataContext = mvm;
		}

		// 接続および、メールヘッダの取得
		private async void actButton_Click(object sender, RoutedEventArgs e) {

			mvm.mail_data.Clear();

			BasicImapLogon logon = new BasicImapLogon(this.userName.Text, this.password.Password);
			client = new ImapClient(logon, "imap.gmail.com", 993);
			client.AuthenticationProtocol = AuthenticationProtocols.SSL;

			if (!client.Connect()) {
				return;
			}

			// メールデータ一覧を格納するオブジェクト
			IMailData[] md = client.GetMailList();

			// データがありません
			if (md == null) {
				return;
			}

			// メールデータの数
			mailCount.Text = md.Length.ToString();

			// 読込み制限
			int maxCount = 20;
			int idx = 0;

			// 非同期で全て表示
			foreach (var data in md) {

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

				// Framework 4.5 : 値を返す非同期処理
				MailReader reader = await ReadBodyAnsync( data );

				// UI スレッドに戻って来ているので、特殊な処理は必要無い
				string from = "";
				string subject = "";
				string mdate = "";
				// ヘッダの一覧より、目的のヘッダを探す
				foreach (TKMP.Reader.Header.HeaderString headerdata in reader.HeaderCollection) {

					if (headerdata.Name == "From") {
						from = headerdata.Data;
					}
					if (headerdata.Name == "Subject") {
						subject = headerdata.Data;
					}
					if (headerdata.Name == "Date") {
						mdate = headerdata.Data;
					}

				}

				// 行追加
				mvm.mail_data.Add(new ItemViewModel() {
					from = from,
					subject = subject,
					mdate = mdate
				});

			}
			// ソース的には、順次処理なので全てのデータ処理後のクローズ
			client.Close();

		}

		// *********************************************
		// 戻り値を返す事のできる非同期処理 【開始】
		// *********************************************
		private TaskCompletionSource<MailReader> tcs = null;
		private Task<MailReader> ReadBodyAnsync(IMailData MailData) {

			// 戻り値用のクラス
			tcs = new TaskCompletionSource<MailReader>();

			// 個別にイベント登録
			MailData.BodyLoaded += new EventHandler(MailData_event);
			// 非同期処理開始
			MailData.ReadBodyAnsync();

			return tcs.Task;
		}

		// 本来のイベント処理
		private void MailData_event(object sender, EventArgs e) {

			IMailData MailData = (IMailData)sender;

			// イベント削除
			MailData.BodyLoaded -= new EventHandler(MailData_event);

			// 本文無し( 本文が必要な場合は、false で、reader.MainText )
			MailReader reader = new MailReader(MailData.DataStream, true);

			// ****************************
			// 戻り値用のクラスの戻り値をセット
			// ****************************
			tcs.TrySetResult(reader);

		}
		// *********************************************
		// 戻り値を返す事のできる非同期処理 【終了】
		// *********************************************


		// ダブルクリック
		private void dataGrid1_MouseDoubleClick(object sender, MouseButtonEventArgs e) {
			Debug.WriteLine(dataGrid1.SelectedIndex);

		}


	}
}

参考ページ

c# - Best way to convert callback-based async method to awaitable task - Stack Overflow
c# - TaskCompletionSource : When to use SetResult() versus TrySetResult(), etc - Stack Overflow

関連するページ

▼ このページの処理の元となった、通常のイベント非同期処理
WPF(C#) : 『DataGrid に、TKMP.DLL を使用して非同期にメールヘッダを受信する』 テンプレート



posted by lightbox at 2013-11-01 20:29 | 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 終わり