Wrong.
And the worst part is I have no idea why. My CreateWindowEx() call is returning NULL, and MSDN tells me that GetLastError() will tell me why. Problem is, GetLastError is returning 0 - meaning the last call succeeded. Something doesn't add up here.
I'm sure I'm missing something obvious, but damned if I know what. Any ideas?
Code:
WinMain.cpp
#include #include "Window.h"int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/, LPSTR /*CommandLine*/, int nCmdShow){ Window *wnd = new Window(hInstance); wnd->Create(WS_OVERLAPPEDWINDOW|WS_VISIBLE); wnd->Show(nCmdShow); while ( true ) { if (!wnd->HandleMessages()) { break; } } return EXIT_SUCCESS;}
Window.h
#ifndef WINDOW_H#define WINDOW_H#include class Window;typedef long (*MessageHandler)(Window &, HWND, long, long);typedef std::map<long, MessageHandler> MessageMap;typedef MessageMap::const_iterator MessageIterator;class Window{public: Window(HINSTANCE hInstance); ~Window(); HWND Create(DWORD style); BOOL Show(int CmdShow) const; MessageHandler GetMessageHandler(long msg) const; MessageHandler RegisterMessageHandler(long msg, MessageHandler mh); void SetExit(bool exitState); bool IsExit() const; void SetHWND(HWND hwnd); HWND GetHWND() const; void SetHINSTANCE(HINSTANCE hInstance); HINSTANCE GetHINSTANCE() const; bool HandleMessages(); static LRESULT CALLBACK StaticWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); static long OnClose(Window &wnd, HWND hwnd, long param0, long param1); static long OnDestroy(Window &wnd, HWND hwnd, long param0, long param1);private: MessageMap m_MsgHandlers; HWND m_hwnd; HINSTANCE m_hInstance; bool m_Exit;};#endif
Window.cpp
#include #include #include "Window.h"Window::Window(HINSTANCE hInstance) : m_hInstance(hInstance), m_Exit(false), m_hwnd(NULL){ RegisterMessageHandler(WM_CLOSE, OnClose); RegisterMessageHandler(WM_DESTROY, OnDestroy);}Window::~Window(){}HWND Window::Create(DWORD style){ const char* myClassName = "MyClassName"; const char* myWindowTitle = "Window"; WNDCLASS wndClass = {0}; // Initialize everything to zero. wndClass.style = CS_VREDRAW | CS_HREDRAW; wndClass.lpfnWndProc = StaticWindowProc; wndClass.hInstance = GetHINSTANCE(); wndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION); wndClass.hCursor = LoadCursor(NULL, IDC_ARROW); wndClass.hbrBackground = (HBRUSH)(COLOR_APPWORKSPACE + 1); wndClass.lpszMenuName = NULL; wndClass.lpszClassName = myClassName; ATOM result = RegisterClass(&wndClass); // I don't want this silently failing assert(result || GetLastError() == ERROR_CLASS_ALREADY_EXISTS); (void)result; // Avoid unreferenced variable warnings in release builds. HWND window = CreateWindowEx( //<------this returns NULL 0, // Extended style myClassName, myWindowTitle, style, // window style CW_USEDEFAULT, CW_USEDEFAULT, // x, y CW_USEDEFAULT, CW_USEDEFAULT, // width, height 0, // Parent window 0, // Menu GetHINSTANCE(), (LPVOID)this); assert(window == GetHWND()); //<----this fails return window;}BOOL Window::Show(int CmdShow) const{ return ShowWindow(GetHWND(), CmdShow);}MessageHandler Window::GetMessageHandler(long msg) const{ MessageIterator iter = m_MsgHandlers.find(msg); if (iter == m_MsgHandlers.end()) { return NULL; } return iter->second;}MessageHandler Window::RegisterMessageHandler(long msg, MessageHandler mh){ MessageHandler m = NULL; MessageIterator iter = m_MsgHandlers.find(msg); if (iter != m_MsgHandlers.end()) { m = iter->second; } m_MsgHandlers.insert(std::pair<long, MessageHandler>(msg, mh)); return m;}void Window::SetExit(bool exitState){ m_Exit = exitState;}bool Window::IsExit() const{ return !m_Exit;}void Window::SetHWND( HWND hwnd ){ m_hwnd = hwnd;}HWND Window::GetHWND() const{ return m_hwnd;}void Window::SetHINSTANCE(HINSTANCE hInstance){ m_hInstance = hInstance;}HINSTANCE Window::GetHINSTANCE() const{ return m_hInstance;}bool Window::HandleMessages(){ static MSG msg; if (!GetHWND()) { return false; } if ( PeekMessage(&msg, GetHWND(), 0, 0, PM_REMOVE) ) { TranslateMessage(&msg); DispatchMessage(&msg); } else { return IsExit(); } return true;}LRESULT CALLBACK Window::StaticWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam){ Window *wnd = NULL; if (uMsg == WM_NCCREATE) { CREATESTRUCT *cs = reinterpret_cast(lParam); wnd = reinterpret_cast(cs->lpCreateParams); ::SetWindowLong(hwnd, GWLP_USERDATA, reinterpret_cast<long>(wnd)); wnd->SetHWND(hwnd); } else { wnd = reinterpret_cast(::GetWindowLong(hwnd, GWL_USERDATA)); } if (wnd) { MessageHandler mh = wnd->GetMessageHandler(uMsg); if(mh != NULL) { return mh(*wnd, hwnd, (long)wParam, (long)lParam); } } return DefWindowProc(hwnd, uMsg, lParam, wParam);}long Window::OnClose(Window &wnd, HWND hwnd, long param0, long param1){ (void)wnd; (void)param0; (void)param1; DestroyWindow(hwnd); return 0;}long Window::OnDestroy(Window &wnd, HWND hwnd, long param0, long param1){ (void)hwnd; (void)param0; (void)param1; PostQuitMessage(0); wnd.SetExit(true); return 0;}
edit: Also, my Set/GetWindowLong calls give me the following warnings:
c:\documents and settings\administrator\desktop\svn\spring 07\window\window\window\window.cpp(138) : warning C4311: 'reinterpret_cast' : pointer truncation from 'Window *' to 'long'c:\documents and settings\administrator\desktop\svn\spring 07\window\window\window\window.cpp(144) : warning C4312: 'reinterpret_cast' : conversion from 'LONG' to 'Window *' of greater size
I thought the whole idea of using long ptrs was make this thing 64-bit compatable, so why am I getting these warnings with /W64 [headshake]?