//////////////////////////////
// CIMGLISTクラス定義ファイル
//（Bitmapのみ）
// Copyright (c) August, 2022
//        By Ysama
//////////////////////////////

class CIMGLIST
{
public:
	HIMAGELIST m_hImgList;	//イメージリストハンドル
	UINT m_flag;			//イメージリストのフラッグ
	int	m_w;				//イメージの幅
	int	m_h;				//イメージの高さ
	int m_ImgNum;			//最大イメージ数
	int m_ImgIndex;			//現在のイメージインデックス
	bool m_fDragging;		//ドラッグ操作フラグ（実行中TRUE）
	POINT m_ptHotSpot;		//イメージのホットスポット
	HWND m_hWnd;			//表示対象ウィンドウハンドル
	CANVAS* m_cvs;			//表示用ウィンドウ仮想ウィンドウ
	int m_cxOffset	;		//ウィンドウ外寸とクライアント領域の差
	int m_cyOffset	;		//ウィンドウ外寸とクライアント領域の差

	CIMGLIST();											//コンストラクター（１）
	CIMGLIST(HWND, int, int, UINT, int, int, CANVAS*);	//コンストラクター（２）
	~CIMGLIST();										//デストラクター
	bool Init(HWND, int, int, UINT, int, int, CANVAS*);	//ImageListの初期化
	bool GetInfo(int, IMAGEINFO*);						//イメージ情報を取る
	bool AddImage(HBITMAP, HBITMAP);					//イメージの追加（１）
	bool AddMasked(HBITMAP, COLORREF);					//イメージの追加（２）
	bool Replace(int, HBITMAP, HBITMAP);				//イメージの交換（１）
	void Exchange(int, int);							//イメージの交換（２）
	void ReArrange(int, int);							//イメージの並び替え
	bool DeleteImage(int);								//イメージの削除
	int Count();										//現在の保有イメージ数
	bool ShowImage(int, int, int);						//イメージの表示
	void ShowAll(int, int);								//全イメージの表示
	bool StartDragging(int, int, int, int, int);		//イメージドラッグ開始
	bool MoveImage(int, int);							//イメージを動かす
	bool StopDragging(int, int);						//ドラッグ終了
};

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

	m_hImgList = 0;
	m_hWnd = 0;
	m_ImgNum = 0;
}

//コンストラクター（２）
CIMGLIST::CIMGLIST(HWND hWnd, int w, int h, UINT flag = ILC_COLOR,
					int ininum = 32, int addnum = 8, CANVAS* cvs = 0) {

	Init(hWnd, w, h, flag, ininum, addnum, cvs);	//最後のイメージは作業用
}

//デストラクター（イメージリストの破壊）
CIMGLIST::~CIMGLIST() {

	ImageList_Destroy(m_hImgList);
}

//ImageListの初期化
bool CIMGLIST::Init(HWND hWnd, int w, int h, UINT flag = ILC_COLOR,
					int ininum = 32, int addnum = 8, CANVAS* cvs = 0) {

	m_hWnd = hWnd;
	m_ImgNum = ininum;
	m_w = w;
	m_h = h;
	m_cvs = cvs;
	//ウィンドウ外寸と内寸差を測る
	RECT winrect, clrect;
	GetWindowRect(m_hWnd, &winrect);
	GetClientRect(m_hWnd, &clrect);
	m_cxOffset = ((winrect.right - winrect.left) -
					(clrect.right - clrect.left)) / 2;		//境界線の幅
	m_cyOffset = ((winrect.bottom - winrect.top) -
					(clrect.bottom - clrect.top)) -			//キャプション、メニューと
					m_cxOffset;								//境界線の高さ
	return m_hImgList  = ImageList_Create(w, h, m_flag = flag, ininum, addnum);
}

//イメージ情報を取る
bool CIMGLIST::GetInfo(int num, IMAGEINFO* lpImgInfo) {

	return ImageList_GetImageInfo(m_hImgList, num, lpImgInfo);
}

