//////////////////////////////////////////
// DiceCtrl.cpp
//Copyright (c) 05/17/2022 by BCCSkelton
//////////////////////////////////////////
#include	"DiceCtrl.h"
#include	"Dll.h"

///////////
//外部変数
///////////
HINSTANCE g_hInstance;
HBITMAP g_hDice[6];
int g_Dice = 0;

/////////////////
// DLLMain関数
////////////////
int WINAPI DllMain(HINSTANCE hInstance, DWORD fdwReason, LPVOID lpReserved) {

	//インスタンスの取得
	g_hInstance = hInstance;
	return TRUE;
}

/////////////////////////
//"DICE"コールバック関数
/////////////////////////
LRESULT CALLBACK DiceProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) {

	//変数宣言
	LONG style;
	LONG estyle;
	RECT rec;
	HMENU hMenu, hPopupMenu;
	POINT pt;
	PAINTSTRUCT ps;
	HDC hDC, hCompDC;
	//メッセージ処理
	switch(Msg) {
	case WM_CREATE:
		//乱数の初期化
		srand(time(NULL));
		//ダイスの目のイメージを読み込む
		for(int i = 0; i < 6; i++) {
			g_hDice[i] = (HBITMAP)LoadImage(g_hInstance, MAKEINTRESOURCE(IDI_D1 + i), IMAGE_BITMAP, 0, 0, LR_DEFAULTSIZE);
			if(!g_hDice[i])
				MessageBox(hWnd, "ダイスのビットマップが読めません", "エラー", MB_OK | MB_ICONERROR);
		}
		break;
	case WM_RBUTTONDOWN:
		//ポップアップメニューの読込
		hMenu = LoadMenu(g_hInstance, "IDM_POPUP");
		hPopupMenu = GetSubMenu(hMenu, 0);
		//ウインドウの位置情報を取得
		GetWindowRect(hWnd, &rec);
		//ポップアップメニューの表示場所を設定
		GetCursorPos(&pt);
		//ポップアップメニューの表示
		TrackPopupMenu(hPopupMenu, TPM_LEFTALIGN | TPM_TOPALIGN | TPM_LEFTBUTTON, pt.x, pt.y, 0, hWnd, &rec);
		//ポップアップメニューの開放
		DestroyMenu(hMenu);
		break;
	case WM_COMMAND:
		if(LOWORD(wParam) != IDM_ROLL)
			return DefWindowProc(hWnd, Msg, wParam, lParam);
	case WM_LBUTTONDOWN:
		PlaySound("IDS_DICE", g_hInstance, SND_RESOURCE | SND_ASYNC);
	case DM_ROLL:
		//ウィンドウを押し下げたようにする
		style = GetWindowLong(hWnd, GWL_STYLE) ^ WS_DLGFRAME;
		SetWindowLong(hWnd, GWL_STYLE, style);
		estyle = GetWindowLong(hWnd, GWL_EXSTYLE) ^ WS_EX_WINDOWEDGE;
		estyle |= WS_EX_CLIENTEDGE;
		SetWindowLong(hWnd, GWL_EXSTYLE, estyle);
		SetWindowPos(hWnd, NULL, 0, 0, 0, 0, (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED));
		//乱数でサイコロの目を決める
		for(int i = 0; i < 10; i++) {
			g_Dice = rand() % 6;	//m_Dice = 0 - 5
			SetProp(hWnd, "DICE_NUM", (HANDLE)g_Dice);	//そのウィンドウにサイコロの目を保存する
			InvalidateRect(hWnd, NULL, TRUE);			//領域無効化
			UpdateWindow(hWnd);							//再描画命令
			Sleep(50);
		}
		//ウィンドウを元に戻す
		style |= WS_DLGFRAME;
		SetWindowLong(hWnd, GWL_STYLE, style);
		estyle |= WS_EX_WINDOWEDGE;
		estyle ^= WS_EX_CLIENTEDGE;
		SetWindowLong(hWnd, GWL_EXSTYLE, estyle);
		SetWindowPos(hWnd, NULL, 0, 0, 0, 0, (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED));
		//親へWin3.xのオマージュで通知コードHIWORD(wParam)の代わりに賽の目のメッセージを送る
		SendMessage(GetParent(hWnd), WM_COMMAND, MAKELONG(GetDlgCtrlID(hWnd), g_Dice + 1), LPARAM(hWnd));
		//親からのDM_ROLLメッセージの戻り値として賽の目を返す
		return g_Dice + 1;
	case WM_PAINT:
		hDC = BeginPaint(hWnd, &ps);
		//ダイスの描画
			//クライアントエリアサイズの取得
			RECT rec;
			GetClientRect(hWnd, &rec);
			//ウィンドウプロパティからサイコロの目を取り出す
			g_Dice = (int)GetProp(hWnd, "DICE_NUM");
			//ビットマップの描画
			BITMAP bmp;
			GetObject(g_hDice[g_Dice], sizeof(BITMAP), &bmp);
			hCompDC = CreateCompatibleDC(hDC);
			SelectObject(hCompDC, g_hDice[g_Dice]);
			StretchBlt(hDC, 0, 0, rec.right - rec.left, rec.bottom - rec.top, hCompDC, 0, 0, bmp.bmWidth, bmp.bmHeight, SRCCOPY);
			DeleteDC(hCompDC);
		EndPaint(hWnd, &ps);
		break;
	case WM_CLOSE:
		//ダイスの目のイメージを破棄する
		for(int i = 0; i < 6; i++)
			DeleteObject((HGDIOBJ)g_hDice[i]);
		//ウィンドウプロパティを削除する
		RemoveProp(hWnd, "DICE_NUM");
		DestroyWindow(hWnd);
		break;
	case WM_DESTROY:
		PostQuitMessage(0);
		break;
	default:
		return DefWindowProc(hWnd, Msg, wParam, lParam);
	}
	return 0L;
}

EXPORT bool InitDiceCtrl(HINSTANCE hInstance) {

	//"DICE"ウィンドウクラスの登録
	WNDCLASSEX WndClass;
	//ウィンドウクラスの登録
	WndClass.cbSize		= sizeof(WNDCLASSEX);			//この構造体のサイズ
	WndClass.style		= CS_HREDRAW | CS_VREDRAW;		//縦横移動、サイズ変更時再描画
	WndClass.lpfnWndProc= DiceProc;						//コールバック関数ポインター
	WndClass.cbClsExtra	= 0;							//この構造体以降に置くバイト数
	WndClass.cbWndExtra	= 0;							//インスタンス以降に置くバイト数
	WndClass.hInstance	= hInstance;					//このウィンドウのインスタンス
	WndClass.hIcon		= NULL;							//このウィンドウクラスのアイコン
	WndClass.hCursor	= LoadCursor(NULL, IDC_ARROW);	//このウィンドウクラスのカーソル
	WndClass.hbrBackground = (HBRUSH)WHITE_BRUSH;		//このウィンドウクラスの背景色
	WndClass.lpszMenuName	= NULL;						//このウィンドウクラスのメニュー
	WndClass.lpszClassName	= "DICE";					//このウィンドウクラスの名称
	WndClass.hIconSm	= NULL;							//最小化時の小さいアイコン
	if(!RegisterClassEx(&WndClass)) {
		MessageBox(NULL, "ウィンドウを登録できませんでした。", "エラー", MB_OK | MB_ICONEXCLAMATION);
		return FALSE;
	}
	return TRUE;
}
