#ifndef cWindow_H
#define cWindow_H

#include <windows.h>

class cWindow{ 
private:
	static cWindow *pThisObject; // 정적 멤버 함수를 위한 객체 포인터

// 애플리케이션 인스턴스 핸들
protected:
	static HINSTANCE hInstance;
	HWND hWnd; 


protected:

	// Overridables
	virtual char *GetClassName() = 0;
	// Do NOT call directly
	static LRESULT CALLBACK DefaultProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
	static BOOL RegisterClass(char *ClassName, DWORD Style, HICON hIcon = NULL, HCURSOR hCursor = NULL, HBRUSH hbrBackground = NULL, LPCTSTR lpszMenuName = NULL);
	virtual LRESULT Proc(UINT uMsg, WPARAM wParam, LPARAM lParam) = 0;

	LRESULT DefProc(UINT msg, WPARAM w, LPARAM l);
	
	// 전역 서비스
	static cWindow *GetWindow(HWND hWnd){ return (cWindow *)GetWindowLong(hWnd, GWL_USERDATA); }

public:

	// 생성자
	cWindow();
	virtual ~cWindow();

	// 창 만들고 없에기
	BOOL Create(DWORD dwExStyle, LPCTSTR lpWindowName, 
		DWORD dwStyle, int x, int y, int nWidth, int nHeight, 
		cWindow *pParentWindow, HMENU hMenu = NULL); 
	virtual void Destroy();

	// 윈도우 속성
	DWORD GetStyle(){ return ::GetWindowLong(hWnd, GWL_STYLE); }
	DWORD GetExStyle(){ return ::GetWindowLong(hWnd, GWL_EXSTYLE); }

	// 윈도우 상태
	BOOL IsEnabled(){ return ::IsWindowEnabled(hWnd); }
	BOOL Enable(BOOL bEnable){ return ::EnableWindow(hWnd, bEnable); }
	static cWindow *GetActiveWindow(){ return GetWindow(::GetActiveWindow()); }
	cWindow *Activate(){ return GetWindow(::SetActiveWindow(hWnd)); }
	static cWindow *GetCapture(){ return GetWindow(::GetCapture()); }
	cWindow *SetCapture(){ return GetWindow(::SetCapture(hWnd)); }
	static cWindow *GetFocus(){ return GetWindow(::GetFocus()); }
	cWindow *SetFocus(){ return GetWindow(::SetFocus(hWnd)); }
	static HWND GetDesktopWindow(){ return ::GetDesktopWindow(); }
	BOOL GetPlacement(WINDOWPLACEMENT *lpwndpl){ return ::GetWindowPlacement(hWnd, lpwndpl); }
	int GetRgn(HRGN hRgn){ return ::GetWindowRgn(hWnd, hRgn); }
	int SetRgn(HRGN hRgn, BOOL bRedraw){ return ::SetWindowRgn(hWnd, hRgn, bRedraw); }
	BOOL IsIconic(){ return ::IsIconic(hWnd); }
	BOOL IsZoomed(){ return ::IsZoomed(hWnd); }
	BOOL OpenIcon(){ return ::OpenIcon(hWnd); }
	BOOL Close(){ return ::CloseWindow(hWnd); }
	BOOL Move(int x, int y, int w, int h, BOOL bRedraw){ return ::MoveWindow(hWnd, x, y, w, h, bRedraw); }
	BOOL SetPos(cWindow *Behind, int x, int y, int cx, int cy, UINT uFlag){ return ::SetWindowPos(hWnd, Behind->hWnd, x, y, cx, cy, uFlag); }
//	UINT ArrangeIconicChilds(){ return ::ArrageIconicWindows(hWnd); }
	BOOL BringToTop(){ return ::BringWindowToTop(hWnd); }
	BOOL GetRect(LPRECT lpRect){ return ::GetWindowRect(hWnd, lpRect); }
	BOOL GetClientRect(LPRECT lpRect){ return ::GetClientRect(hWnd, lpRect); }

	// 윈도우 접근 함수
//	cWindow *ChildFromPoint(POINT pt){ return GetWindow(::ChildWindowFromPoint(hWnd, pt)); }
//	cWindow *FindWindow(LPCTSTR pClassName, LPCTSTR pWindowName){ return GetWindow(){ ::FindWindow(pClassName, pWindowName)) };
//	cWindow *GetNextWindow(
	cWindow *GetParent(){ return GetWindow(::GetParent(hWnd)); }
	cWindow *SetParent(cWindow *pParent){ return GetWindow(::SetParent(hWnd, pParent->hWnd)); }
	cWindow *GetTop(UINT uCmd){ return GetWindow(::GetWindow(hWnd, uCmd)); }
	cWindow *GetWindow(UINT uCmd){ return GetWindow(::GetWindow(hWnd, uCmd)); }
	cWindow *GetLastActivePopup(){ return GetWindow(::GetLastActivePopup(hWnd)); }
	BOOL IsChild(cWindow *pParent){ return ::IsChild(pParent->hWnd, hWnd); }
//	WindowFromPoint
	cWindow *GetItem(int id){ return GetWindow(::GetDlgItem(hWnd, id)); }
	int GetCtrlID(){ return ::GetDlgCtrlID(hWnd); }
	int SetCtrlID(int id){ return ::SetWindowLong(hWnd, GWL_ID, id); }
	cWindow *GetTopLevelParent();

