将棋評価値バーを作る（最終回）

前回からの続きです。

https://qiita.com/TETSURO1999/items/e708393013b9da575235

# 開発目標の確認

ここで第１回で掲げた開発目標を確認してみます。
<table>
<tr><th>目標</th><th>結果</th></tr>
<tr><td>AVX2 未対応の古い CPU でも動く</td>
    <td>特に何もしていないが出来た</td></tr>
<tr><td>Windows内蔵の C# コンパイラだけでビルドできる
    <td>ちょっと頑張れば出来た</td></tr>
<tr><td>使用する将棋エンジンをコンパイル無しで切替可能</td>
    <td>初期設定ファイルで対応<br>※第５回で説明</td></tr>
<tr></tr>
<tr><td>対局するプレイヤー名を表示できるようにする</td>
    <td>ShogiGUI のタイトルバーから読み出す<br>※第４回で説明</td></tr>
<tr></tr>
<tr><td>評価値バーを常に最前面で表示できるようにする</td>
    <td>超簡単にできた<br>※詳しくはソースコード参照</td></tr>
</table>

最後にWindows内蔵のC#コンパイラだけでビルドできるようにするためのちょっとした苦労を紹介します。

# Windows 内蔵の C# コンパイラだけでビルド
Windows 内蔵の C# コンパイラでビルドするためのバッチファイルを以下に示します。C# コンパイラのインストールパスはPCによってあまり変わらないと思いますが，一応，レジストリを検索して正確なインストールパスを得るようにしています。

※シンタクスハイライトがおかしいので VScode のを貼りました。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3490655/8bf5f592-7da2-403e-1295-68eff77ec613.png" alt="build.bat">

<details><summary>build.bat のテキストを参照したい人はコチラ</summary>

```
@echo off
setlocal
rem ----------------------------------------------------------------------------
rem csc.exe にパスが通っているかどうかの確認
rem ----------------------------------------------------------------------------
set DOTNETPATH=
for %%I in ( csc.exe ) do set DOTNETPATH=%%~$PATH:I
if defined DOTNETPATH goto LETS_COMPILE

rem ----------------------------------------------------------------------------
rem .NET Framework のインストールパスを探す
rem ----------------------------------------------------------------------------
for /F "usebackq tokens=1,2,*" %%I in ( `reg query "HKLM\SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full" /v InstallPath` ) do (
  if "%%I"=="InstallPath" set "DOTNETPATH=%%K"
)
if defined DOTNETPATH goto APPEND_PATH

echo ^[[91m.NET Framework のインストールパスが見つかりません！
pause
exit /b

:APPEND_PATH
echo パスに %DOTNETPATH% を追加します。
set "PATH=%PATH%;%DOTNETPATH%"

:LETS_COMPILE
rem ----------------------------------------------------------------------------
rem コンパイル
rem ----------------------------------------------------------------------------
echo evalbar.cs をコンパイルします。
if exist evalbar.exe del evalbar.exe
csc -o -w:4 -win32icon:shogi.ico evalbar.cs

if exist evalbar.exe goto SUCCESS
echo ^[[91mevalbar のコンパイルに失敗しました！
pause
exit /b

:SUCCESS
echo evalbar のコンパイルに成功しました。
pause
exit /b
```
</details>

# 便利な拡張メソッド
string.Contains() は，指定した文字が指定した文字列の中に存在するか確認するという便利なメソッドですが，Windows 内蔵の C# コンパイラ（.NET Framework）は対応していません。しかし，C# の持つ拡張メソッドという機能のおかげで以下のコードを追加するだけでよく，string.Contains() を使用しているコードを書き換えずに済みました。いやあ C# って本当に便利な言語ですね。

