/////////////
//追加構造体
/////////////
//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;

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

//---------------------------------------
// CBMPEX Class - 改造ビットマップクラス
// Copyright (c) 2021, K. Yoshida
//---------------------------------------
class CBMPEX : public CBMP {

public:
	//アイコンハンドル
	HICON m_hIcon;
	//アイコン関連情報
	ICONDIR m_icondir;
	ICONDIRENTRY m_icondirentry;
	//使用ウィンドウのデバイスコンテキスト
	HDC m_hDC;
	//HotSpot(x, y)
	POINT m_Hotspot;
	//取得するビットマップデータへのポインター
	LPBYTE m_pImageDat;
	//デストラクター
	~CBMPEX();
	//初期化
	void SetWnd(HWND);
	//ファイルからアイコンまたはカーソルを取り込む（Icon-1、Cursor-2）
	bool LoadIconFromBMP(LPCTSTR, UINT, int, bool);
	//ファイルへアイコンまたはカーソルを書き込む（Icon-1、Cursor-2）
	bool SaveAsIcon(LPTSTR, int, UINT, int, int);
	//画面から上下(flag - FALSE)左右(flag - TRUE)反転画像のビットマップを取得
	bool FlipImage(HWND, int, int, int, int, bool);
};

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

	if(m_hIcon)
		DestroyIcon(m_hIcon);
	if(m_pImageDat)
		LocalFree(m_pImageDat);
	ReleaseDC(m_hWnd, m_hDC);
}

//初期化
void CBMPEX::SetWnd(HWND hWnd) {

	m_hWnd = hWnd;
	m_hDC = GetDC(m_hWnd);
}

