   I can't figure out this error in my window wrapper class attempt.
  [[EDIT: Original problem solved, source code has been updated as of post #12 to address new problem]]Before continuing on with learning D3D I wanted to wrap the window creation code for a bit of modularity. I used this article as reference:http://www.gamedev.net/reference/articles/article1810.aspI really don't want learn Win32 programming in-depth right now and just want to get this wrapper class right and sort of forget about it, merely dumping the module in new projects. This might mean that there _may_ be serious silly stuff in my code with me not knowing the meaning of various constants and working of some functions. srry >_>The error I am getting is:1>.\BaseWindow.cpp(49) : error C2664: 'BaseWindow::RegisterMessageHandler' : cannot convert parameter 2 from 'long (__thiscall BaseWindow::* )(BaseWindow &,HWND,long,long)' to 'BaseWindow::fpMessageHandler_t'1>   There is no context in which this conversion is possibleSomething wrong with the function pointer stuff.It points to this line(It is in the constructor of BaseWindow):RegisterMessageHandler(WM_DESTROY, &BaseWindow::OnDestroy);I tried commenting out the line, but then I get this linker error:1>BaseWindow.obj : error LNK2019: unresolved external symbol "private: static class std::map<long,long (__cdecl*)(class BaseWindow &,struct HWND__ *,long,long),struct std::less<long>,class std::allocator<struct std::pair<long const ,long (__cdecl*)(class BaseWindow &,struct HWND__ *,long,long)> > > BaseWindow::_msgHandlers" (?_msgHandlers@BaseWindow@@0V?$map@JP6AJAAVBaseWindow@@PAUHWND__@@JJ@ZU?$less@J@std@@V?$allocator@U?$pair@$$CBJP6AJAAVBaseWindow@@PAUHWND__@@JJ@Z@std@@@4@@std@@A) referenced in function "public: static long __stdcall BaseWindow::MsgRouter(struct HWND__ *,unsigned int,unsigned int,long)" (?MsgRouter@BaseWindow@@SGJPAUHWND__@@IIJ@Z)1>F:\STUFF\Dev Stuff\ziggeh\Debug\ziggeh.exe : fatal error LNK1120: 1 unresolved externalsHere is the code:BaseWindow.h#ifndef GUARD_BASEWINDOW_H#define GUARD_BASEWINDOW_H#include <windows.h>#include <string>#include <map>class BaseWindow{public:BaseWindow(HINSTANCE hInstance, std::string winCaption, int width, int height, bool isFullScreen, const std::string & cl );~BaseWindow();typedef long (* fpMessageHandler_t)(BaseWindow &, HWND, long, long);static LRESULT CALLBACK MsgRouter(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);fpMessageHandler_t RegisterMessageHandler(long message, fpMessageHandler_t handler);bool HandleMessagesTillQuit();std::string rawr;private:bool _fullScreen;HINSTANCE _appHInst;HWND _windowHandle;std::string _windowCaption;typedef std::map<long, fpMessageHandler_t> MessageMap_t;typedef MessageMap_t::iterator MessageIterator_t;static MessageMap_t _msgHandlers;static long OnDestroy(BaseWindow & wnd, HWND hwnd, long wparam, long lparam);static long OnClose(BaseWindow & wnd, HWND hwnd, long wparam, long lparam);void SetHWND(HWND hwnd);};#endifBaseWindow.cpp:#include "BaseWindow.h"#include "GeneralStuff.h"BaseWindow::MessageMap_t BaseWindow::_msgHandlers;BaseWindow::BaseWindow(HINSTANCE hInstance, std::string winCaption, int width, int height, bool isFullScreen, const std::string & cl) :_appHInst(hInstance),_windowCaption(winCaption),_windowHandle(0),_fullScreen(isFullScreen){WNDCLASS wc;wc.style = CS_HREDRAW | CS_VREDRAW;wc.cbClsExtra = 0;wc.cbWndExtra = 0;wc.hbrBackground = (HBRUSH)::GetStockObject(WHITE_BRUSH);wc.hCursor = ::LoadCursor(0, IDC_ARROW);wc.hIcon = ::LoadIcon(0, IDI_APPLICATION);wc.hInstance = _appHInst;wc.lpfnWndProc = MsgRouter;wc.lpszClassName = cl.c_str();// "ManiacalAce";wc.lpszMenuName = 0;if (!::RegisterClass(&wc)){ReportMsg("RegisterClass() failed in InitWindow()");::PostQuitMessage(0);}RECT R = {0, 0, width, height};DWORD dwStyle;if (_fullScreen == true)dwStyle = WS_POPUP;elsedwStyle = (WS_OVERLAPPEDWINDOW | WS_VISIBLE); // & ~WS_THICKFRAME; //<---for non-resizable windowDWORD dwExStyle = 0;::AdjustWindowRectEx(&R, dwStyle, false, dwExStyle);R.right -= R.left;R.bottom -= R.top;//_windowHandle = ::CreateWindowA("ManiacalAce", _windowCaption.c_str(), dwStyle,//CW_USEDEFAULT, CW_USEDEFAULT, R.right, R.bottom, 0, 0, _appHInst, this);_windowHandle = ::CreateWindowEx(dwExStyle, cl.c_str(), _windowCaption.c_str(), dwStyle,CW_USEDEFAULT, CW_USEDEFAULT, R.right, R.bottom, 0, 0, _appHInst, this);if (!_windowHandle){ReportMsg("CreateWindow() failed in InitWindow()");::PostQuitMessage(0);}RegisterMessageHandler(WM_DESTROY, &BaseWindow::OnDestroy);RegisterMessageHandler(WM_CLOSE, &BaseWindow::OnClose);::ShowWindow(_windowHandle, SW_SHOW);::UpdateWindow(_windowHandle);}//==================================================================================================BaseWindow::~BaseWindow(){}//==================================================================================================void BaseWindow::SetHWND(HWND hwnd) {_windowHandle = hwnd;}//==================================================================================================LRESULT CALLBACK BaseWindow::MsgRouter(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {BaseWindow * wnd = 0;if (msg == WM_NCCREATE){//wnd = reinterpret_cast<BaseWindow *> ((LPCREATESTRUCT)lparam)->lpCreateParams;wnd = (BaseWindow *)((LPCREATESTRUCT)lparam)->lpCreateParams;::SetWindowLong(hwnd, GWL_USERDATA, reinterpret_cast<long>(wnd));wnd->SetHWND(hwnd);//return true;}else{wnd = reinterpret_cast<BaseWindow *>(::GetWindowLong(hwnd, GWL_USERDATA));}if (wnd){MessageIterator_t it = _msgHandlers.find(msg);if (it != _msgHandlers.end())return (it->second)((*wnd), hwnd, wparam, lparam);}return ::DefWindowProc(hwnd, msg, wparam, lparam);}//==================================================================================================BaseWindow::fpMessageHandler_t BaseWindow::RegisterMessageHandler(long message, BaseWindow::fpMessageHandler_t handler) {fpMessageHandler_t m = 0;MessageIterator_t it = _msgHandlers.find(message);if (it != _msgHandlers.end())m = it->second;_msgHandlers.insert(std::pair<long, fpMessageHandler_t>(message, handler));return m;}//==================================================================================================bool BaseWindow::HandleMessagesTillQuit(){static MSG msg;::ZeroMemory(&msg, sizeof(MSG));if (::PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) //param 2 should be _windowHandle?{if (msg.message == WM_QUIT)return true;::TranslateMessage(&msg);::DispatchMessage(&msg);}return false;}//==================================================================================================long BaseWindow::OnDestroy(BaseWindow &wnd, HWND hwnd, long wparam, long lparam) {::PostQuitMessage(0);return 0;}//==================================================================================================long BaseWindow::OnClose(BaseWindow &wnd, HWND hwnd, long wparam, long lparam) {::DestroyWindow(hwnd);return 0;}//==================================================================================================GeneralStuff.h:#ifndef GUARD_GENERALSTUFF_H#define GUARD_GENERALSTUFF_Hinline void ReportMsg(const std::string & msg){::MessageBox(0, msg.c_str(), "Message", 0);}#endifmain.cpp#include <iostream>#include "BaseWindow.h"int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR cmdline, int nShowCmd){BaseWindow tehWindow(hInstance, "Phew! Window!", 800, 600, false, "asd");BaseWindow ww(hInstance, "asdad", 400, 400, false, "desd");//while (tehWindow.HandleMessagesTillQuit() == false){}bool quit = false;bool b1 = false, b2 = false;while (quit == false){if (b1 == false)b1 = tehWindow.HandleMessagesTillQuit();if (b2 == false)b2 = ww.HandleMessagesTillQuit();if (b1 == true && b2 == true)quit = true;}return 0;}Pardon me for dumping the entire code like this.And of course, there might be more stuff wrong with this as I said before.[Edited by - ManiacalAce on June 26, 2009 12:30:15 PM]
  the name of the function is the address to the function so &(function) is a pointer to a pointer use just the function name and I think it should compile.   ;  A member function pointer is incompatible with regular function pointers. See here. Sn interesting gamedev article for you is here.   ;  The linker error you get is caused by you not defining BaseWindow::_msgHandlers.  When you make a variable in a class static, you also have to explicitly define it in one and only one source file.  This means that in your BaseWindow.cpp file, you'd have to add the linestd::map<long, fpMessageHandler_t> BaseWindow::_msgHandlers;If you wanted to initialize _msgHandlers, you could also asign it some value at the same time.The first error is caused by the fact that you are passing the function OnDestroy, which is a non-static method.  Because it is a non-static method, you must use an object to call it (i.e. object.OnDestroy(...parameters...)); you cannot call it by itself (i.e. OnDestroy(...parameters...)).  fpMessageHandler_t is a pointer to a function, but if you want to pass OnDestroy, you need a pointer to a member function.  You either need to 1) make OnDestroy static, or 2) use some type of function library (like Boost.Function) that will allow you to bind an object to a member function so that you can call it like a regular function and pass it to other function as well.  If you go with option 2, you have to be careful that the object that the member function is bound to is not destroyed, otherwise calling that function will result in undefined behavior.[edit]ninja'd += 2;   ;  Thanks for the help, gentlemen. The code now compiles.But I'm now getting a runtime error. I knew there would be something wrong with the design v__vThe error is:Unhandled exception at 0x0040126d in ziggeh.exe: 0xC0000005: Access violation writing location 0x00000008.The code compiled after following Mike's fixes:1)the static data member was defined:BaseWindow::MessageMap_t BaseWindow::_msgHandlers;2) OnDestroy was made static.More counsel? x__x   ;Quote:Original post by MikeTacular[edit]ninja'd += 2;<offtopic>Just curious, what's your definition of "ninja'd"? Your post and the others have move than a 10 minute difference.</offtopic>   ;Quote:Original post by Halifax2Quote:Original post by MikeTacular[edit]ninja'd += 2;<offtopic>Just curious, what's your definition of "ninja'd"? Your post and the others have move than a 10 minute difference.</offtopic>If someone replies before me while I'm writing my own reply.  Neither of those posts were there when I started my post.  I'm slow :)@ManiacalAce: When you CreateWindow(), you are passing 0 for the last parameter.  This is the same parameter that is passed to the LPARAM of the MsgRoute function.  When you try to dereference 0, you're getting the crash (probably, assuming there isn't another problem).  You probably meant to pass this as the last parameter of CreateWindow(), not 0.   ;Quote:Original post by Halifax2Quote:Original post by MikeTacular[edit]ninja'd += 2;<offtopic>Just curious, what's your definition of "ninja'd"? Your post and the others have move than a 10 minute difference.</offtopic>The Ninja count is 2, so he has been ninja'd 2 times.edit: Partially ninja'd.   ;  Hmm.. putting 0 for the last parameter worked in my old code.I passed 'this' as the last param and now there's no crash, but my error checking code kicks in. The lines just below the CreateWindow() part.So I get: "CreateWindow() failed in InitWindow()"My window handle isn't being created :(I looked at someone else's code and even mimicked their use of CreateWindowEx instead >_>. Still same error :(   ;  I suggest you read this thread.  I'm too lazy to rewrite everything I said in that thread, but it all holds true for your code as well.  Basically you should return TRUE; after handling the WM_NCCREATE message.After CreateWindow fails, you can call GetLastError(), which will return an integer error code that will tell you why the last function (in this case, CreateWindow) failed.  You can then look the error code up here to get a little more information from it.Anyway, make sure to return TRUE; after handling WM_NCCREATE and call GetLastError() when a Windows function fails to get the error code that describes what went wrong.  If you don't know what to do after looking the error code up at the page I linked to, you can let us know what it is and we can try to help you out.   