#include "stdafx.h"

#define OWN__SIZEDLG__

#include "sizedlg.h"

SIZEDLG::~SIZEDLG()
{
	hDlg = NULL;
	if ( dlgitemdata ) {
		delete[] dlgitemdata;
		dlgitemdata = NULL;
	}
}

bool SIZEDLG::Create(HWND hWnd, const DLGITEM *dlgitems)
{
	RECT  rc, rcdlg, rcdlg0;	// コントロールやダイアログのサイズを得る
	POINT po1, po2;				// ScreenToClient座標系変換
	int   n;					// dlgitemsに与えられた数をカウント

	// 引数に関するエラーチェック
	if ( hWnd == NULL || dlgitems == NULL ) {
		return false;
	}

	// ダイアログのハンドルをコピー
	hDlg = hWnd;

	// 構造体初期化
	if ( dlgitemdata ) {
		delete[] dlgitemdata;
		dlgitemdata = NULL;
	}

	// 引数dlgitemsの要素数を数え、dlgitemdataのメモリを確保
	for(n = 0; dlgitems[n].iCtrl != 0; ++n)
		;
	++n;
	dlgitemdata = new DLGITEMDATA[n];
	ZeroMemory(dlgitemdata, sizeof(DLGITEMDATA)*n);

	// ダイアログのクライアント領域に関する座標情報の取得
	GetClientRect(hDlg, &rcdlg);

	// ダイアログ自体に関する座標情報の取得
	// （ダイアログの初期サイズが、デフォルトの最小サイズ）
	GetWindowRect(hDlg, &rcdlg0);
	defwidth  = minwidth  = rcdlg0.right  - rcdlg0.left;
	defheight = minheight = rcdlg0.bottom - rcdlg0.top;
	maxwidth  = maxheight = -1; // 初期の最大サイズは未定義

	// アイテムのハンドルをコピー。また各種座標情報を生成
	for(n = 0; dlgitems[n].iCtrl != 0; ++n) {
		// アイテムとアンカー情報をコピー
		dlgitemdata[n].hItem = GetDlgItem(hWnd, dlgitems[n].iCtrl);
		dlgitemdata[n].anchor = dlgitems[n].anchor;

		// アイテムが存在したならば処理を開始
		if ( dlgitemdata[n].hItem ) {
			// アイテムの、ダイアログ左上からの座標に関する情報の取得
			GetWindowRect(dlgitemdata[n].hItem, &rc);
			po1.x = rc.left;
			po1.y = rc.top;
			ScreenToClient(hDlg, &po1);

			// アイテムの、ダイアログ右下からの座標に関する情報の取得
			po2.x = rc.right;
			po2.y = rc.bottom;
			ScreenToClient(hDlg, &po2);

			switch(dlgitems[n].anchor) {
				/*case ANCHOR_TOPLEFT:
					// 特に何もしない
					break;*/

				case ANCHOR_TOPRIGHT:
					// dx:ダイアログ右とアイテム左の差を記憶
					dlgitemdata[n].dx = rcdlg.right - po1.x;
					// dy:Y座標を記憶
					dlgitemdata[n].dy = po1.y;
					break;

				case ANCHOR_BOTTOMLEFT:
					// dx:X座標を記憶
					dlgitemdata[n].dx = po1.x;
					// dy:ダイアログ下とアイテム上の差を記憶
					dlgitemdata[n].dy = rcdlg.bottom - po1.y;
					break;

				case ANCHOR_BOTTOMRIGHT:
					// dx:ダイアログ右とアイテム左の差を記憶
					dlgitemdata[n].dx = rcdlg.right - po1.x;
					// dy:ダイアログ下とアイテム上の差を記憶
					dlgitemdata[n].dy = rcdlg.bottom - po1.y;
					break;

				case ANCHOR_TOPLEFTRIGHT:
					// dx:ダイアログの幅とアイテムの幅の差を記憶
					dlgitemdata[n].dx = (rcdlg.right - rcdlg.left) - (rc.right - rc.left);
					// dy:アイテムの高さを記憶
					dlgitemdata[n].dy = po2.y - po1.y;
					break;

				case ANCHOR_CENTER:
					// dx:ダイアログの幅とアイテムの幅の差を記憶
					dlgitemdata[n].dx = (rcdlg.right - rcdlg.left) - (rc.right - rc.left);
					// dy:ダイアログの高さとアイテムの高さの差を記憶
					dlgitemdata[n].dy = (rcdlg.bottom - rcdlg.top) - (rc.bottom - rc.top);
					break;

				case ANCHOR_BOTTOMLEFTRIGHT:
					// dx:ダイアログの幅とアイテムの幅の差を記憶
					dlgitemdata[n].dx = (rcdlg.right - rcdlg.left) - (rc.right - rc.left);
					// dy:ダイアログ下とアイテム上の差を記憶
					dlgitemdata[n].dy = rcdlg.bottom - po1.y;
					// dx2:アイテムのX座標を記憶
					dlgitemdata[n].dx2 = po1.x;
					// dy2:アイテムの高さを記憶
					dlgitemdata[n].dy2 = po2.y - po1.y;
					break;
			}
		}
	}

	// 最終データのマークを挿入
	dlgitemdata[n].anchor = ANCHOR_END;

	return true;
}

