//--------------------------------
// CICON Class
// Copyright (c) 2021, K. Yoshida
//--------------------------------
///////////
//定数定義
///////////
#define	MAX_ICON	32	//アイコン内の構成ビットマップ数の上限
#define	DISPSIZE	128	//LoadImageの読み込みサイズ

/////////////
//追加構造体
/////////////
//ICONDIR構造体宣言　−　6バイト長
typedef struct tagICONDIR {
	WORD	idReserved;			//予約済み（常に0）
	WORD	idType;				//リソースタイプ:アイコン：1、カーソル：2
	WORD	idCount;			//アイコンの数
}ICONDIR, *LPICONDIR;

//ICONDIRENTRY構造体宣言　−　16バイト長
typedef struct tagICONDIRENTRY {
	BYTE	bWidth;				//画像幅（単位：ピクセル）
	BYTE	bHeight;			//画像高さ（単位：ピクセル）
	BYTE	bColorCount;		//画像の色数（256色以上は0）
	BYTE	bReserved;			//予約済み（常に0）
	WORD	wPlanes;			//カラープレーン数（カーソル時、Xホットスポット）
	WORD	wBitCount;	  		//ピクセルのビット深度（カーソル時、Yホットスポット）
	DWORD   dwBytesInRes;   	//ピクセルデータのバイト数
	DWORD   dwImageOffset;  	//ファイル先頭からピクセルデータまでのオフセット
}ICONDIRENTRY, *LPICONDIRENTRY;

class CICON {
public:
	//////メンバー変数//////
	//アイコンを読み込むウィンドウハンドル
	HWND m_hWnd;
	//そのウィンドウのデバイスコンテキストハンドル
	HDC m_hDC;
	//アイコン、カ―ソルのハンドル
	HICON m_hIcon;
	//ICONDIR構造体
	ICONDIR m_Icondir;
	//ICONDIRENTRY構造体
	ICONDIRENTRY m_Iconentry[MAX_ICON];
	//構成ビットマップカウンター
	int m_BmpCounter;
	//構成ビットマップのDIB情報取得用
	LPBYTE  m_ImageDat[MAX_ICON];	//構成ビットマップデータ
	LPBITMAPINFO m_lpBmi[MAX_ICON];	//BITMAPINFO構造体へのポインター
	LPBYTE m_XOR[MAX_ICON];			//カラービットマップポインター
	LPBYTE m_AND[MAX_ICON];			//マスクビットマップポインター
	//構成ビットマップのハンドル
	HBITMAP m_hBmp[MAX_ICON];		//カラービットマップ
	HBITMAP m_hMaskBmp[MAX_ICON];	//マスクビットマップ
	//////メンバー関数//////
	//コンストラクター（１）
	CICON();
	//コンストラクター（２）
	CICON(HWND);
	//デストラクター
	~CICON();
	//CICON初期化
	void Init();
	//すべてのビットマップの廃棄
	void Clear();
	//ウィンドウを指定する
	void SetWindow(HWND);
	//構成ビットマップ数を取得する
	int GetCount() {return m_BmpCounter;}
	//ファイルからアイコンまたはカーソルを取り込む（Icon-1、Cursor-2）
	bool Load_Icon(LPCTSTR, UINT, bool);
	//ファイルからビットマップを追加する
	bool Add_Bitmap(LPCTSTR);
	//登録ビットマップの削除
	bool Del_Bitmap(int);
	//特定のビットマップのICONDIRENTRYへのポインターを返す
	bool GetIDEntry(int, LPICONDIRENTRY*);
	//特定のビットマップのBITMAPINFOHEADERへのポインターを返す
	bool GetBmpInfo(int, PBITMAPINFOHEADER*);
	//アイコンのハンドルを返す
	HICON GetIcon();
	//カラー（XOR）ビットマップのハンドルを返す
	HBITMAP GetColBmp(int);
	//マスク（AND）ビットマップのハンドルを返す
	HBITMAP GetMaskBmp(int);
	//ファイルへアイコンまたはカーソルを書き込む（Icon-1、Cursor-2）
	bool Save_Icon(LPTSTR, UINT);
	//HotSpotXを取得する
	int GetHsX(int n) {return m_Iconentry[n].wPlanes;}
	//HotSpotYを取得する
	int GetHsY(int n) {return m_Iconentry[n].wBitCount;}
	//HotSpotXを設定する
	int SetHsX(int n, int x) {m_Iconentry[n].wPlanes = x;}
	//HotSpotYを設定する
	int SetHsY(int n, int y) {m_Iconentry[n].wBitCount = y;}
};

//コンストラクター（１）
CICON::CICON() {

	m_hIcon = 0;
}

//コンストラクター（２）
CICON::CICON(HWND hWnd) {

	m_hIcon = 0;
	SetWindow(hWnd);
}

