// cWindow.cpp: implementation of the cWindow class.
//
//////////////////////////////////////////////////////////////////////

#include "cWindow.h"

// 정적 멤버를 초기화 한다.
cWindow *cWindow::pThisObject = NULL;
HINSTANCE cWindow::hInstance = NULL;
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

cWindow::cWindow(){
	hWnd = NULL;
}

cWindow::~cWindow(){
	Destroy();
}

//////////////////////////////////////////////////////////////////////
// Window Creation
//////////////////////////////////////////////////////////////////////

BOOL cWindow::RegisterClass(DWORD Style, HICON hIcon, 
				   HCURSOR hCursor, HBRUSH hbrBackground, 
				   LPCTSTR lpszMenuName){
	WNDCLASSEX wc;

	wc.cbSize = sizeof(WNDCLASSEX);
	wc.style = Style;
	wc.lpfnWndProc = DefaultProc;
	wc.cbClsExtra = 0;
	wc.cbWndExtra = 0;
	wc.hInstance = hInstance;
	wc.hIcon = hIcon;
	wc.hCursor = hCursor;
	wc.hbrBackground = hbrBackground;
	wc.lpszMenuName = lpszMenuName;
	wc.lpszClassName = GetClassName();
    wc.hIconSm = hIcon;

	return RegisterClassEx(&wc) != 0;
}

//////////////////////////////////////////////////////////////////////
// Window Creation
//////////////////////////////////////////////////////////////////////

BOOL cWindow::Create(DWORD dwExStyle, LPCTSTR lpWindowName, 
	DWORD dwStyle, int x, int y, int nWidth, int nHeight, 
	cWindow *pParent, HMENU hMenu){

	if(!IsClassRegistered())
		if(!RegisterClass()) return NULL;

	pThisObject = this;
	hWnd = ::CreateWindowEx(
		dwExStyle, GetClassName(), lpWindowName, 
		dwStyle, x, y, nWidth, nHeight, 
		*pParent, hMenu, hInstance, NULL);

	return hWnd != NULL;
}

void cWindow::Destroy(){
	if(hWnd){
		::DestroyWindow(hWnd);
		hWnd = NULL;
	}
}
//////////////////////////////////////////////////////////////////////
// Window Procedure
//////////////////////////////////////////////////////////////////////

LRESULT CALLBACK cWindow::DefaultProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam){
// * 정적 멤버 함수이므로 정적 멤버에만 접근할 수 있다.
// 윈도우 핸들을 처리하는 cWindow객체를 찾아 WindowProc를 호출해 준다.
	cWindow *pObj;
	
	pObj = (cWindow *)::GetWindowLong(hWnd, GWL_USERDATA);
	if(pObj == NULL){ // 객체가 처음 생성 되었을 경우
		SetWindowLong(hWnd, GWL_USERDATA, (LONG)pThisObject);
		pObj = pThisObject;
		pObj->hWnd = hWnd;
	}
	return pObj->Proc(uMsg, wParam, lParam);
}



//////////////////////////////////////////////////////////////////////
// Window Size and Position
//////////////////////////////////////////////////////////////////////
/*
SIZE cWindow::GetNormalClientSize(){
// 윈도우가 최소화 되었을 경우는 GetClientRect로는 
// 윈도우의 원래 크기를 얻을 수 없으므로 
// AdjustWindowRectEx 함수를 이용한다.
	WINDOWPLACEMENT wndpl;
	RECT rcWindow, rcRequired;
	SIZE sz;

	// 윈도우의 본래 위치를 파악한다.
	wndpl.length = sizeof(WINDOWPLACEMENT);
	GetWindowPlacement(hWnd, &wndpl);
	rcWindow = wndpl.rcNormalPosition;
	rcRequired = rcWindow;
	// required 에 window가 클라이언트일 경우 필요한 윈도우의 크기를 기록
	AdjustWindowRectEx(&rcRequired, GetWindowLong(hWnd, GWL_STYLE),
		FALSE, GetWindowLong(hWnd, GWL_EXSTYLE));
	sz.cx = rcWindow.right - (rcRequired.right - rcWindow.right)
		- (rcWindow.left + rcWindow.left - rcRequired.left);
	sz.cy = rcWindow.bottom - (rcRequired.bottom - rcWindow.bottom)
		- (rcWindow.top + rcWindow.top - rcRequired.top);

	return sz;
}
*/
//////////////////////////////////////////////////////////////////////
// Static Window Operations
//////////////////////////////////////////////////////////////////////
cWindow *cWindow::GetTopLevelParent(){
	HWND hwnd;

	hwnd = hWnd;

	while(::GetParent(hwnd)) 
		hwnd = ::GetParent(hwnd);
	return GetWindow(hwnd);
}

