LRESULT __stdcall COverlappedWindow::windowProc( HWND _handle, UINT message, WPARAM wParam, LPARAM lParam ) {
		RECT clientRect;
		COverlappedWindow* ptr;
		ptr = reinterpret_cast<COverlappedWindow*>( ::GetWindowLong( _handle, GWL_USERDATA ) );
		switch ( message ) {
			case WM_NCCREATE:
				{
					COverlappedWindow* that = reinterpret_cast<COverlappedWindow*>( reinterpret_cast<LPCREATESTRUCT>( lParam )->lpCreateParams );
					::SetWindowLong(_handle, GWL_USERDATA, reinterpret_cast<LONG>( that ) );
					::DefWindowProc( _handle, message, wParam, lParam );
					::SetTimer( _handle, TIMER_ID, 0.01, NULL );
					break;
				}
			case WM_TIMER:
				ptr->OnTimer();
				break;

			case WM_DESTROY:
				ptr->OnDestroy();
				break;

			case WM_PAINT:
				ptr->OnPaint();
				break;

			default:
				return ::DefWindowProc( _handle, message, wParam, lParam );
		}
		return ::DefWindowProc( _handle, message, wParam, lParam );
}
LRESULT COverlappedWindow::windowProc(HWND handle, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message) {
    case WM_NCCREATE:
    {
        COverlappedWindow* window = reinterpret_cast<COverlappedWindow*>((reinterpret_cast<CREATESTRUCT*>(lParam))->lpCreateParams);
        SetLastError(0);
        SetWindowLongPtr(handle, GWLP_USERDATA, (LONG)window);
        if( GetLastError() != 0 ) {
            return GetLastError();
        }
        window->OnNCCreate(handle);
        return DefWindowProc(handle, message, wParam, lParam);
    }
    case WM_CREATE:
    {
        COverlappedWindow* window = reinterpret_cast<COverlappedWindow*>(GetWindowLongPtr(handle, GWLP_USERDATA));
        window->OnCreate();
        return DefWindowProc(handle, message, wParam, lParam);
    }
    case WM_DESTROY:
    {
        COverlappedWindow* window = reinterpret_cast<COverlappedWindow*>(GetWindowLongPtr(handle, GWLP_USERDATA));
        window->OnDestroy();
        return 0;
    }
    case WM_PAINT:
    {
        COverlappedWindow* window = reinterpret_cast<COverlappedWindow*>(GetWindowLongPtr(handle, GWLP_USERDATA));
        window->OnPaint();
        return 0;
    }
    case WM_SIZE:
    {
        COverlappedWindow* window = reinterpret_cast<COverlappedWindow*>(GetWindowLongPtr(handle, GWLP_USERDATA));
        window->OnResize();
        return 0;
    }
    default:
        return DefWindowProc(handle, message, wParam, lParam);
    }
}
LRESULT __stdcall COverlappedWindow::windowProc(HWND handle, UINT message, WPARAM wParam, LPARAM lParam)
{
	if (message == WM_ERASEBKGND) {
		return true;
	}

	if (message == WM_NCCREATE) {
		COverlappedWindow* window = reinterpret_cast<COverlappedWindow*>(reinterpret_cast<CREATESTRUCT*>(lParam)->lpCreateParams);
		::SetWindowLongPtr(handle, GWLP_USERDATA, reinterpret_cast<LONG>(window));
	}
	else {
		COverlappedWindow* window = reinterpret_cast<COverlappedWindow*>(::GetWindowLongPtr(handle, GWLP_USERDATA));
		switch (message) {
		case WM_CREATE:
			window->OnCreate(handle);
			break;
		case WM_PAINT:
			window->OnPaint();
			break;
		case WM_COMMAND:
			window->OnCommand(wParam, lParam);
			break;
		case WM_LBUTTONDOWN:
			window->OnLButtonDown(wParam, lParam);
			break;
		case WM_CLOSE:
			if (!window->OnClose()) {
				return 0;
			}
			break;
		case WM_DESTROY:
			window->OnDestroy();
			break;
		default:
			break;
		}
	}

	return DefWindowProc(handle, message, wParam, lParam);
}