bool SIZEDLG::Add(HWND hItem, unsigned char anchor)
{
	if (!hItem) {
		return false;
	}

	int n, m;
	// 要素数をカウント
	for(n=0 ; dlgitemdata[n].anchor != ANCHOR_END ; ++n) {
		if (dlgitemdata[n].hItem == hItem) {
			// 登録済みだったら異常終了
			return false;
		}
	}
	m = n + 2;
	DLGITEMDATA *temp_dlgitemdata = new DLGITEMDATA[m];
	if (!temp_dlgitemdata) {
		return false;
	}
	
	memcpy(temp_dlgitemdata, dlgitemdata, sizeof(DLGITEMDATA)*n);
	temp_dlgitemdata[n].hItem = hItem;
	temp_dlgitemdata[n].anchor = anchor;

	delete dlgitemdata;
	dlgitemdata = temp_dlgitemdata;

	RECT  rcdlg, rc;
	POINT po1, po2;

	// ダイアログのクライアント領域に関する座標情報の取得
	GetClientRect(hDlg, &rcdlg);

	// アイテムの、ダイアログ左上からの座標に関する情報の取得
	GetWindowRect(dlgitemdata[n].hItem, &rc);
	po1.x = rc.left;
	po1.y = rc.top;
	ScreenToClient(hDlg, &po1);

	// アイテムの、ダイアログ右下からの座標に関する情報の取得
	po2.x = rc.right;
	po2.y = rc.bottom;
	ScreenToClient(hDlg, &po2);

	switch(anchor) {
		/*case ANCHOR_TOPLEFT:
			// 特に何もしない
			break;*/

		case ANCHOR_TOPRIGHT:
			// dx:ダイアログ右とアイテム左の差を記憶
			dlgitemdata[n].dx = rcdlg.right - po1.x;
			// dy:Y座標を記憶
			dlgitemdata[n].dy = po1.y;
			break;

		case ANCHOR_BOTTOMLEFT:
			// dx:X座標を記憶
			dlgitemdata[n].dx = po1.x;
			// dy:ダイアログ下とアイテム上の差を記憶
			dlgitemdata[n].dy = rcdlg.bottom - po1.y;
			break;

		case ANCHOR_BOTTOMRIGHT:
			// dx:ダイアログ右とアイテム左の差を記憶
			dlgitemdata[n].dx = rcdlg.right - po1.x;
			// dy:ダイアログ下とアイテム上の差を記憶
			dlgitemdata[n].dy = rcdlg.bottom - po1.y;
			break;

		case ANCHOR_TOPLEFTRIGHT:
			// dx:ダイアログの幅とアイテムの幅の差を記憶
			dlgitemdata[n].dx = (rcdlg.right - rcdlg.left) - (rc.right - rc.left);
			// dy:アイテムの高さを記憶
			dlgitemdata[n].dy = po2.y - po1.y;
			break;

		case ANCHOR_CENTER:
			// dx:ダイアログの幅とアイテムの幅の差を記憶
			dlgitemdata[n].dx = (rcdlg.right - rcdlg.left) - (rc.right - rc.left);
			// dy:ダイアログの高さとアイテムの高さの差を記憶
			dlgitemdata[n].dy = (rcdlg.bottom - rcdlg.top) - (rc.bottom - rc.top);
			break;

		case ANCHOR_BOTTOMLEFTRIGHT:
			// dx:ダイアログの幅とアイテムの幅の差を記憶
			dlgitemdata[n].dx = (rcdlg.right - rcdlg.left) - (rc.right - rc.left);
			// dy:ダイアログ下とアイテム上の差を記憶
			dlgitemdata[n].dy = rcdlg.bottom - po1.y;
			// dx2:アイテムのX座標を記憶
			dlgitemdata[n].dx2 = po1.x;
			// dy2:アイテムの高さを記憶
			dlgitemdata[n].dy2 = po2.y - po1.y;
			break;
	}
	
	// 最終データのマークを挿入
	dlgitemdata[n+1].hItem  = 0;
	dlgitemdata[n+1].anchor = ANCHOR_END;

	return true;
}