//デストラクター
CICON::~CICON() {

	//アイコンの破棄
	Init();
	//すべてのビットマップと関連情報の破棄
	Clear();
	if(m_hDC)
		ReleaseDC(m_hWnd, m_hDC);
}

//CICON初期化
void CICON::Init() {

	if(m_hIcon) {
		DestroyIcon(m_hIcon);
		m_hIcon = 0;
	}
}

//すべてのビットマップの廃棄
void CICON::Clear() {

	//すべてのビットマップと関連情報の破棄
	for(int i = m_BmpCounter; i > 0; i--) {
		LocalFree(m_ImageDat[i - 1]);
		DeleteObject(m_hBmp[i - 1]);
		DeleteObject(m_hMaskBmp[i - 1]);
	}
	m_BmpCounter = 0;
}

//ウィンドウを指定する
void CICON::SetWindow(HWND hWnd) {

	m_hWnd = hWnd;
	if(m_hDC)
		ReleaseDC(m_hWnd, m_hDC);
	m_hDC = GetDC(hWnd);
}

///////////////////////////////////////////////////////////////
//アイコンまたはカーソルを読み込む
//FileName : ファイルパス・名前またはリソースID
//iType	: Icon = 1(IMAGE_ICON:規定値)、Cursor = 2(IMAGE_CURSOR)
//flag	: ファイルから = TRUE（規定値）、リソースから = FALSE
///////////////////////////////////////////////////////////////
bool CICON::Load_Icon(LPCTSTR FileName, UINT iType = IMAGE_ICON,
						bool flag = TRUE) {

	//イメージタイプチェック（IMAGE_ICON, IMAGE_CURSOR以外はエラー）
	if(iType != 1 && iType != 2) {
		MessageBox(m_hWnd, "IMAGE_ICON(1)、IMAGE_CURSOR(2)ではありません",
					"エラー", MB_OK | MB_ICONSTOP);
    		return FALSE;
	}
	//変更時の初期化処理
	if(m_hIcon) {
		if(MessageBox(m_hWnd, "既にアイコンデータが読み込まれています。\r\n"\
							"現在のアイコンデータを破棄しますか？",
							"確認", MB_YESNO | MB_ICONQUESTION) == IDYES)
			Init();
		else
			return FALSE;
		if(MessageBox(m_hWnd, "アイコンのビットマップデータも破棄しますか？",
							"確認", MB_YESNO | MB_ICONQUESTION) == IDYES)
			Clear();
	}
	/////////////////////////////
	//アイコン、カーソルのロード
	/////////////////////////////
	UINT fLoad;	//ロードオプション（デフォルトはファイルから入力）
	if(flag)
		fLoad = LR_DEFAULTCOLOR | LR_LOADFROMFILE;
	else
		fLoad = LR_DEFAULTCOLOR;
	m_hIcon = (HICON)LoadImage((HINSTANCE)GetWindowLong(m_hWnd, GWL_HINSTANCE),
				FileName, iType, DISPSIZE, DISPSIZE, fLoad);
	if(!m_hIcon) {	//アイコンまたはカーソルの読み込みに失敗した場合エラー
		MessageBox(m_hWnd, "アイコンまたはカーソルの読み込みに失敗しました",
					"エラー", MB_OK | MB_ICONSTOP);
		return FALSE;
	}
	/////////////////////////////
	//アイコンファイルを読み込む
	/////////////////////////////
	//アイコン、カーソルデータを読み込む
	HANDLE hFile = CreateFile(FileName, GENERIC_READ, 0, NULL, OPEN_EXISTING,
					FILE_ATTRIBUTE_NORMAL, NULL);
	if(hFile == INVALID_HANDLE_VALUE) {
		MessageBox(m_hWnd, "ファイルを開けられませんでした",
					"エラー", MB_OK | MB_ICONSTOP);
		return FALSE;
	}
	DWORD dwRead;
	if(!ReadFile(hFile, &m_Icondir, sizeof(ICONDIR), &dwRead, NULL)) {
		MessageBox(m_hWnd, "m_Icondirを読み込めませんでした",
					"エラー", MB_OK | MB_ICONSTOP);
		CloseHandle(hFile);
		return FALSE;
	}
	//画像数が超過する場合のエラー
	if((m_BmpCounter + m_Icondir.idCount) > MAX_ICON) {
		MessageBox(m_hWnd, "画像数が読込限度を超えています", "エラー",
					MB_OK | MB_ICONSTOP);
		return FALSE;
	}
	//idCount個のICONDIRENTRYを読み込む
	for(int i = 0; i < m_Icondir.idCount; i++) {
		if(!ReadFile(hFile, &m_Iconentry[m_BmpCounter + i], sizeof(ICONDIRENTRY),
					&dwRead, NULL)) {
			MessageBox(m_hWnd, "m_Iconentry配列を読み込めませんでした",
					"エラー", MB_OK | MB_ICONSTOP);
			CloseHandle(hFile);
			return FALSE;
		}
	}
	//idCount個のイメージ情報を読み、ポインターを設定する
	for(int i = 0; i < m_Icondir.idCount; i++) {
		int rgbq;		//RGBQUADのビット数
		WORD BmpSize;	//カラービットマップのビットデータサイズ
		//m_ImageDatのメモリーを確保する
		m_ImageDat[m_BmpCounter + i] = (LPBYTE)LocalAlloc(LPTR,
									m_Iconentry[m_BmpCounter + i].dwBytesInRes);
		if(!m_ImageDat[m_BmpCounter + i]) {
			MessageBox(m_hWnd, "m_ImageDatのメモリーを確保出来ませんでした",
					"エラー", MB_OK | MB_ICONSTOP);
			CloseHandle(hFile);
			return FALSE;
		}
		//イメージデータファイル読込みの為のファイルポインター移動
		SetFilePointer(hFile, m_Iconentry[m_BmpCounter + i].dwImageOffset,
						NULL, FILE_BEGIN);
		//イメージデータファイルを読み込む
		if(!ReadFile(hFile, m_ImageDat[m_BmpCounter + i],
			m_Iconentry[m_BmpCounter + i].dwBytesInRes, &dwRead, NULL)) {
			MessageBox(m_hWnd, "m_ImageDatを読み込めませんでした",
					"エラー", MB_OK | MB_ICONSTOP);
			CloseHandle(hFile);
			return FALSE;
		}
		//イメージデータファイルによる各種ポインター設定
		m_lpBmi[m_BmpCounter + i] = (LPBITMAPINFO)m_ImageDat[m_BmpCounter + i];
		//biBitCountに基づくRGBQUAD長の計算
		switch(m_lpBmi[m_BmpCounter + i]->bmiHeader.biBitCount) {
		case 1:		//256 - 1 << 1 (= 2)
			rgbq = 8;	//sizeof(RGBQUAD) * (1 << biBitCount)
			break;
		case 4:		//256 - 1 << 4 (= 16)
			rgbq = 64;	//sizeof(RGBQUAD) * (1 << biBitCount)
			break;
		case 8:		//256 - 1 << 8 (= 256)
			rgbq = 1024;
			break;
		default:	//16, 24, 32bit色のビットマップはRGBQUADテーブルを持たない
			 rgbq = 0;
			 break;
		}
		//カラービットマップのビットデータへのポインターの設定
		m_XOR[m_BmpCounter + i] = (LPBYTE)m_lpBmi[m_BmpCounter + i] +
									sizeof(BITMAPINFOHEADER) + rgbq;
		//カラービットマップ（XOR）データサイズを算出
		BmpSize = ((m_lpBmi[m_BmpCounter + i]->bmiHeader.biBitCount *
					m_lpBmi[m_BmpCounter + i]->bmiHeader.biWidth + 31) / 32) *
					4 * abs(m_lpBmi[m_BmpCounter + i]->bmiHeader.biHeight / 2);
		//マスクビットマップのビットデータへのポインターの設定
		m_AND[m_BmpCounter + i] = (LPBYTE)m_lpBmi[m_BmpCounter + i] +
									sizeof(BITMAPINFOHEADER) + rgbq + BmpSize;
		/////////////////////////////////////
		//取得したデータでビットマップを作成
		/////////////////////////////////////
		LPBYTE Bmi = (LPBYTE)LocalAlloc(LPTR, sizeof(BITMAPINFOHEADER) + rgbq);
		memcpy(Bmi, (LPBYTE)m_lpBmi[m_BmpCounter + i],
				sizeof(BITMAPINFOHEADER) + rgbq);
		//Bmiの高さ修正
		((LPBITMAPINFOHEADER)Bmi)->biHeight /= 2;	//高さが2倍になっているため
		//カラービットマップを作成
		m_hBmp[m_BmpCounter + i] = CreateCompatibleBitmap(m_hDC,
										((LPBITMAPINFOHEADER)Bmi)->biWidth,
										((LPBITMAPINFOHEADER)Bmi)->biHeight);
		//カラービットマップのBitデータを与える
		if(SetDIBits(m_hDC, m_hBmp[m_BmpCounter + i], 0,
					((LPBITMAPINFOHEADER)Bmi)->biHeight, m_XOR[m_BmpCounter + i],
					(LPBITMAPINFO)Bmi, DIB_RGB_COLORS)
					== ERROR_INVALID_PARAMETER) {
			MessageBox(m_hWnd, "カラービットマップの作成に失敗しました",
						"エラー", MB_OK | MB_ICONERROR);
			DeleteObject(m_hBmp[m_BmpCounter + i]);
		}
		//マスクビットマップを作成
		m_hMaskBmp[m_BmpCounter + i] = CreateCompatibleBitmap(m_hDC,
										((LPBITMAPINFOHEADER)Bmi)->biWidth,
										((LPBITMAPINFOHEADER)Bmi)->biHeight);
		//モノクロにする
		((LPBITMAPINFOHEADER)Bmi)->biBitCount = 1;
		RGBQUAD mono[2] =	{{0, 0, 0, 0},
							 {0xff, 0xff, 0xff, 0}
							};
		memcpy(Bmi + sizeof(BITMAPINFOHEADER), mono, sizeof(RGBQUAD) * 2);
		//マスクビットマップのBitデータを与える
		if(SetDIBits(m_hDC, m_hMaskBmp[m_BmpCounter + i], 0,
					((LPBITMAPINFOHEADER)Bmi)->biHeight,
					m_AND[m_BmpCounter + i],(LPBITMAPINFO)Bmi, DIB_RGB_COLORS)
					== ERROR_INVALID_PARAMETER) {
			MessageBox(m_hWnd, "マスクビットマップの作成に失敗しました",
						"エラー", MB_OK | MB_ICONERROR);
			DeleteObject(m_hMaskBmp[m_BmpCounter + i]);
		}
		//Bmiの開放
		LocalFree(Bmi);
	}
	//Iconファイルをクローズする
	if(!CloseHandle(hFile))
		MessageBox(m_hWnd, "ファイルをクローズできませんでした",
					"エラー", MB_OK | MB_ICONSTOP);
	//ビットマップカウンターを読み込んだ数だけ進める
	m_BmpCounter += m_Icondir.idCount;

	return TRUE;
}

