//////////////////////////////////////////
// PaintBoxProc.h
// Copyright (c) 05/02/2022 by BCCSkelton
//////////////////////////////////////////

/////////////////////////////////
//主ウィンドウCMyWndの関数の定義
//ウィンドウメッセージ関数
/////////////////////////////////
bool CMyWnd::OnInit(WPARAM wParam, LPARAM lParam) {

	//PICTUREBOXの初期化
	PicBox.Init(m_hWnd, IDC_PICBOX);
	MessageBox(m_hWnd, "画面を消去するにはマウス左ボタンを押してください。\n"\
				"またマウス右ボタンを押すとメニューが出ます。",
				"操作方法", MB_OK | MB_ICONINFORMATION);
	return TRUE;
}

bool CMyWnd::OnClose(WPARAM wParam, LPARAM lParam) {

	if(MessageBox(m_hWnd, "終了しますか", "終了確認",
					MB_YESNO | MB_ICONINFORMATION) == IDYES)
		//処理をするとDestroyWindow、PostQuitMessageが呼ばれる
		return TRUE;
	else
		//そうでなければウィンドウではDefWindowProc関数をreturn、ダイアログではreturn FALSEとなる。
		return FALSE;
}

bool CMyWnd::OnNotify(WPARAM wParam, LPARAM lParam) {

	//PICTUREBOX内のマウス情報はWM_NOTIFYを使い、
	//１）nmhdr.hwndFromはウィンドウハンドル
	//２）nmhdr.codeでマウスメッセージを受け、
	//３）wParamはマウス座標を送り
	//４）マウス情報(wParam)はnmhdr.idFromで送る
	NMHDR* lpnmhdr = (NMHDR*)lParam;
	if(lpnmhdr->code == WM_LBUTTONDOWN) {
		PicBox.Color(15);
		PicBox.Clear();
	}
	else if(lpnmhdr->code == WM_RBUTTONDOWN) {
		//ポップアップメニューの読込
		HMENU hMenu = LoadMenu(m_hInstance, "IDM_POPUP");
		HMENU hPopupMenu = GetSubMenu(hMenu, 0);
		//ウインドウの位置情報を取得
		RECT rec;
		GetWindowRect(m_hWnd, &rec);
		//ポップアップメニューの表示場所を設定
		POINT pt;
		GetCursorPos(&pt);
		//ポップアップメニューの表示
		TrackPopupMenu(hPopupMenu, TPM_LEFTALIGN | TPM_TOPALIGN | TPM_LEFTBUTTON, pt.x, pt.y, 0, m_hWnd, &rec);
		//注：このままではポップアップメニューのメニューアイテムを選んだ後も、メニューが消えないので
		//　　IDC_PICBOXコントロールの座標(0, 0)でマウスの左ボタンが押されたように見せかける。
		SendItemMsg(IDC_PICBOX, WM_LBUTTONDOWN, MK_LBUTTON, 0);
		//ポップアップメニューの開放
		DestroyMenu(hMenu);
	}
	return TRUE;
}

//ダイアログベースの場合はこれが必要
bool CMyWnd::OnDestroy(WPARAM wPram, LPARAM lParam) {

	PostQuitMessage(0);
	return TRUE;
}

/////////////////////////////////
//主ウィンドウCMyWndの関数の定義
//メニュー項目、コントロール関数
/////////////////////////////////
bool CMyWnd::OnRect() {

	//16色の正方形の重ね描画
	for(int i = 0; i < 16; i++) {
		PicBox.Color(i);
		PicBox.Box(10 + i * 10, 10 + i * 10, 320 - i * 10, 320 - i * 10, 1);
	}
	return TRUE;
}

