// 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(char *ClassName, 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 = ClassName;
    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){
	RECT rcClient;

	pThisObject = this;

	SetRect(&rcClient, 0, 0, nWidth, nHeight);
	AdjustWindowRectEx(&rcClient, dwStyle, 
		(!(dwStyle & WS_CHILD)) && (hMenu != NULL),  dwExStyle);

	hWnd = ::CreateWindowEx(
		dwExStyle, GetClassName(), lpWindowName, 
		dwStyle, 
		x, y,
		rcClient.right - rcClient.left,
		rcClient.bottom - rcClient.top, 
		*pParent, hMenu, hInstance, NULL);

	return hWnd != NULL;
}

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

//////////////////////////////////////////////////////////////////////
// Window Procedure
//////////////////////////////////////////////////////////////////////

LRESULT cWindow::DefProc(UINT msg, WPARAM w, LPARAM l){
	switch(msg){
	case WM_DESTROY:
		hWnd = NULL;
		break;
	}
	return ::DefWindowProc(hWnd, msg, w, l); 
}

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);
}

void cWindow::ClientToScreen(LPRECT prc){
	::ClientToScreen(hWnd, LPPOINT(prc));
	::ClientToScreen(hWnd, LPPOINT(prc) + 1);
}

void cWindow::ScreenToClient(LPRECT prc){
	::ScreenToClient(hWnd, LPPOINT(prc));
	::ScreenToClient(hWnd, LPPOINT(prc) + 1);
}


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

	hwnd = hWnd;

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


BOOL TextOut(HDC hdc, int x, int y, LPCTSTR str){
	return TextOut(hdc, x, y, str, lstrlen(str));
}