//////////////////////////////////////////////////////////////
//アイコンまたはカーソルを取り込む
//iType	: Icon = 1、Cursor = 2
//flag	: ファイルから = TRUE（規定値）、リソースから = FALSE
//num	: 何番目のビットマップを読むか（"0"ベース、規定値−0）
//////////////////////////////////////////////////////////////
bool CBMPEX::LoadIconFromBMP(LPCTSTR FileName, UINT iType,
								int num = 0, bool flag = TRUE) {

	//イメージタイプチェック（IMAGE_ICON, IMAGE_CURSOR以外はエラー）
	if(iType != 1 && iType != 2)
		return FALSE;
	//既存アイコンの破棄、ビットマップの初期化
	if(m_hIcon) {
		DestroyIcon(m_hIcon);
		m_hIcon = 0;
	}
	CheckandInit();	//PBmfはアイコン、カーソルで使用しない
	//ロードオプション（デフォルトはファイルから入力）
	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, 0, 0, fLoad);
	if(!m_hIcon)	//アイコンまたはカーソルの読み込みに失敗した場合エラー
		return FALSE;
	//ファイルからアイコンまたはカーソルのサイズ、色情報を取得する
	DWORD dwResult;
	//ファイルオープン
	HANDLE hFile = CreateFile(FileName, GENERIC_READ, 0, NULL, OPEN_EXISTING,
					FILE_ATTRIBUTE_NORMAL, NULL);
	if(hFile == INVALID_HANDLE_VALUE)
		return FALSE;
	//ファイルからICONDIRを読み込む
	ReadFile(hFile, (ICONDIR*)&m_icondir, sizeof(ICONDIR), &dwResult, NULL);
	//取得対象（num）ビットマップが登録数（icondir.idCount）以上の場合エラー
	if(num >= m_icondir.idCount) {
		char str[MAX_PATH];
		wsprintf(str, "指定された番号（%d−\"0\"ベースの為、%d番目になります）"\
				"が画像数（%d）を超えています", num, num + 1, m_icondir.idCount);
		MessageBox(m_hWnd, str,  "エラー", MB_OK | MB_ICONSTOP);
		CloseHandle(hFile);
		return FALSE;
	}
	//先頭からnum番目（0ベース）のICONDIRENTRYへファイルポインター移動
	SetFilePointer(hFile, sizeof(ICONDIR) + sizeof(ICONDIRENTRY) * num,
					NULL, FILE_BEGIN);
	//ファイルからnum番目のICONDIRENTRYを読み込む
	ReadFile(hFile, (ICONDIRENTRY*)&m_icondirentry, sizeof(ICONDIRENTRY),
				&dwResult, NULL);
	//規定サイズではない場合、エラーとして初期化
	if(m_icondirentry.bWidth != 32 && m_icondirentry.bWidth != 16) {
		MessageBox(m_hWnd, "サイズが規定（16 x 16、32 x 32）外です", "エラー",
					MB_OK | MB_ICONSTOP);
		CloseHandle(hFile);
		return FALSE;
	}
	//カーソルの場合、ホットスポットを記録する
	if(iType == 2) {
	 	m_Hotspot.x = m_icondirentry.wPlanes;
	 	m_Hotspot.y = m_icondirentry.wBitCount;
	}
	//先頭からnum番目のイメージ情報へファイルポインター移動
	SetFilePointer(hFile, m_icondirentry.dwImageOffset, NULL, FILE_BEGIN);
	//num番目のビットマップ情報を取得する
	m_pImageDat = (LPBYTE)LocalAlloc(LPTR, m_icondirentry.dwBytesInRes);
	ReadFile(hFile, m_pImageDat, m_icondirentry.dwBytesInRes, &dwResult, NULL);
	//m_pImageDatのBITMAPINFO部のサイズを計算
	m_ClrBits = ((LPBITMAPINFOHEADER)m_pImageDat)->biBitCount;
	int infosize = sizeof(BITMAPINFOHEADER);
	//16, 24, 32bitフォーマットはBI_RGBの場合RGBQUADがない
	if(m_ClrBits <= 8)
		infosize += (sizeof(RGBQUAD) * (1 << m_ClrBits));
	//PBITMAPINFO(m_PBmi)のメモリーを確保し、データを取得
	m_PBmi = (LPBITMAPINFO)LocalAlloc(LPTR, infosize);
	memcpy(m_PBmi, m_pImageDat, infosize);
	m_PBmi->bmiHeader.biHeight /= 2;	//倍になっている高さを戻す
	//num番目のビットマップ作成
	m_hBMP = CreateCompatibleBitmap(m_hDC, m_icondirentry.bWidth,
									m_icondirentry.bHeight);
	//カラービットマップのBitデータを与える
	bool result = SetDIBits(m_hDC, m_hBMP, 0, m_icondirentry.bHeight,
							m_pImageDat + infosize, m_PBmi, DIB_RGB_COLORS);
	//BITMAPデータ設定
	GetObject(m_hBMP, sizeof(BITMAP), &m_Bmp);
	//Iconファイルをクローズする
	CloseHandle(hFile);
	if(!m_hBMP || !result) {
		MessageBox(m_hWnd, "ビットマップの作成に失敗しました", "エラー",
					MB_OK | MB_ICONERROR);
		return FALSE;
	}
	else
		return TRUE;
}

