
#include	"stdafx.h"
#include	"Common.h"
#include	"WindowBase.h"

CWindowBase::CWindowBase()
{
	m_hWnd = NULL;
	m_hInst = NULL;
	m_oldWndProc = NULL;
	m_bDialog = FALSE;
}

CWindowBase::~CWindowBase()
{
	RemoveProp(m_hWnd, _T("CWindowBase"));
}

void CWindowBase::Init()
{
	MoveWindowCenter();
}

void CWindowBase::Init(LONG cx, LONG cy)
{
	MoveWindowCenter(cx, cy);
}

void CWindowBase::Init(UINT uID, LONG cx, LONG cy)
{
	m_uID = uID;

	YCIni				clIni( SBL_STR_INI_EXTRACTDATA );

	clIni.SetSection( m_uID );

	RECT rc;
	SetRect(&rc, 0, 0, cx, cy);
	POINT pt = GetCenterPt(rc);

	clIni.SetKey( _T("Left") );
	clIni.ReadDec( &pt.x );
	clIni.SetKey( _T("Top") );
	clIni.ReadDec( &pt.y );
	clIni.SetKey( _T("Width") );
	clIni.ReadDec( &cx );
	clIni.SetKey( _T("Height") );
	clIni.ReadDec( &cy );

	WINDOWPLACEMENT wndpl;

	memset(&wndpl, 0, sizeof(WINDOWPLACEMENT));

	wndpl.length = sizeof(WINDOWPLACEMENT);
	wndpl.showCmd = SW_HIDE;

	SetRect(&wndpl.rcNormalPosition, pt.x, pt.y, pt.x + cx, pt.y + cy);
	SetWindowPlacement(m_hWnd, &wndpl);

	clIni.SetKey( _T("showCmd") );
	clIni.ReadDec<UINT>( &wndpl.showCmd, SW_SHOWNORMAL );

	ShowWindow( m_hWnd, wndpl.showCmd );
}

void CWindowBase::Init(HWND hWnd)
{
	MoveWindowCenter(hWnd);
}

void CWindowBase::Init(HWND hWnd, LONG cx, LONG cy)
{
	MoveWindowCenter(hWnd, cx, cy);
}

void CWindowBase::SaveIni()
{
	YCIni				clIni( SBL_STR_INI_EXTRACTDATA );

	clIni.SetSection( m_uID );

	WINDOWPLACEMENT wndpl;

	wndpl.length = sizeof(WINDOWPLACEMENT);
	GetWindowPlacement(m_hWnd, &wndpl);

	// 位置保存

	clIni.SetKey( _T("Left") );
	clIni.WriteDec( wndpl.rcNormalPosition.left );
	clIni.SetKey( _T("Top") );
	clIni.WriteDec( wndpl.rcNormalPosition.top );

	// サイズ保存

	clIni.SetKey( _T("Width") );
	clIni.WriteDec( wndpl.rcNormalPosition.right - wndpl.rcNormalPosition.left );
	clIni.SetKey( _T("Height") );
	clIni.WriteDec( wndpl.rcNormalPosition.bottom - wndpl.rcNormalPosition.top );

	if( wndpl.showCmd != SW_SHOWMINIMIZED )
	{
		clIni.SetKey( _T("showCmd") );
		clIni.WriteDec( wndpl.showCmd );
	}
}

BOOL CWindowBase::Attach(HWND hWnd)
{
	if (!hWnd)
		return FALSE;
	m_hWnd = hWnd;
	m_hInst = (HINSTANCE)GetWindowLongPtr(hWnd, GWLP_HINSTANCE);
	// ダイアログかウィンドウかを判定
	m_bDialog = GetWindowLong(hWnd, DWL_DLGPROC);
	int tproc = m_bDialog ? DWL_DLGPROC : GWL_WNDPROC;

	SetProp(m_hWnd, _T("CWindowBase"), (HANDLE)this);

	// 既存のウィンドウをサブクラス化
	if (GetWindowLong(m_hWnd, tproc) != (LONG)WndStaticProc)
		m_oldWndProc = (WNDPROC)SetWindowLong(m_hWnd, tproc, (LONG)WndStaticProc);

	return TRUE;
}

BOOL CWindowBase::Detach()
{
	if (!m_hWnd)
		return FALSE;

	// サブクラス化を解除
	if (m_oldWndProc) {
		int tproc = (m_bDialog == TRUE) ? DWL_DLGPROC : GWL_WNDPROC;
		SetWindowLong(m_hWnd, tproc, (DWORD)m_oldWndProc);
	}
	RemoveProp(m_hWnd, _T("CWindowBase"));
	return TRUE;
}