bool CMyWnd::OnSpiral() {

	//「新Visual Basic入門」P309より移植
	int xo = 150, yo = 200;
	double deg;
	double x, y = 100, r_large = 100, r_small = 60, shift = 0;
	for(deg = 0; deg < 360 * 3; deg += 3) {
		x = r_large * cos(deg * g_RAD);
		y = r_large * sin(deg * g_RAD);
		x += xo + shift++;
		y += yo;
		PicBox.Color(1);
		PicBox.Ellipsed(x - r_small, y - r_small, x + r_small, y + r_small, 1);
		PicBox.Color(15);
		PicBox.Ellipsed(x - r_small + 1, y - r_small + 1, x + r_small - 1, y + r_small - 1, 1);
		if(deg > 360 * 2)
			r_small *= 0.98;
	}
	return TRUE;
}

bool CMyWnd::OnHirbelt() {

	//「新Visual Basic入門」P311より移植−ヒルベルト曲線
	int x, y, ct, size = 256;		// 描画全体サイズ（16 ^ 3）
	int len, d;
	char str[128];
	for(ct = 1; ct < 7; ct++) {		// 位相1, 2までは正常
		PicBox.Color(15);
		PicBox.Clear();
		len = size / pow((float)2, ct);	//線の長さ
		x = size - size / pow((float)2, ct + 1);
		y = size / pow((float)2, ct + 1);
		d = 270;					//向き角度
		DrawA(ct - 1, x, y, d, len);//Starting drawing
		UpdateWindow(m_hWnd);//再描画命令
		Sleep(500);
	}
	return TRUE;
}

bool CMyWnd::OnTree() {

	int n = 4, m;
	double len = g_LEN, th = 180 / 2, deg = 180 / n, x = g_XSIZE / 2, y = g_YSIZE / 3;
	PicBox.Color(4);
	PicBox.Line(x, g_YSIZE, x, g_YSIZE - y);	//Initial main branch
	Tree(x, y, len, th, deg);
	return TRUE;
}

bool CMyWnd::OnRotate() {

	int m, n, i, j, len = 150, x1, y1, x2, y2;
	double PAI = 3.14159, th, th1, th2;
	for (n = m = 5; n < 15; m++, n++) {
		PicBox.Color(15);
		PicBox.Clear();
		PicBox.Color(3);
		for(i = 0; i < m; i++) {
			for(j = 1; j < n; j++) {
				th = j * (PAI / n);
				th1 = i * (PAI / m) + th;
				th2 = i * (PAI / m) - th;
				x1 = cos(th1) * len + 200;
				y1 = sin(th1) * len + 200;
				x2 = cos(th2) * len + 200;
				y2 = sin(th2) * len + 200;
				PicBox.Line(x1, y1, x2, y2);
			}
		}
		UpdateWindow(m_hWnd);//再描画命令
		Sleep(500);
	}
	return TRUE;
}

bool CMyWnd::OnSphere1() {

	int const RADIUS = 150, XBASE =200, YBASE = 200;
	double x, y, z, x2, y2, degz, degy;
	PicBox.Color(8);
	for(degz = -90; degz <= 90; degz += 10) {
		x = RADIUS * cos(degz * g_RAD);
		y = RADIUS * sin(degz * g_RAD);
		for(degy = 0; degy <= 360; degy++) {
			x2 = x * cos(degy * g_RAD);
			z = x * sin(degy * g_RAD);
			y2 = y * cos(30 * g_RAD) + z * cos(60 * g_RAD);
			PicBox.Dot(XBASE + x2, YBASE + y2);
		}
	}
	for(degy = 0; degy <= 180; degy += 10) {
		for(degz = -90; degz <= 270; degz++) {
			x = RADIUS * cos(degz * g_RAD);
			y = RADIUS * sin(degz * g_RAD);
			x2 = x * cos(degy * g_RAD);
			z = x * sin(degy * g_RAD);
			y2 = y * cos(30 * g_RAD) + z * cos(60 * g_RAD);
			PicBox.Dot(XBASE + x2, YBASE + y2);
		}
	}
	return TRUE;
}