///////////////////////////////////////////////////////////////
//ファイルからビットマップを追加する
//FileName : ファイルパス・名前またはリソースID
//flag	: ファイルから = TRUE（規定値）、リソースから = FALSE
///////////////////////////////////////////////////////////////
bool CICON::Add_Bitmap(LPCTSTR FileName) {

	//ローカル変数
	LPBITMAPINFOHEADER PBmi;//ビットマップインフォヘッダー
	int rgbq;				//カラーテーブル（RGBQUAD）サイズ
	int BmpSize;			//XORビットマップサイズ
	int MaskSize;			//ANDビットマップサイズ
	int BkCol;				//背景色パレット番号（Cbit == 1, 4, 8の場合）
	char BkC[4];			//背景色パレット番号（Cbit == 24の場合）
	//ファイルオープン
	DWORD dwResult;
	HANDLE hFile = CreateFile(FileName, GENERIC_READ, 0, NULL, OPEN_EXISTING,
					FILE_ATTRIBUTE_NORMAL, NULL);
	if(hFile == INVALID_HANDLE_VALUE) {
		MessageBox(m_hWnd, "ファイルを開けませんでした",
					"エラー", MB_OK | MB_ICONSTOP);
		return FALSE;
	}
	//BITMAPFILEHEADERをスキップする
	SetFilePointer(hFile, sizeof(BITMAPFILEHEADER), NULL, FILE_BEGIN);
	//一旦BITMAPINFOHEADERを読み込む
	PBmi = (LPBITMAPINFOHEADER)LocalAlloc(LPTR, sizeof(BITMAPINFOHEADER));
	if(!PBmi) {
		MessageBox(m_hWnd, "PBmi用のメモリーが確保できませんでした",
				"エラー", MB_OK | MB_ICONSTOP);
		CloseHandle(hFile);
		return FALSE;
 	}
	ReadFile(hFile, PBmi, sizeof(BITMAPINFOHEADER), &dwResult, NULL);
	//カラーパレットサイズを確認する
	switch(PBmi->biBitCount) {
	case 1:		//256 - 1 << 1 (= 2)
		rgbq = 8;	//sizeof(RGBQUAD) * (1 << biBitCount)
		break;
	case 4:		//256 - 1 << 4 (= 16)
		rgbq = 64;	//sizeof(RGBQUAD) * (1 << biBitCount)
		break;
	case 8:		//256 - 1 << 8 (= 256)
		rgbq = 1024;
		break;
	case 16:	//16bit色のビットマップはRGBQUADテーブルを持たない
	case 24:	//24bit色のビットマップはRGBQUADテーブルを持たない
	case 32:	//32bit色のビットマップはRGBQUADテーブルを持たない
		 rgbq = 0;
		 break;
	}
	LocalFree(PBmi);
	//カラービットマップのデータサイズを算出
	BmpSize = ((PBmi->biBitCount * PBmi->biWidth + 31) / 32) * 4 * abs(PBmi->biHeight);
	//マスクビットマップのデータサイズを算出
	MaskSize = ((PBmi->biWidth + 31) / 32) * 4 * abs(PBmi->biHeight);
	//m_ImageDatのメモリーを確保する
	m_ImageDat[m_BmpCounter] = (LPBYTE)LocalAlloc(LPTR,
						sizeof(BITMAPINFOHEADER) + rgbq + BmpSize + MaskSize);
	//ファイルからBITMAPINFOHEADER、カラーパレットとXORビットマップを読み込む
	SetFilePointer(hFile, sizeof(BITMAPFILEHEADER), NULL, FILE_BEGIN);
	ReadFile(hFile, m_ImageDat[m_BmpCounter], sizeof(BITMAPINFOHEADER) + rgbq +
				BmpSize, &dwResult, NULL);
	m_lpBmi[m_BmpCounter] = (LPBITMAPINFO)m_ImageDat[m_BmpCounter];
	PBmi = (LPBITMAPINFOHEADER)m_lpBmi[m_BmpCounter];
	//ローカルメモリーの確保とビットパターンデータの読み込み
	m_XOR[m_BmpCounter] = (LPBYTE)PBmi + sizeof(BITMAPINFOHEADER) + rgbq;
	//ローカルメモリーの確保とビットパターンデータの読み込み
	m_AND[m_BmpCounter] = (LPBYTE)PBmi + sizeof(BITMAPINFOHEADER) + rgbq + BmpSize;
	//ColBmp最右下端ピクセルの色を背景色に設定し、その1バイトを取り出す
	if(PBmi->biHeight > 0) {	//ボトムアップ
		switch(PBmi->biBitCount) {
		case 1:		//モノクロの場合は「幅 / 8」バイトの第1ビットが値
			BkCol = m_XOR[m_BmpCounter][PBmi->biWidth / 8 - 1] & 1;	//0か1となる
			break;
		case 4:		//16色の場合「幅 / 2」バイトのは下位4ビットが値
			BkCol = m_XOR[m_BmpCounter][PBmi->biWidth / 2 - 1] & 0xF;
			break;
		case 8:		//256色の場合は8ビットが値
			BkCol = m_XOR[m_BmpCounter][PBmi->biWidth - 1];
			break;
		case 16:	//16bitの場合は2byte(RGB555 or 565の順)が値
			BkC[0] = m_XOR[m_BmpCounter][PBmi->biWidth * 2 - 2];	//RGB555または
			BkC[1] = m_XOR[m_BmpCounter][PBmi->biWidth * 2 - 1];	//RGB565を想定
			break;
		case 24:	//24bitの場合は3byte(BGRの順)が値
			BkC[0] = m_XOR[m_BmpCounter][PBmi->biWidth * 3 - 3];	//B
			BkC[1] = m_XOR[m_BmpCounter][PBmi->biWidth * 3 - 2];	//G
			BkC[2] = m_XOR[m_BmpCounter][PBmi->biWidth * 3 - 1];	//R
			break;
		case 32:	//32bitの場合は4byte(BRGRsvdの順)が値
			BkC[0] = m_XOR[m_BmpCounter][PBmi->biWidth * 4 - 4];	//B
			BkC[1] = m_XOR[m_BmpCounter][PBmi->biWidth * 4 - 3];	//G
			BkC[2] = m_XOR[m_BmpCounter][PBmi->biWidth * 4 - 2];	//R
			BkC[3] = m_XOR[m_BmpCounter][PBmi->biWidth * 4 - 1];	//Rsvd
			break;
		}
    }
	else {						//ボトムダウン
		switch(PBmi->biBitCount) {
		case 1:		//モノクロの場合は最終バイトの第1ビットが値
			BkCol = m_XOR[m_BmpCounter][BmpSize - 1] & 1;	//0か1となる
			break;
		case 4:		//16色の場合は最終バイトの下位4ビットが値
			BkCol = m_XOR[m_BmpCounter][BmpSize - 1] & 0xf;
			break;
		case 8:		//256色の場合最終バイトが値
			BkCol = m_XOR[m_BmpCounter][BmpSize - 1];
			break;
		case 16:	//16bitの場合はは2byte(RGB555 or 565の順)が値
			BkC[0] = m_XOR[m_BmpCounter][BmpSize - 2];		//RGB555または
			BkC[1] = m_XOR[m_BmpCounter][BmpSize - 1];		//RGB565を想定
			break;
		case 24:	//24bitの場合は3byte(BRGの順)が値
			BkC[0] = m_XOR[m_BmpCounter][BmpSize - 3];		//B
			BkC[1] = m_XOR[m_BmpCounter][BmpSize - 2];		//G
			BkC[2] = m_XOR[m_BmpCounter][BmpSize - 1];		//R
			break;
		case 32:	//32bitの場合は4byte(BRGRsvdの順)が値
			BkC[0] = m_XOR[m_BmpCounter][BmpSize - 4];		//B
			BkC[1] = m_XOR[m_BmpCounter][BmpSize - 3];		//G
			BkC[2] = m_XOR[m_BmpCounter][BmpSize - 2];		//R
			BkC[3] = m_XOR[m_BmpCounter][BmpSize - 1];	//Rsvd
			break;
		}
	}
	//マスクビットパターンの作成
	char Bit, tmp;	//各バイトの代入値算出用変数（tmpで1−透過をORしてゆく）
	int Dat;		//4bitビットマップ用色データ用変数
	for(int i = 0; i < MaskSize; i++) {
		Bit = 0;					//毎バイトで0に初期化
		for(int j = 7; j >= 0; j--) {	//左から右へ見て行く
			switch(PBmi->biBitCount) {
			case 1:
				tmp = 1 << j;
				if(m_XOR[m_BmpCounter][i] & tmp) {	//?0000000→へ'1'か否かのチェック
					if(BkCol)			//背景色が'1'の場合
						Bit |= tmp;		//ビットを'1'にして透過
				}
				else {					//前景色が'0'の場合でも
					if(!BkCol)			//背景色が'0'であれば
						Bit |= tmp;		//ビットを'1'にして透過
				}
				break;
			case 4:
				if(j % 2)
					Dat = m_XOR[m_BmpCounter][i * 4 + (7 - j) / 2] >> 4;
				else
					Dat = m_XOR[m_BmpCounter][i * 4 + (7 - j) / 2] & 0xF;
				if(Dat == BkCol) {
					tmp = 1 << j;
					Bit |= tmp;
				}
				break;
			case 8:
				if(m_XOR[m_BmpCounter][i * 8 + 7 - j] == BkCol) {
					tmp = 1 << j;
					Bit |= tmp;
				}
				break;
			case 16:
				if(m_XOR[m_BmpCounter][(i * 8 + 7 - j) * 2] == BkC[0] &&
				   m_XOR[m_BmpCounter][(i * 8 + 7 - j) * 2 + 1] == BkC[1]) {
					tmp = 1 << j;
					Bit |= tmp;
				}
				break;
			case 24:
				if(m_XOR[m_BmpCounter][(i * 8 + 7 - j) * 3] == BkC[0] &&
				   m_XOR[m_BmpCounter][(i * 8 + 7 - j) * 3 + 1] == BkC[1] &&
				   m_XOR[m_BmpCounter][(i * 8 + 7 - j) * 3 + 2] == BkC[2]) {
					tmp = 1 << j;
					Bit |= tmp;
				}
				break;
			case 32:
				if(m_XOR[m_BmpCounter][(i * 8 + 7 - j) * 4] == BkC[0] &&
				   m_XOR[m_BmpCounter][(i * 8 + 7 - j) * 4 + 1] == BkC[1] &&
				   m_XOR[m_BmpCounter][(i * 8 + 7 - j) * 4 + 2] == BkC[2] &&
				   m_XOR[m_BmpCounter][(i * 8 + 7 - j) * 4 + 3] == BkC[3]) {
					tmp = 1 << j;
					Bit |= tmp;
				}
				break;
			}
    	}
		m_AND[m_BmpCounter][i] = Bit;
	}
	// 幅が16の時には2バイト分の0が続くので修正する（以下はボトムアップ例）
	//　　　　現状のデーターの状態　　　　　　　　　　　実データ　　　余分な0（追加）
	//											  00000000 00000000 00000000 00000000
	//											  00000000 00000000 00000000 00000000
	//											  00000000 00000000 00000000 00000000
	//											  00000000 00000000 00000000 00000000
	// 00000000 00000000 00000000 00000000 −−＞ 11111111 11111111 00000000 00000000
	// 00000000 00000000 00000000 00000000 −−＞ 10000000 00000001 00000000 00000000
	// 10000000 00000001 11111111 11111111 −−＞ 10000000 00000001 00000000 00000000
	// 11111111 11111111 10000000 00000001 −−＞ 11111111 11111111 00000000 00000000
	// -------------------------------------------------------------------------------
	// 01234567 89ABCDEF 01234567 89ABCDEF		   01234567 89ABCDEF 01234567 89ABCDEF
	if(PBmi->biWidth == 16) {
		LPBYTE temp = (LPBYTE)LocalAlloc(LPTR, MaskSize);
		if(!temp) {
			MessageBox(NULL, "ローカルメモリーが確保できませんでした",
						"エラー", MB_OK | MB_ICONSTOP);
			CloseHandle(hFile);
			return FALSE;
		}
		int j = 0;
		for(int i = 0; i < MaskSize / 2; i += 2, j += 4) {
			temp[j] = m_AND[m_BmpCounter][i];
			temp[j + 1] = m_AND[m_BmpCounter][i + 1];
			temp[j + 2] = 0;
			temp[j + 3] = 0;
		}
		memcpy(m_AND[m_BmpCounter], temp, MaskSize);
		GlobalFree((HGLOBAL)temp);
	}
	//カラービットマップを作成
	m_hBmp[m_BmpCounter] = CreateCompatibleBitmap(m_hDC, PBmi->biWidth, PBmi->biHeight);
	//カラービットマップのBitデータを与える
	if(SetDIBits(m_hDC, m_hBmp[m_BmpCounter], 0, PBmi->biHeight, m_XOR[m_BmpCounter],
				(LPBITMAPINFO)PBmi, DIB_RGB_COLORS) == ERROR_INVALID_PARAMETER) {
		MessageBox(m_hWnd, "マスクビットマップの作成に失敗しました",
				"エラー", MB_OK | MB_ICONERROR);
		DeleteObject(m_hBmp[m_BmpCounter]);
		CloseHandle(hFile);
		return FALSE;
	}
	//マスクビットマップを作成
	m_hMaskBmp[m_BmpCounter] = CreateCompatibleBitmap(m_hDC, PBmi->biWidth, PBmi->biHeight);
	//モノクロにする
	WORD OldCol = PBmi->biBitCount;
	PBmi->biBitCount = 1;
	RGBQUAD Oldrgb[2];
	memcpy(Oldrgb, PBmi + sizeof(BITMAPINFOHEADER), sizeof(RGBQUAD) * 2);
	RGBQUAD mono[2] =	{{0, 0, 0, 0},
						 {0xff, 0xff, 0xff, 0}
						};
	memcpy(PBmi + sizeof(BITMAPINFOHEADER), mono, sizeof(RGBQUAD) * 2);
	//マスクビットマップのBitデータを与える
	if(SetDIBits(m_hDC, m_hMaskBmp[m_BmpCounter], 0, PBmi->biHeight, m_AND[m_BmpCounter],
				(LPBITMAPINFO)PBmi, DIB_RGB_COLORS) == ERROR_INVALID_PARAMETER) {
		MessageBox(m_hWnd, "マスクビットマップの作成に失敗しました",
				"エラー", MB_OK | MB_ICONERROR);
		DeleteObject(m_hMaskBmp[m_BmpCounter]);
		CloseHandle(hFile);
		return FALSE;
	}
	//元に戻す
	PBmi->biBitCount = OldCol;
	memcpy(PBmi + sizeof(BITMAPINFOHEADER), Oldrgb, sizeof(RGBQUAD) * 2);
	//アイコン、カーソルファイル用に修正
	PBmi->biHeight *= 2;	//biHeightは2倍になっている
	PBmi->biSizeImage += MaskSize;	//ANDビットマップのサイズを追加
	//ファイルをクローズする
	if(!CloseHandle(hFile))
		MessageBox(m_hWnd, "ファイルをクローズできませんでした",
					"エラー", MB_OK | MB_ICONSTOP);
	//(ICONDIRENTRY)m_Iconentryにデータを入れる
	m_Iconentry[m_BmpCounter].bWidth = PBmi->biWidth;
	m_Iconentry[m_BmpCounter].bHeight = PBmi->biHeight / 2;
	switch(PBmi->biBitCount) {
	case 1:
		m_Iconentry[m_BmpCounter].bColorCount = 2;
		break;
	case 4:
		m_Iconentry[m_BmpCounter].bColorCount = 16;
		break;
	default:
		m_Iconentry[m_BmpCounter].bColorCount = 0;
		break;
	}
	m_Iconentry[m_BmpCounter].bReserved = 0;
	m_Iconentry[m_BmpCounter].wPlanes = PBmi->biPlanes;
	m_Iconentry[m_BmpCounter].wBitCount = PBmi->biBitCount;
	m_Iconentry[m_BmpCounter].dwBytesInRes = sizeof(BITMAPINFOHEADER) + rgbq + BmpSize + MaskSize;
	m_Iconentry[m_BmpCounter].dwImageOffset = 0;	//保存時まで未定
	//追加が完了したらビットマップカウンターを進める
	m_BmpCounter++;

	return TRUE;
}