LRESULT CALLBACK CWindowBase::WndStaticProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
{
	// プロパティリストからデータを取得
	CWindowBase* tWnd = (CWindowBase*)GetProp(hWnd, _T("CWindowBase"));

	// 取得できなかったときの処理
	if (tWnd == NULL) {
		if ((msg == WM_CREATE) || (msg == WM_NCCREATE))
			tWnd = (CWindowBase*)((LPCREATESTRUCT)lp)->lpCreateParams;
		else if (msg == WM_INITDIALOG)
			tWnd = (CWindowBase*)lp;
		if (tWnd)
			tWnd->Attach(hWnd);
	}

	// tWndの取得に成功
	if (tWnd) {
		LRESULT lResult = tWnd->WndProc(hWnd, msg, wp, lp);
		if (msg == WM_DESTROY)
			tWnd->Detach();
		return lResult;
	}

	// ダイアログの場合、FALSEを返す
	if (GetWindowLong(hWnd, DWL_DLGPROC))
		return FALSE;

	return DefWindowProc(hWnd, msg, wp, lp);
}

LRESULT CWindowBase::WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
{
	// サブクラス化している場合は、古いウィンドウプロシージャに後の処理を任せる
	if (m_oldWndProc)
		return CallWindowProc(m_oldWndProc, hWnd, msg, wp, lp);
	// ダイアログの場合、FALSEを返す
	if (m_bDialog)
		return FALSE;
	// サブクラス化で無い場合は、デフォルトウィンドウプロシージャを呼び出す
	return DefWindowProc(hWnd, msg, wp, lp);
}

void CWindowBase::MoveWindowCenter()
{
	RECT rc;
	GetWindowRect(m_hWnd, &rc);
	POINT pt = GetCenterPt(rc);
	MoveWindow(m_hWnd, pt.x, pt.y, rc.right - rc.left, rc.bottom - rc.top, TRUE);
}

void CWindowBase::MoveWindowCenter(LONG cx, LONG cy)
{
	RECT rc;
	SetRect(&rc, 0, 0, cx, cy);
	POINT pt = GetCenterPt(rc);
	MoveWindow(m_hWnd, pt.x, pt.y, rc.right - rc.left, rc.bottom - rc.top, TRUE);
}

void CWindowBase::MoveWindowCenter(HWND hWnd)
{
	RECT rc;
	GetWindowRect(hWnd, &rc);
	POINT pt = GetCenterPt(hWnd, rc);
	MoveWindow(hWnd, pt.x, pt.y, rc.right - rc.left, rc.bottom - rc.top, TRUE);
}

void CWindowBase::MoveWindowCenter(HWND hWnd, LONG cx, LONG cy)
{
	RECT rc;
	SetRect(&rc, 0, 0, cx, cy);
	POINT pt = GetCenterPt(hWnd, rc);
	MoveWindow(hWnd, pt.x, pt.y, rc.right - rc.left, rc.bottom - rc.top, TRUE);
}

POINT CWindowBase::GetCenterPt(RECT& dlgrc)
{
	RECT ParentRect;
	HWND hParentWnd = GetParent(m_hWnd);
	if (hParentWnd == NULL)
		hParentWnd = GetDesktopWindow();
	GetWindowRect(hParentWnd, &ParentRect);
	//CError error;
	//error.Message(m_hWnd, _T("%d %d %d %d"), ParentRect.left, ParentRect.top, ParentRect.right, ParentRect.bottom);

	POINT pt;
	pt.x = ParentRect.left + ((ParentRect.right - ParentRect.left) - (dlgrc.right - dlgrc.left)) / 2;
	pt.y = ParentRect.top + ((ParentRect.bottom - ParentRect.top) - (dlgrc.bottom - dlgrc.top)) / 2;
	//error.Message(m_hWnd, _T("%d %d %d %d"), dlgrc.left, dlgrc.top, dlgrc.right, dlgrc.bottom);
	return (pt);
}

POINT CWindowBase::GetCenterPt(HWND hWnd, RECT& dlgrc)
{
	RECT ParentRect;
	HWND hParentWnd = GetParent(hWnd);
	if (hParentWnd == NULL)
		hParentWnd = GetDesktopWindow();
	GetWindowRect(hParentWnd, &ParentRect);
	//CError error;
	//error.Message(m_hWnd, _T("%d %d %d %d"), ParentRect.left, ParentRect.top, ParentRect.right, ParentRect.bottom);

	POINT pt;
	pt.x = ParentRect.left + ((ParentRect.right - ParentRect.left) - (dlgrc.right - dlgrc.left)) / 2;
	pt.y = ParentRect.top + ((ParentRect.bottom - ParentRect.top) - (dlgrc.bottom - dlgrc.top)) / 2;
	//error.Message(m_hWnd, _T("%d %d %d %d"), dlgrc.left, dlgrc.top, dlgrc.right, dlgrc.bottom);
	return (pt);
}