	// 윈도우 그리기
	HDC BeginPaint(LPPAINTSTRUCT pps){ return ::BeginPaint(hWnd, pps); }
	void EndPaint(LPPAINTSTRUCT pps){ ::EndPaint(hWnd, pps); }
	BOOL LockUpdate(){ return ::LockWindowUpdate(hWnd); }
	void UnlockUpdate(){ ::LockWindowUpdate(NULL); }
	HDC GetDC(){ return ::GetDC(hWnd); }
	HDC GetDCEx(HRGN hClipRgn, DWORD flags){ return ::GetDCEx(hWnd, hClipRgn, flags); }
	BOOL Redraw(CONST RECT *prcUpdate, HRGN hUpdateRgn, UINT flags){ return ::RedrawWindow(hWnd, prcUpdate, hUpdateRgn, flags); }
	HDC GetWindowDC(){ return ::GetWindowDC(hWnd); }
	int ReleaseDC(HDC hdc){ return ::ReleaseDC(hWnd, hdc); }
	BOOL Update(){ return ::UpdateWindow(hWnd); }
	BOOL GetUpdateRect(LPRECT prc, BOOL bErase){ return ::GetUpdateRect(hWnd, prc, bErase); }
	int GetUpdateRgn(HRGN hRgn, BOOL bErase){ return ::GetUpdateRgn(hWnd, hRgn, bErase); }
	BOOL Invalidate(BOOL bErase = true){ return ::InvalidateRect(hWnd, NULL, bErase); }
	BOOL InvalidateRect(CONST RECT *prc = NULL, BOOL bErase = true){ return ::InvalidateRect(hWnd, prc, bErase); }
	BOOL InvalidateRgn(HRGN hRgn, BOOL bErase){ return ::InvalidateRgn(hWnd, hRgn, bErase); }
	BOOL ValidateRect(LPRECT lpRect = NULL){ return ::ValidateRect(hWnd, lpRect); }
	BOOL ValidateRgn(HRGN hRgn){ return ::ValidateRgn(hWnd, hRgn); }
	BOOL Show(int nCmdShow){ return ::ShowWindow(hWnd, nCmdShow); }
	BOOL IsVisible(){ return ::IsWindowVisible(hWnd); }
	BOOL ShowOwnedPopups(BOOL fShow){ return ::ShowOwnedPopups(hWnd, fShow); }
	BOOL EnableScrollBar(UINT wSBFlags, UINT wArrows){ return ::EnableScrollBar(hWnd, wSBFlags, wArrows); }

	// 좌표와 매핑 함수
	int MapPoints(cWindow *To, LPPOINT pts, UINT n){ return ::MapWindowPoints(hWnd, To->hWnd, pts, n); }
	BOOL ClientToScreen(LPPOINT ppt){ return ::ClientToScreen(hWnd, ppt); }
	void ClientToScreen(LPRECT prc);
	void ScreenToClient(LPRECT prc);
	BOOL ScreenToClient(LPPOINT ppt){ return ::ScreenToClient(hWnd, ppt); }

	// 윈도우 캡션
	BOOL SetText(LPCTSTR str){ return ::SetWindowText(hWnd, str); }
	int GetText(LPTSTR str, int max){ return ::GetWindowText(hWnd, str, max); }
	int GetTextLength(){ return ::GetWindowTextLength(hWnd); }

	// 스크롤
	int GetScrollPos(int nBar){ return ::GetScrollPos(hWnd, nBar); }
	BOOL GetScrollRange(int nBar, LPINT pMinPos, LPINT pMaxPos){ return ::GetScrollRange(hWnd, nBar, pMinPos, pMaxPos); }
	BOOL Scroll(int xAmount, int yAmount, CONST RECT *prc = NULL, CONST RECT *prcClip = NULL){ return ::ScrollWindow(hWnd, xAmount, yAmount, prc, prcClip); }
	BOOL GetScrollInfo(int nBar, LPSCROLLINFO psi){ return ::GetScrollInfo(hWnd, nBar, psi); }
	int SetScrollInfo(int fnBar, LPSCROLLINFO psi, BOOL fRedraw = true){ return ::SetScrollInfo(hWnd, fnBar, psi, fRedraw); }
	BOOL SetScrollRange(int nBar, int nMinPos, int nMaxPos, BOOL bRedraw = true){ return ::SetScrollRange(hWnd, nBar, nMinPos, nMaxPos, bRedraw); }
	BOOL ShowScrollBar(int wBar, BOOL bShow = true){ return ::ShowScrollBar(hWnd, wBar, bShow); }