/////////////////////////
//登録ビットマップの削除
/////////////////////////
bool CICON::Del_Bitmap(int del) {

	if(del >= m_BmpCounter)
		return FALSE;
	//イメージデータ
	LocalFree(m_ImageDat[del]);
	//作成済ビットマップ
	DeleteObject(m_hBmp[del]);
	DeleteObject(m_hMaskBmp[del]);
	for(int i = del; i < m_BmpCounter; i++) {
		//ICONDIRENTRY構造体
		m_Iconentry[i] = m_Iconentry[i + 1];
		//構成ビットマップのDIB情報取得用
		m_ImageDat[i] = m_ImageDat[i + 1];	//構成ビットマップデータ
		m_lpBmi[i] = m_lpBmi[i + 1];		//BITMAPINFO構造体へのポインター
		m_XOR[i] = m_XOR[i + 1];			//カラービットマップポインター
		m_AND[i] = m_AND[i + 1];			//マスクビットマップポインター
		//構成ビットマップのハンドル
		m_hBmp[i] = m_hBmp[i + 1];			//カラービットマップ
		m_hMaskBmp[i] = m_hMaskBmp[i + 1];	//マスクビットマップ
	}
	m_BmpCounter--;
	m_ImageDat[m_BmpCounter] = 0;
	m_lpBmi[m_BmpCounter] = 0;
	m_XOR[m_BmpCounter] = 0;
	m_AND[m_BmpCounter] = 0;
	m_hBmp[m_BmpCounter] = 0;
	m_hMaskBmp[m_BmpCounter] = 0;
	return TRUE;
}