//イメージの追加（１）
bool CIMGLIST::AddImage(HBITMAP hbmImage, HBITMAP hbmMask = NULL) {

	bool bSuccess = ImageList_Add(m_hImgList, hbmImage, hbmMask);
	m_ImgIndex = Count();
	return bSuccess;
}

//イメージの追加（２）
bool CIMGLIST::AddMasked(HBITMAP hbmImage, COLORREF crMask) {

	bool bSuccess = ImageList_AddMasked(m_hImgList, hbmImage, crMask);
	m_ImgIndex = Count();
	return bSuccess;
}

//イメージの交換（１）
bool CIMGLIST::Replace(int num, HBITMAP hbmImage, HBITMAP hbmMask) {

	return ImageList_Replace(m_hImgList, num, hbmImage, hbmMask);
}

//イメージの交換（２）
void CIMGLIST::Exchange(int num1, int num2) {

	//次の行で「関数が見当たらない」エラーが出る人は"-D_WIN32_WINNT=0x400"オプションを与えてください。
	ImageList_Copy(m_hImgList, num1, m_hImgList, num2, ILCF_SWAP);
}

//イメージの並び替え
void CIMGLIST::ReArrange(int num1, int num2) {

	if(num1 > num2) {
		for(int i = num1; i > num2; i--)
			Exchange(i - 1, i);
	}
	else {
		for(int i = num1; i < num2; i++)
			Exchange(i, i + 1);
	}
}

//イメージの削除
bool CIMGLIST::DeleteImage(int num) {

	bool bSuccess = ImageList_Remove(m_hImgList, num);
	m_ImgIndex = Count();
	return bSuccess;
}

//現在の保有イメージ数
int CIMGLIST::Count() {

	return ImageList_GetImageCount(m_hImgList);
}

//イメージの表示（１）
bool CIMGLIST::ShowImage(int x, int y, int i) {

	if (m_cvs)
		return ImageList_Draw(m_hImgList, i, m_cvs->hDC(), x, y, ILD_TRANSPARENT);
	else {
		HDC hDC = GetDC(m_hWnd);
		return ImageList_Draw(m_hImgList, i, hDC, x, y, ILD_TRANSPARENT);
		ReleaseDC(m_hWnd, hDC);
	}
}

//イメージの表示（２）
void CIMGLIST::ShowAll(int x, int y) {

	if (m_cvs)
		for(int i = 0, j = Count(); i < j; i++) {
			ImageList_Draw(m_hImgList, i, m_cvs->hDC(), x + i * m_w, y, ILD_TRANSPARENT);
		}
	else {
		HDC hDC = GetDC(m_hWnd);
		for(int i = 0, j = Count(); i < j; i++) {
			ImageList_Draw(m_hImgList, i, hDC, x + i * m_w, y, ILD_TRANSPARENT);
		}
		ReleaseDC(m_hWnd, hDC);
	}
}

//イメージドラッグ開始
bool CIMGLIST::StartDragging(int Imgx, int Imgy, int mx, int my, int num) { 

	//マウスキャプチャー
	SetCapture(m_hWnd);
	//ホットスポット位置の計算と記録
	m_ptHotSpot.x = mx - Imgx;
	m_ptHotSpot.y = my - Imgy;
	//ドラッグ開始
	if (!ImageList_BeginDrag(m_hImgList, m_ImgIndex = num,
					m_ptHotSpot.x, m_ptHotSpot.y))
		return FALSE;
	ImageList_DragEnter(m_hWnd, mx + m_cxOffset, my + m_cyOffset);
	//ドラッグフラグを真へ
	m_fDragging = TRUE; 
	//ウィンドウ描画を更新
	InvalidateRect(m_hWnd, NULL, TRUE);
	UpdateWindow(m_hWnd);
	return TRUE; 
}

//イメージを動かす
bool CIMGLIST::MoveImage(int x, int y) {

	if (!ImageList_DragMove(x + m_cxOffset, y + m_cyOffset))
		return FALSE;
	return TRUE;
}

//ドラッグ終了
bool CIMGLIST::StopDragging(int x, int y) {

	ImageList_EndDrag();
	ImageList_DragLeave(m_hWnd);
	m_fDragging = FALSE;
	ReleaseCapture();
	return TRUE;
}