bool CMyWnd::OnSphere2() {

	int const RADIUS = 150, XBASE =200, YBASE = 200;
	int const R2 = 150 * 149;
	double x, y, z, x2, y2, degz, degy;
	int Draw, InsideFlag;
	for(degz = 90; degz >= -90; degz -= 10) {
		x = RADIUS * cos(degz * g_RAD);
		y = RADIUS * sin(degz * g_RAD);
		for(degy = -90; degy <= 90; degy += 0.5) {
			x2 = x * cos(degy * g_RAD);
			z = x * sin(degy * g_RAD);
			y2 = y * cos(30 * g_RAD) + z * cos(60 * g_RAD);
			if(degz >= -50) {
				PicBox.Color(15);
				PicBox.Line(XBASE - x2, y2 + YBASE, XBASE + x2, y2 + YBASE);
			}
			PicBox.Color(5);
			PicBox.Dot(XBASE + x2, YBASE + y2);
			PicBox.Dot(XBASE - x2, YBASE + y2);
		}
	}
	for(degy = 0; degy <= 180; degy += 10) {
		Draw = InsideFlag = TRUE;
		for(degz = -90; degz <= 270; degz += 0.5) {
			x = RADIUS * cos(degz * g_RAD);
			y = RADIUS * sin(degz * g_RAD);
			x2 = x * cos(degy * g_RAD);
			z = x * sin(degy * g_RAD);
			y2 = y * cos(30 * g_RAD) + z * cos(60 * g_RAD);
			if((x2 * x2 + y2 * y2) >= R2) {
				if(InsideFlag == TRUE)
					Draw = !Draw;
				InsideFlag = FALSE;
			}
			else
				InsideFlag = TRUE;
			if(Draw == TRUE || InsideFlag == FALSE) {
				PicBox.Color(5);
				PicBox.Dot(XBASE + x2, YBASE + y2);
			}
		}
	}
	return TRUE;
}

bool CMyWnd::OnExit() {

	SendMsg(WM_CLOSE, 0, 0);
	return TRUE;
}

///////////////////
//ユーザー定義関数
///////////////////
bool CMyWnd::DrawA(int ct, int& x, int& y, int d, int len) {
	if((ct) < 0)
		return FALSE;
	d -= 90; DrawB(ct - 1, x, y, d, len); Drawline(x, y, d, len);
	d += 90; DrawA(ct - 1, x, y, d, len); Drawline(x, y, d, len);
	DrawA(ct - 1, x, y, d, len); d += 90; Drawline(x, y, d, len);
	DrawB(ct - 1, x, y, d, len); d -= 90;
	return TRUE;
}

bool CMyWnd::DrawB(int ct, int& x, int& y, int d, int len) {
	if(ct < 0)
		return FALSE;
	d += 90; DrawA(ct - 1, x, y, d, len); Drawline(x, y, d, len);
	d -= 90; DrawB(ct - 1, x, y, d, len); Drawline(x, y, d, len);
	DrawB(ct - 1, x, y, d, len); d -= 90; Drawline(x, y, d, len);
	DrawA(ct - 1, x, y, d, len); d += 90;
	return TRUE;
}

void CMyWnd::Drawline(int& x, int& y, int& d, int len) {
	int oldx = x, oldy = y;
	if(d < 0)
		d += 360;
	if(d >= 360)
		d -= 360;
	switch(d) {
	case   0: x += len; break;
	case  90: y -= len; break;
	case 180: x -= len; break;
	case 270: y += len; break;
	}
	PicBox.Color(2);
	PicBox.Line(oldx, oldy, x, y);
}

bool CMyWnd::Tree(double x, double y, double len, double th, double deg) {
	double x1, y1, x2, y2, th1, th2;
	if(len <= g_LEN / 15)
		return FALSE;
	len *= 0.75;
	th1 = th - deg;
	th2 = th + deg;
	x1 = x + len * cos(th1 * g_RAD);
	y1 = y + len * sin(th1 * g_RAD);
	x2 = x + len * cos(th2 * g_RAD);
	y2 = y + len * sin(th2 * g_RAD);
	PicBox.Color(4);
	PicBox.Line(x, g_YSIZE - y, x1, g_YSIZE - y1);    //Right branch
	Tree(x1, y1, len, th1, deg);
	PicBox.Line(x, g_YSIZE - y, x2, g_YSIZE - y2);    //Left branch
	Tree(x2, y2, len, th2, deg);
	return TRUE;
}