//////////////////////////////////////////////////////
//特定のビットマップのICONDIRENTRYへのポインターを返す
//////////////////////////////////////////////////////
bool CICON::GetIDEntry(int i, LPICONDIRENTRY *lpide) {

	if(i < m_BmpCounter) {
		*lpide = &m_Iconentry[i];
		return TRUE;
	}
	else
		return FALSE;
}

//////////////////////////////////////////////////////////
//特定のビットマップのBITMAPINFOHEADERへのポインターを返す
//////////////////////////////////////////////////////////
bool CICON::GetBmpInfo(int i, PBITMAPINFOHEADER *pbmi) {

	if(i < m_BmpCounter) {
		*pbmi = (PBITMAPINFOHEADER)m_lpBmi[i];
		return TRUE;
	}
	else
		return FALSE;
}

//アイコンのハンドルを返す
HICON CICON::GetIcon() {

	return m_hIcon;
}

//カラー（XOR）ビットマップのハンドルを返す
HBITMAP CICON::GetColBmp(int i) {

 	return m_hBmp[i];
}

//マスク（AND）ビットマップのハンドルを返す
HBITMAP CICON::GetMaskBmp(int i) {

 	return m_hMaskBmp[i];
}

///////////////////////////////////////////////////////////////
//ファイルへアイコンまたはカーソルを書き込む（Icon-1、Cursor-2）
//iType	: Icon = 1(IMAGE_ICON:規定値)、Cursor = 2(IMAGE_CURSOR)
//hspx, y:ホットスポットのx, y座標（イメージサイズ以内）
///////////////////////////////////////////////////////////////
bool CICON::Save_Icon(LPTSTR FileName, UINT iType = IMAGE_ICON) {

	//イメージタイプチェック（IMAGE_ICON, IMAGE_CURSOR以外はエラー）
	if(iType != 1 && iType != 2) {
		MessageBox(m_hWnd, "IMAGE_ICON(1)、IMAGE_CURSOR(2)ではありません",
					"エラー", MB_OK | MB_ICONSTOP);
    		return FALSE;
	}
	////////////////////////////////////
	//アイコン、カーソルデータを書き込む
	////////////////////////////////////
	//ファイルを開く
	HANDLE hFile = CreateFile(FileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
					FILE_ATTRIBUTE_NORMAL, NULL);
	if(hFile == INVALID_HANDLE_VALUE) {
		MessageBox(m_hWnd, "ファイルを開けられませんでした",
					"エラー", MB_OK | MB_ICONSTOP);
		return FALSE;
	}
	//ICONDIRを書き込む
	m_Icondir.idReserved = 0;
	m_Icondir.idType = iType;
	m_Icondir.idCount = m_BmpCounter;
	DWORD dwWrite;
	if(!WriteFile(hFile, &m_Icondir, sizeof(ICONDIR), &dwWrite, NULL)) {
		MessageBox(m_hWnd, "m_Icondirを書き込めませんでした",
					"エラー", MB_OK | MB_ICONSTOP);
		CloseHandle(hFile);
		return FALSE;
	}
	//ICONDIENTRYRを書き込む
	DWORD Offset = sizeof(ICONDIR) + sizeof(ICONDIRENTRY) * m_BmpCounter;
	for(int i = 0; i < m_BmpCounter; i++) {
		m_Iconentry[i].dwImageOffset = Offset;	//オフセット値を代入する
		Offset += m_Iconentry[i].dwBytesInRes;	//次のオフセット値に更新する
		if(!WriteFile(hFile, &m_Iconentry[i], sizeof(ICONDIRENTRY),
					&dwWrite, NULL)) {
			MessageBox(m_hWnd, "m_Iconentryを書き込めませんでした",
						"エラー", MB_OK | MB_ICONSTOP);
			CloseHandle(hFile);
			return FALSE;
		}
	}
	for(int i = 0; i < m_BmpCounter; i++) {
		if(!WriteFile(hFile, m_ImageDat[i], m_Iconentry[i].dwBytesInRes,
					&dwWrite, NULL)) {
			MessageBox(m_hWnd, "m_ImageDatを書き込めませんでした",
						"エラー", MB_OK | MB_ICONSTOP);
			CloseHandle(hFile);
			return FALSE;
		}
	}
	CloseHandle(hFile);
	return TRUE;
}
