/////////////////////////////////////////////
//Canvasを改造したPictureBoxクラス（CPICBOX）
//ダイアログコントロールに使用すると重宝する
//【使い方】
//１．グローバル変数に使いたいだけ宣言する
//２．＜プロジェクト.cpp＞ファイルのWinMain
//    でModelessダイアログを作る前にRegister
//    関数を呼ぶ
//３．WM_INITDIALOG（OnInit関数）でこのクラス
//    のInit関数を呼ぶ
//４．後はCanvasと同じ関数がPICTUREBOXコント
//    ロールで使えるようになる
//５．PICTUREBOX内ののマウス情報はWM_NOTIFY
//    を使い、
//   １）nmhdr.hwndFromはウィンドウハンドル
//   ２）nmhdr.codeでマウスメッセージを受け、
//   ３）wParamはマウス座標を送り
//   ４）マウス情報(wParam)はnmhdr.idFromで送る
/////////////////////////////////////////////
class CPICBOX : public CANVAS
{
public:
	HWND		m_hParent;		//PictureBoxコントロールの親ウィンドウハンドル
	HINSTANCE	m_hInstance;	//親ウィンドウのインスタンス

	CPICBOX();					//コンストラクター
	bool Register(HINSTANCE);	//"PICTUREBOX"ウィンドウクラス登録
	bool Init(HWND, int);		//初期化（含むコールバック関数の設定）
	HWND GethWnd() {return m_hWnd;}	//ウィンドウハンドルを取得
	static LRESULT CALLBACK DummyProc(HWND, UINT, WPARAM, LPARAM);	//ダミーのコールバック関数
	virtual LRESULT CALLBACK PicBoxProc(HWND, UINT, WPARAM, LPARAM);//本来のコールバック関数
};

//コンストラクター
CPICBOX::CPICBOX() {

	m_hParent	= 0;			//親ウィンドウ
	m_hInstance	= 0;			//親のインスタンス
}

//"PICTUREBOX"ウィンドウクラスの登録
bool CPICBOX::Register(HINSTANCE hInstance) {

	WNDCLASS wc;
	wc.style			= CS_HREDRAW | CS_VREDRAW;
	wc.lpfnWndProc		= this->DummyProc;	//ダミーコールバック関数
	wc.cbClsExtra		= 0;
	wc.cbWndExtra		= 0;
	wc.hInstance		= m_hInstance = hInstance;
	wc.hIcon			= NULL;
	wc.hCursor			= LoadCursor(NULL, IDC_CROSS);
	wc.hbrBackground	= (HBRUSH)GetStockObject(WHITE_BRUSH);
	wc.lpszMenuName		= NULL;
	wc.lpszClassName	= "PICTUREBOX";

	return RegisterClass(&wc);
}

//PICTUREBOXコントロールの初期化（含むコールバック関数の設定）
bool CPICBOX::Init(HWND hParent, int ID) {

	if(!hParent) {
		MessageBox(NULL, "ウィンドウハンドルが指定されていません",
					"エラー", MB_OK | MB_ICONEXCLAMATION);
		return FALSE;
	}
	m_hWnd = GetDlgItem(m_hParent = hParent, ID);	//ウィンドウハンドルを記録
	//ウィンドウプロパティにこのクラスのインスタンスへのポインターを書込む（重要）
	SetProp(m_hWnd, "CPP_CLASS", (HANDLE)this);
	HDC hDC = GetDC(m_hWnd);						//対象ウィンドウのDCを取得
	m_hDC = CreateCompatibleDC(hDC);				//コンパチＤＣを作成
	m_Left = m_Top = 0;								//フルスクリーンに拡大した
	m_Right = GetSystemMetrics(SM_CXFULLSCREEN);	//時のキャンヴァスサイズを
	m_Bottom = GetSystemMetrics(SM_CYFULLSCREEN);	//記録しておく

	m_hCanvas = CreateCompatibleBitmap(hDC,			//m_hDCではないので注意
				m_Right,							//m_hDCにするとモノクロとなる
				m_Bottom);
	SelectObject(m_hDC, m_hCanvas);					//キャンヴァスの実体
//	m_Pen = (HPEN)GetStockObject(BLACK_PEN);
	m_PStyle = PS_SOLID;							//ソリッドペン
	m_PWidth = 0;									//1ピクセル
//	m_Brush = (HBRUSH)GetStockObject(WHITE_BRUSH);
	m_Color = RGB(0, 0, 0);							//黒
	PatBlt(m_hDC, m_Left, m_Top, m_Right, m_Bottom, PATCOPY);	//初期描画
	ReleaseDC(m_hWnd, hDC);							//hDCを開放
	m_Focus = FALSE;								//DragRectフラグの初期化
	m_hFont = 0;									//m_hFontの初期化

	return TRUE;
}

//ダミーコールバック関数
LRESULT CALLBACK CPICBOX::DummyProc(HWND hWnd, UINT Message, WPARAM wParam, LPARAM lParam) {

	//Initメンバー関数が書き込んだこのクラスのインスタンスへのポインターを読む
	CPICBOX* pPicBox = (CPICBOX*)GetProp(hWnd, "CPP_CLASS");
	//もしそれが読み込めたら
	if(pPicBox) {
		//本来のコールバック関数（PicBoxProc）を呼ぶ
		LRESULT lResult = pPicBox->PicBoxProc(hWnd, Message, wParam, lParam);
		//ウィンドウ破壊時にウィンドウプロパティを廃棄する
		if(Message == WM_DESTROY)
			RemoveProp(hWnd, "CPP_CLASS");
		return lResult;
	}
	else
		//ウィンドウズの処理に任せる
		return DefWindowProc(hWnd, Message, wParam, lParam);
}

//本来のコールバック関数（仮想関数）
LRESULT CALLBACK CPICBOX::PicBoxProc(HWND hWnd, UINT Message, WPARAM wParam, LPARAM lParam) {

	static NMHDR nmhdr;
	switch(Message) {
		//全てのマウス情報を送る
		case WM_LBUTTONDOWN:
		case WM_LBUTTONUP:
		case WM_LBUTTONDBLCLK:
		case WM_MBUTTONDOWN:
		case WM_MBUTTONUP:
		case WM_MBUTTONDBLCLK:
		case WM_RBUTTONDOWN:
		case WM_RBUTTONUP:
		case WM_RBUTTONDBLCLK:
		case WM_MOUSEMOVE:
			nmhdr.hwndFrom = hWnd;
			nmhdr.idFrom = (UINT)wParam;	//マウス情報を送る
			nmhdr.code = Message;
			//nmhdr.codeでマウスメッセージを、
			//nmhdr.idFromでwParamをまま送り
			//座標情報(lParam)はwParam(32bit長)で送る
			SendMessage(m_hParent, WM_NOTIFY, lParam, (LPARAM)&nmhdr);
			break;
		case WM_PAINT:
			PAINTSTRUCT paint;
			OnPaint(BeginPaint(hWnd, &paint));
			EndPaint(hWnd, &paint);
			break;
		default:
			return DefWindowProc(hWnd, Message, wParam, lParam);
	}
	return 0;
}