bool SIZEDLG::Add(HWND hWnd, int iItem, unsigned char anchor)
{
	return Add(GetDlgItem(hWnd, iItem), anchor);
}

bool SIZEDLG::Resize(bool bRedraw)
{
	if ( hDlg ) {
		RECT rcdlg;
		int  n;

		// 新しいダイアログサイズを取得
		GetClientRect(hDlg, &rcdlg);

		for(n=0; dlgitemdata[n].anchor != ANCHOR_END ; ++n) {
			if (dlgitemdata[n].hItem) {
				switch(dlgitemdata[n].anchor) {
					case ANCHOR_TOPRIGHT:
						// dx:ダイアログ右とアイテム左の差を記憶している
						// dy:Y座標を記憶している
						SetWindowPos(dlgitemdata[n].hItem, 0, rcdlg.right - dlgitemdata[n].dx, dlgitemdata[n].dy, 0, 0, SWP_NOSIZE | SWP_NOZORDER);
						break;

					case ANCHOR_BOTTOMLEFT:
						// dx:X座標を記憶している
						// dy:ダイアログ下とアイテム上の差を記憶している
						SetWindowPos(dlgitemdata[n].hItem, 0, dlgitemdata[n].dx, rcdlg.bottom - dlgitemdata[n].dy, 0, 0, SWP_NOSIZE | SWP_NOZORDER);
						break;

					case ANCHOR_BOTTOMRIGHT:
						// dx:ダイアログ右とアイテム左の差を記憶している
						// dy:ダイアログ下とアイテム上の差を記憶している
						SetWindowPos(dlgitemdata[n].hItem, 0, rcdlg.right - dlgitemdata[n].dx, rcdlg.bottom - dlgitemdata[n].dy, 0, 0, SWP_NOSIZE | SWP_NOZORDER);
						break;

					case ANCHOR_TOPLEFTRIGHT:
						// dx:ダイアログの幅とアイテムの幅の差を記憶している
						// dy:アイテムの高さを記憶している
						SetWindowPos(dlgitemdata[n].hItem, 0, 0, 0, (rcdlg.right - rcdlg.left) - dlgitemdata[n].dx, dlgitemdata[n].dy, SWP_NOMOVE | SWP_NOZORDER);
						break;

					case ANCHOR_CENTER:
						// dx:ダイアログの幅とアイテムの幅の差を記憶している
						// dy:ダイアログの高さとアイテムの高さの差を記憶している
						SetWindowPos(dlgitemdata[n].hItem, 0, 0, 0, (rcdlg.right - rcdlg.left) - dlgitemdata[n].dx, (rcdlg.bottom - rcdlg.top) - dlgitemdata[n].dy, SWP_NOMOVE | SWP_NOZORDER);
						break;

					case ANCHOR_BOTTOMLEFTRIGHT:
						// dx:ダイアログの幅とアイテムの幅の差を記憶している
						// dy:ダイアログ下とアイテム上の差を記憶している
						// dx2:アイテムのX座標を記憶している
						// dy2:アイテムの高さを記憶している
						SetWindowPos(dlgitemdata[n].hItem, 0, dlgitemdata[n].dx2, rcdlg.bottom - dlgitemdata[n].dy, (rcdlg.right - rcdlg.left) - dlgitemdata[n].dx, dlgitemdata[n].dy2, SWP_NOZORDER);
						break;
				}
			}
		}

		if ( bRedraw ) {
			// 画面の再描画
			InvalidateRect(hDlg, NULL, TRUE);
		}

		return true;
	}
	return false;
}

BOOL SIZEDLG::GetMinMaxInfo(LPARAM lParam)
{
	MINMAXINFO *pmmi = (MINMAXINFO *)lParam;

	if ( pmmi ) {
		if ( minwidth != -1 ) {
			pmmi->ptMinTrackSize.x = minwidth;    // 最小幅(ダイアログの最初の幅がデフォルト)
		}
		if ( minheight != -1 ) {
			pmmi->ptMinTrackSize.y = minheight;   // 最小高(ダイアログの最初の高さがデフォルト)
		}
		if ( maxwidth != -1 ) {
			pmmi->ptMaxTrackSize.x = maxwidth;    // 最大幅 - デフォルトは指定なし
		}
		if ( maxheight != -1 ) {
			pmmi->ptMaxTrackSize.y = maxheight;   // 最大高 - デフォルトは指定なし
		}

		return TRUE;
	}
	else {
		return FALSE;
	}
}