///////////////////////////////////////////////////////
//ビットマップをアイコンとしてファイルへ書き込む
//FileName	: ファイルパスとファイル名
//CBit		: 色深さ（1, 4, 8, 16, 24, 32bit）
//iType		: Icon = 1、Cursor = 2
//hsx, hsy	: カーソルの場合、ホットスポットのx, y座標
///////////////////////////////////////////////////////
bool CBMPEX::SaveAsIcon(LPTSTR FileName, int CBit = 0,
						UINT iType = 1, int hsx = 0, int hsy = 0) {

	//ローカル変数
	HANDLE hFile;			//フィルハンドル
	LPBYTE lpBits;			//メモリーへのポインター
	DWORD dwTotal;			//総バイト数
	DWORD dwTmp;			//WriteFile()関数の書込バイト数用
	DWORD BMPSize;			//ビットマップサイズ計算用
	int nSuccess;			//GetDIBits関数の成功判定フラグ
	HDC hDC, hMem;			//デスクトップDCとコンパチビットマップDC
	PBITMAPINFO PBmi;		//書込み用
	DWORD bmpSize;			//ビットマッップバイトサイズ
	int BkCol;				//背景色パレット番号（Cbit == 1, 4, 8の場合）
	char BkC[4];			//背景色パレット番号（Cbit == 24の場合）
	ICONDIR IconDir;		//ICONDIR構造体
	ICONDIRENTRY IconEntry;	//ICONDIRENTRY構造体
	LPBYTE mskBits;			//マスクビットメモリーへのポインター
	DWORD mskSize;			//マスクビットバイトサイズ
	//iTypeのチェック
	if(iType != 1 && iType != 2)
		return FALSE;
	//イメージサイズチェック（16 x 16と32 x 32しか受け付けない）
	if(m_Bmp.bmWidth != 32 && m_Bmp.bmWidth != 16)
		return FALSE;
	//CBitのチェック（1, 4, 8, 16, 24, 32以外は受け付けられない）
	switch(CBit) {
	case 1:
	case 4:
	case 8:
	case 16:
	case 24:
	case 32:
		break;
	default:
		return FALSE;
	}
	//PBITMAPINFO PBmiの為のメモリーを確保（固定メモリー・ゼロで初期化）
	if (CBit <= 8)
		PBmi = (PBITMAPINFO)LocalAlloc(LPTR,
				sizeof(BITMAPINFOHEADER) +
				sizeof(RGBQUAD) * (1 << CBit));
	//24bitフォーマットはBI_RGBの場合RGBQUADがない
	else
		PBmi = (PBITMAPINFO)LocalAlloc(LPTR,
				sizeof(BITMAPINFOHEADER));
	if(!PBmi) {	//メモリー確保失敗
			MessageBox(NULL, "PBmiのローカルメモリー確保に失敗しました",
						"エラー!", MB_OK | MB_ICONSTOP);
			return FALSE;
	}
	//ビットマップデータサイズを算出
	BMPSize = ((CBit * m_Bmp.bmWidth + 31) / 32) * 4
				* abs(m_Bmp.bmHeight);
	//BITMAPINFOの準備
	PBmi->bmiHeader.biSize			= sizeof(BITMAPINFOHEADER);
	PBmi->bmiHeader.biWidth			= m_Bmp.bmWidth;
	PBmi->bmiHeader.biHeight		= m_Bmp.bmHeight;
	PBmi->bmiHeader.biPlanes		= 1;
	PBmi->bmiHeader.biBitCount		= CBit;
	PBmi->bmiHeader.biCompression	= BI_RGB;	//0x0
	PBmi->bmiHeader.biSizeImage		= BMPSize;
	PBmi->bmiHeader.biXPelsPerMeter	= 0;
	PBmi->bmiHeader.biYPelsPerMeter	= 0;
	PBmi->bmiHeader.biClrUsed		= 0;
	PBmi->bmiHeader.biClrImportant	= 0;
	//ビットパターンデータの準備
	lpBits = (LPBYTE)LocalAlloc(LPTR, BMPSize);
	if(!lpBits) {
		MessageBox(NULL, "グローバルメモリーが確保できませんでした",
					"エラー", MB_OK | MB_ICONSTOP);
		LocalFree(PBmi);
		return FALSE;
	}
	//ここで色数を変更
	hDC = GetDC(0);					//デスクトップのデバイスコンテキスト
	hMem = CreateCompatibleDC(hDC);	//そのコンパチDC
	SelectObject(hMem, m_hBMP);		//ビットマップを読ませる
	//ビット配列をGetDIBits関数でグローバルメモリーに取り出す
	nSuccess = GetDIBits(hMem, m_hBMP, 0, m_Bmp.bmHeight,
							lpBits, PBmi, DIB_RGB_COLORS);
	DeleteDC(hMem) ;				//コンパチDCを削除
	ReleaseDC(0, hDC);				//デスクトップのデバイスコンテキストを開放
	if(!nSuccess) {	//色数変更失敗
		MessageBox(NULL, "色数変更ビットマップのビット配列取得に失敗しました",
					"エラー", MB_OK | MB_ICONSTOP);
		LocalFree(PBmi);
		LocalFree((HGLOBAL)lpBits);
		return FALSE;
	}
	//＝＝＝＝＝＝＝＝＝＝　参考情報　＝＝＝＝＝＝＝＝＝＝
	
	//ＷxＨのボトムアップ（Hが正の場合)ビットマップの場合
	// H
	//↑
	//31または					【解説】
	//15 * * * * * * * *     *	「*」がピクセルを表す画素単位とすると
	//〜						【CBit == 1の場合】
	// 7 * * * * * * * *     *	 幅2（16）または4（32）バイトの各ビット
	// 6 * * * * * * * *     *	【CBit == 4の場合】
	// 5 * * * * * * * *     *	 幅8（16）または16（32）バイトの上下各4ビット
	// 4 * * * * * * * *     * 	【CBit == 8の場合】
	// 3 * * * * * * * *     *	 幅16または32バイトの各8ビット（1バイト）
	// 2 * * * * * * * *     *	【CBit == 24の場合】
	// 1 * * * * * * * *     *	 幅16 x 3または32 x 3バイトの各3バイト（BGRの順）
	// 0 * * * * * * * *     *	【CBit == 16または32の場合】→各2または4バイト
	//   0 1 2 3 4 5 6 7 〜 15または31
	//
	//イメージ最右下端ピクセルの色を背景色に設定し、その1バイトを取り出す
	if(PBmi->bmiHeader.biHeight > 0) {	//ボトムアップ
		switch(CBit) {
		case 1:		//モノクロの場合は「幅 / 8」バイトの第1ビットが値
			BkCol = lpBits[m_Bmp.bmWidth / 8 - 1] & 1;	//0か1となる
			break;
		case 4:		//16色の場合「幅 / 2」バイトのは下位4ビットが値
			BkCol = lpBits[m_Bmp.bmWidth / 2 - 1] & 0xF;
			break;
		case 8:		//256色の場合は8ビットが値
			BkCol = lpBits[m_Bmp.bmWidth - 1];
			break;
		case 16:	//16bitの場合は2byte(RGB555 or 565の順)が値
			BkC[0] = lpBits[m_Bmp.bmWidth * 2 - 2];	//RGB555または
			BkC[1] = lpBits[m_Bmp.bmWidth * 2 - 1];	//RGB565を想定
			break;
		case 24:	//24bitの場合は3byte(BRGの順)が値
			BkC[0] = lpBits[m_Bmp.bmWidth * 3 - 3];	//B
			BkC[1] = lpBits[m_Bmp.bmWidth * 3 - 2];	//G
			BkC[2] = lpBits[m_Bmp.bmWidth * 3 - 1];	//R
			break;
		case 32:	//32bitの場合は4byte(BRGRsvdの順)が値
			BkC[0] = lpBits[m_Bmp.bmWidth * 4 - 4];	//B
			BkC[1] = lpBits[m_Bmp.bmWidth * 4 - 3];	//G
			BkC[2] = lpBits[m_Bmp.bmWidth * 4 - 2];	//R
			BkC[3] = lpBits[m_Bmp.bmWidth * 4 - 1];	//Rsvd
			break;
		}
    }
	else {								//ボトムダウン
		switch(CBit) {
		case 1:		//モノクロの場合は最終バイトの第1ビットが値
			BkCol = lpBits[BMPSize - 1] & 1;	//0か1となる
			break;
		case 4:		//16色の場合は最終バイトの下位4ビットが値
			BkCol = lpBits[BMPSize - 1] & 0xf;
			break;
		case 8:		//256色の場合最終バイトが値
			BkCol = lpBits[BMPSize - 1];
			break;
		case 16:	//16bitの場合はは2byte(RGB555 or 565の順)が値
			BkC[0] = lpBits[BMPSize - 2];		//RGB555または
			BkC[1] = lpBits[BMPSize - 1];		//RGB565を想定
			break;
		case 24:	//24bitの場合は3byte(BRGの順)が値
			BkC[0] = lpBits[BMPSize - 3];		//B
			BkC[1] = lpBits[BMPSize - 2];		//G
			BkC[2] = lpBits[BMPSize - 1];		//R
			break;
		case 32:	//32bitの場合は4byte(BRGRsvdの順)が値
			BkC[0] = lpBits[BMPSize - 4];		//B
			BkC[1] = lpBits[BMPSize - 3];		//G
			BkC[2] = lpBits[BMPSize - 2];		//R
			BkC[3] = lpBits[BMPSize - 1];		//Rsvd
			break;
		}
	}
	//マスクビットのサイズを算出（4の倍数で無ければならない）
	mskSize = ((m_Bmp.bmWidth + 31) / 32) * 4 * abs(m_Bmp.bmHeight);
	//マスクビット記憶領域を作成
	mskBits = (LPBYTE)LocalAlloc(LPTR, mskSize);
	if(!mskBits) {
		MessageBox(NULL, "グローバルメモリーが確保できませんでした",
					"エラー", MB_OK | MB_ICONSTOP);
		LocalFree(PBmi);
		LocalFree((HGLOBAL)lpBits);
		return FALSE;
	}
	//マスクビットパターンの作成
	char Bit, tmp;	//各バイトの代入値算出用変数（tmpで1−透過をORしてゆく）
	int Dat;		//4bitビットマップ用色データ用変数の
	for(int i = 0; i < mskSize; i++) {
		Bit = 0;					//毎バイトで0に初期化
		for(int j = 7; j >= 0; j--) {	//左から右へ見て行く
			switch(CBit) {
			case 1:
				tmp = 1 << j;
				if(lpBits[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 = lpBits[i * 4 + (7 - j) / 2] >> 4;
				else
					Dat = lpBits[i * 4 + (7 - j) / 2] & 0xF;
				if(Dat == BkCol) {
					tmp = 1 << j;
					Bit |= tmp;
				}
				break;
			case 8:
				if(lpBits[i * 8 + 7 - j] == BkCol) {
					tmp = 1 << j;
					Bit |= tmp;
				}
				break;
			case 16:
				if(lpBits[(i * 8 + 7 - j) * 2] == BkC[0] &&
				   lpBits[(i * 8 + 7 - j) * 2 + 1] == BkC[1]) {
					tmp = 1 << j;
					Bit |= tmp;
				}
				break;
			case 24:
				if(lpBits[(i * 8 + 7 - j) * 3] == BkC[0] &&
				   lpBits[(i * 8 + 7 - j) * 3 + 1] == BkC[1] &&
				   lpBits[(i * 8 + 7 - j) * 3 + 2] == BkC[2]) {
					tmp = 1 << j;
					Bit |= tmp;
				}
				break;
			case 32:
				if(lpBits[(i * 8 + 7 - j) * 4] == BkC[0] &&
				   lpBits[(i * 8 + 7 - j) * 4 + 1] == BkC[1] &&
				   lpBits[(i * 8 + 7 - j) * 4 + 2] == BkC[2] &&
				   lpBits[(i * 8 + 7 - j) * 4 + 3] == BkC[3]) {
					tmp = 1 << j;
					Bit |= tmp;
				}
				break;
			}
    	}
		mskBits[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(m_Bmp.bmWidth == 16) {
		LPBYTE temp = (LPBYTE)LocalAlloc(LPTR, mskSize);
		if(!temp) {
			MessageBox(NULL, "グローバルメモリーが確保できませんでした",
						"エラー", MB_OK | MB_ICONSTOP);
			LocalFree(PBmi);
			LocalFree(lpBits);
			LocalFree(mskBits);
			return FALSE;
		}
		int j = 0;
		for(int i = 0; i < mskSize / 2; i += 2, j += 4) {
			temp[j] = mskBits[i];
			temp[j + 1] = mskBits[i + 1];
			temp[j + 2] = 0;
			temp[j + 3] = 0;
		}
		memcpy(mskBits, temp, mskSize);
		LocalFree(temp);
	}
	//ICONDIR構造体の準備
	IconDir.idReserved = 0;						//必ず0
	IconDir.idType = iType;						//アイコの場合1、カーソルの場合2
	IconDir.idCount = 1;						//エントリーの数
	//ICONDIRENTRY構造体の準備
	IconEntry.bWidth = m_Bmp.bmWidth;			//アイコンの幅
	IconEntry.bHeight = m_Bmp.bmHeight;			//アイコンの高さ
	switch(CBit) {								//色数（bColorCount  = 1 << (wBitCount * wPlanes)）
	case 1:
	case 4:
		IconEntry.bColorCount	= 1 << (1 * CBit);
		break;
	case 8:										//但し256色以上はゼロ
	case 16:
	case 24:
	case 32:
		IconEntry.bColorCount	= 0;
		break;
	}
	IconEntry.bReserved			= 0;			//必ず0
	if(iType == 1) {							//アイコンの場合
		IconEntry.wPlanes		= 1;			//プレーン数
		IconEntry.wBitCount		= CBit;			//ビットカウント
	}
	else if(iType == 2) {						//カーソルの場合
		IconEntry.wPlanes		= hsx;			//xホットスポット
		IconEntry.wBitCount		= hsy;			//yホットスポット
	}
	//画像データのバイト数-BITMAPINFO(40) + (Color Pallette) + BMPSize + MaskBit size
	//1, 4, 8bitフォーマットはBI_RGBの場合RGBQUADがある
	if (CBit <= 8)
		IconEntry.dwBytesInRes	= 40 + 4 * (1 << CBit) + BMPSize + mskSize;
	//24bitフォーマットはBI_RGBの場合RGBQUADがない
	else
		IconEntry.dwBytesInRes	= 40 + BMPSize + mskSize;
	//画像データまでのオフセットICONDIR( = 6) + ICONDIRENTRY( = 16)
	IconEntry.dwImageOffset			= sizeof(ICONDIR) + sizeof(ICONDIRENTRY);
	//BITMAPINFO構造体の修正
	PBmi->bmiHeader.biHeight		= m_Bmp.bmHeight * 2;	//ここが通常のビットマップと異なる
	PBmi->bmiHeader.biCompression	= 0;					//ここは常に0
	PBmi->bmiHeader.biSizeImage		= BMPSize + mskSize;	//表示データ部とマスクデータ部の合計サイズ
	PBmi->bmiHeader.biXPelsPerMeter	= 0;
	PBmi->bmiHeader.biYPelsPerMeter	= 0;
	PBmi->bmiHeader.biClrUsed		= 0;
	PBmi->bmiHeader.biClrImportant	= 0;
	//------------
	//ファイル作成
	//------------
	//書き込み用ファイルを開く
	hFile = CreateFile(FileName,		//ファイル名
					GENERIC_WRITE,
					(DWORD)0,
					(LPSECURITY_ATTRIBUTES)NULL,
					CREATE_ALWAYS,
					FILE_ATTRIBUTE_NORMAL,
					(HANDLE)NULL);
	if(hFile == INVALID_HANDLE_VALUE) {
		MessageBox(NULL, "ファイルを開くことができませんでした",
					"エラー", MB_OK | MB_ICONSTOP);
		LocalFree(PBmi);
		GlobalFree((HGLOBAL)lpBits);
		GlobalFree((HGLOBAL)mskBits);
		return FALSE;
	}
	//ICONDIR構造体をファイルへ書き込む
	if(!WriteFile(hFile, &IconDir, sizeof(ICONDIR), (LPDWORD)&dwTmp, (LPOVERLAPPED)NULL)) {
		MessageBox(NULL, "アイコンファイルヘッダーを書き込むことができませんでした",
					"エラー", MB_OK | MB_ICONSTOP);
		LocalFree(PBmi);
		LocalFree((HGLOBAL)lpBits);
		LocalFree((HGLOBAL)mskBits);
		CloseHandle(hFile);
		return FALSE;
	}
	//ICONDIRENTRY構造体をファイルへ書き込む
	if(!WriteFile(hFile, &IconEntry, sizeof(ICONDIRENTRY), (LPDWORD)&dwTmp, (LPOVERLAPPED)NULL)) {
		MessageBox(NULL, "アイコン情報ヘッダーを書き込むことができませんでした",
					"エラー", MB_OK | MB_ICONSTOP);
		LocalFree(PBmi);
		LocalFree(lpBits);
		LocalFree(mskBits);
		CloseHandle(hFile);
		return FALSE;
	}
	//BITMAPINFOHEADERとRGBQUADをファイルへ書き込む
	if (CBit <= 8) {
		if(!WriteFile(hFile, PBmi, 40 + 4 * (1 << CBit), (LPDWORD)&dwTmp, (LPOVERLAPPED) NULL)) {
			MessageBox(NULL, "ビットマップ情報とカラーテーブルを書き込むことができませんでした",
						"エラー", MB_OK | MB_ICONSTOP);
			LocalFree(PBmi);
			LocalFree(lpBits);
			LocalFree(mskBits);
			CloseHandle(hFile);
			return FALSE;
		}
	}
	//24bitフォーマットはBI_RGBの場合RGBQUADがない
	else {
		if(!WriteFile(hFile, PBmi, 40, (LPDWORD)&dwTmp, (LPOVERLAPPED) NULL)) {
			MessageBox(NULL, "ビットマップ情報とカラーテーブルを書き込むことができませんでした",
						"エラー", MB_OK | MB_ICONSTOP);
			LocalFree(PBmi);
			LocalFree(lpBits);
			LocalFree(mskBits);
			CloseHandle(hFile);
			return FALSE;
		}
	}
	//Colorビットマップビット配列をファイルへ書き込む
	if(!WriteFile(hFile, lpBits, BMPSize, (LPDWORD)&dwTmp, (LPOVERLAPPED)NULL)) {
		MessageBox(NULL, "カラービット配列を書き込むことができませんでした",
					"エラー", MB_OK | MB_ICONSTOP);
		LocalFree(PBmi);
		LocalFree(lpBits);
		LocalFree(mskBits);
		CloseHandle(hFile);
		return FALSE;
	}
	//Maskビットマップビット配列をファイルへ書き込む
	if(!WriteFile(hFile, mskBits, mskSize, (LPDWORD)&dwTmp, (LPOVERLAPPED)NULL)) {
		MessageBox(NULL, "マスクビット配列を書き込むことができませんでした",
					"エラー", MB_OK | MB_ICONSTOP);
		LocalFree(PBmi);
		LocalFree(lpBits);
		LocalFree(mskBits);
		CloseHandle(hFile);
		return FALSE;
	}
	//Iconファイルをクローズする
	if(!CloseHandle(hFile))
		MessageBox(NULL, "ファイルをクローズできませんでした",
					"エラー", MB_OK | MB_ICONSTOP);
	//メモリーを解放
	LocalFree(PBmi);
	LocalFree(lpBits);
	LocalFree(mskBits);
	return TRUE;
}

//画面から上下(flag - FALSE)左右(flag - TRUE)反転画像のビットマップを取得
bool CBMPEX::FlipImage(HWND hWnd, int x, int y, int w, int h, bool flag = TRUE) {

	//初期化
	CheckandInit();
	//コンパチビットマップに反転画像を読み取る
	m_hWnd = hWnd;
	HDC hDC = GetDC(hWnd);						//ウィンドウDCを取得
	HDC memDC = CreateCompatibleDC(hDC);		//コンパチDCを作成
	m_hBMP = CreateCompatibleBitmap(hDC, w, h);	//コンパチビットマップを作成
	SelectObject(memDC, m_hBMP);				//ビットマップを選択
	if(flag)
		StretchBlt(memDC, w - 1, 0, -w, h, hDC, x, y, w, h, SRCCOPY);
	else
		StretchBlt(memDC, 0, h - 1, w, -h, hDC, x, y, w, h, SRCCOPY);
	ReleaseDC(hWnd, hDC);						//ウィンドウDCを開放
	DeleteObject(memDC);						//コンパチDCを削除
	return GetDDBInfo();						//新ビットマップの情報取得
}