	// 끌어서 놓기
	void DragAcceptFiles(BOOL bAccept = TRUE){ ::DragAcceptFiles(hWnd, bAccept); }

	// 캐럿
	static int CreateCaret(HBITMAP hbmp, int w, int h){ return CreateCaret(hbmp, w, h); }
	static BOOL GetCaretPos(LPPOINT ppt){ return ::GetCaretPos(ppt); }
	static BOOL SetCaretPos(int x, int y){ return ::SetCaretPos(x, y); }
	BOOL HideCaret(){ return ::HideCaret(hWnd); }
	BOOL ShowCaret(){ return ::ShowCaret(hWnd); }

	// 다이얼로그 박스 항목 함수
	HWND GetDlgItem(int id){ return ::GetDlgItem(hWnd, id); }
	BOOL CheckDlgButton(int nidbtn, UINT uCheck){ return ::CheckDlgButton(hWnd, nidbtn, uCheck); }
	BOOL CheckRadioButton(int idFirst, int idLast, int idCheck){ return ::CheckRadioButton(hWnd, idFirst, idLast, idCheck); }
	int DlgDirList(LPTSTR Path, int idListBox, int idPath, UINT uFileTypes){ return ::DlgDirList(hWnd, Path, idListBox, idPath, uFileTypes); }
	int DlgDirListComboBox(LPTSTR Path, int idCombo, int idPath, UINT uFileTypes){ return ::DlgDirListComboBox(hWnd, Path, idCombo, idPath, uFileTypes); }
	int GetDlgItemText(int id, LPTSTR str, int nMax){ return ::GetDlgItemText(hWnd, id, str, nMax); }
	cWindow *GetNextDlgGroupItem(cWindow *Ctrl, BOOL bPrevious = false){ return GetWindow(::GetNextDlgGroupItem(hWnd, Ctrl->hWnd, bPrevious)); }
	cWindow *GetNextDlgTabItem(cWindow *Ctrl, BOOL bPrevious = FALSE){ return GetWindow(::GetNextDlgTabItem(hWnd, Ctrl->hWnd, bPrevious)); }
	BOOL IsDlgButtonChecked(int id){ return ::IsDlgButtonChecked(hWnd, id); }
	BOOL IsDialogMessage(LPMSG pmsg){ return ::IsDialogMessage(hWnd, pmsg); }
	int SendDlgItemMessage(int id, UINT Msg, WPARAM wParam, LPARAM lParam){ return ::SendDlgItemMessage(hWnd, id, Msg, wParam, lParam); }
	BOOL SetDlgItemText(int id, LPCTSTR str){ return ::SetDlgItemText(hWnd, id, str); }

	// 메뉴 함수
	HMENU GetMenu(){ return ::GetMenu(hWnd); }
	BOOL SetMenu(HMENU hMenu){ return ::SetMenu(hWnd, hMenu); }
	BOOL DrawMenuBar(){ return ::DrawMenuBar(hWnd); }
	HMENU GetSystemMenu(BOOL bRevert = false){ return ::GetSystemMenu(hWnd, bRevert); }
	BOOL HiliteMenuItem(HMENU hMenu, UINT Item, UINT Flag){ return ::HiliteMenuItem(hWnd, hMenu, Item, Flag); }
	
	// 타이머 함수
	UINT SetTimer(UINT id, UINT Elapse){ return ::SetTimer(hWnd, id, Elapse, NULL); }
	BOOL KillTimer(UINT id){ return ::KillTimer(hWnd, id); }

	// 경보 함수
	BOOL Flash(DWORD Flag){ return ::FlashWindow(hWnd, Flag); }
	int MessageBox(LPCTSTR text, LPCTSTR caption = NULL, UINT type = MB_OK){ return ::MessageBox(hWnd, text, caption, type); }

	// 메시지 함수
	LRESULT SendMessage(UINT msg, WPARAM wParam, LPARAM lParam){ return ::SendMessage(hWnd, msg, wParam, lParam); }
	BOOL PostMessage(UINT msg, WPARAM wParam, LPARAM lParam){ return ::PostMessage(hWnd, msg, wParam, lParam); }
	BOOL SendNotifyMessage(UINT msg, WPARAM w, LPARAM l){ return ::SendNotifyMessage(hWnd, msg, w, l); }

	
	// Auto Type casting
	operator HWND(){ if(this) return hWnd; return NULL; } 
	HWND GetWindowHandle(){ return hWnd; };
	static void SetInstanceHandle(HINSTANCE _hInstance){ hInstance = _hInstance; }
	// 
};

// GDI 함수들
BOOL TextOut(HDC hdc, int x, int y, LPCTSTR str);

#endif 