```C#
//------------------------------------------------------------------------------
// ユーザ拡張クラス
//------------------------------------------------------------------------------
static	class	UserExtension {
	//--------------------------------------------------------------------------
	// 指定した“文字”が指定した文字列内に存在するか確認する
	//--------------------------------------------------------------------------
	public	static	bool	Contains( this string s, char c ) {
		for( int i = 0; i < s.Length; i++ )
			if( s[i] == c ) return( true );
		return( false );
	}
}
```
# おまけ
アイコンでちょっと苦労したという話です。今回，将棋の駒型のアイコン shogi.ico を自作しています。これをアプリケーションプログラムにリンクするために下記のようなオプションをつけてビルドしました。こうするとビルドされたアプリケーションプログラム evalbar.exe は，エクスプローラーから将棋の駒型アイコンとして表示されます。
```
csc -o -w:4 -win32icon:shogi.ico evalbar.cs
```
しかし，今度は評価値バーのプログラム内で shogi.ico を利用しようと思っても，このアイコンを認識することができません。どうやら .NET Framework の機能では実現できないようです。このため SHGetFileInfo() というWin32 API を用いることになりました。

以下は，メインウィンドウのコンストラクタでタイトルバーアイコンを設定するところです。アプリケーションプログラム自身 Application.ExecutablePath をデータとして読み込み，アイコンのハンドルを取得しています。
```C#
//----------------------------------------------------------------------
// タイトルバーアイコン
//----------------------------------------------------------------------
IntPtr	icon = WindowsAPI.GetApplicationIcon( Application.ExecutablePath );
if( icon != IntPtr.Zero ) this.Icon = Icon.FromHandle( icon );
```

Win32 API のラッパー部分です。
```C#
//------------------------------------------------------------------------------
// Windows API ラッパー
//------------------------------------------------------------------------------
class WindowsAPI {
	//--------------------------------------------------------------------------
	// SHGetFileInfo 関数で使用する定数
	//--------------------------------------------------------------------------
	private	const	uint	SHGFI_ICON          = 0x0100;
	private	const	uint	SHGFI_SYSICONINDEX  = 0x4000;
	private	const	uint	SHGFI_LARGEICON     = 0x0000;
	private	const	uint	SHGFI_SMALLICON     = 0x0001;
	private	const	uint	SHGFI_OPENICON      = 0x0002;
	private	const	uint	SHGFI_SHELLICONSIZE = 0x0004;

	//--------------------------------------------------------------------------
	// SHGetFileInfo 関数で使用する構造体
	//--------------------------------------------------------------------------
	private struct SHFILEINFO {
		public	IntPtr	hIcon;
		public	IntPtr	iIcon;
		public	uint	dwAttributes;
		[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
		public	string	szDisplayName;
		[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 80)]
		public	string	szTypeName;
	};

	//--------------------------------------------------------------------------
	// SHGetFileInfo 関数
	//--------------------------------------------------------------------------
	[DllImport("shell32.dll")]
	private	static	extern	IntPtr	SHGetFileInfo(
		string pszPath, uint dwFileAttributes, ref SHFILEINFO psfi, uint cbSizeFileInfo, uint uFlags );

	//--------------------------------------------------------------------------
	// アプリケーションアイコンを得る
	//--------------------------------------------------------------------------
	public	static	IntPtr	GetApplicationIcon( string filename ) {
		SHFILEINFO	shinfo = new SHFILEINFO();
		IntPtr	hSuccess = SHGetFileInfo( Application.ExecutablePath, 0, ref shinfo, (uint)Marshal.SizeOf(shinfo), SHGFI_ICON );
		return hSuccess == IntPtr.Zero ? IntPtr.Zero : shinfo.hIcon;
	}
}
```

以下のサイトの情報が大変参考になりました。
[.NET TIPS 実行ファイルからアプリケーションのアイコンを取得するには？（atmarkIT）](https://atmarkit.itmedia.co.jp/fdotnet/dotnettips/280getappicon/getappicon.html)

以上で，将棋評価値バーを作るというシリーズ連載を終わります。

将棋評価値バーを使ってみたい方はコチラをご覧ください。

https://qiita.com/TETSURO1999/items/baf82b5af7e8c97c8903