Thread: Why doesn't this example work for me?

  1. #1
    Registered User
    Join Date
    Mar 2006
    Posts
    150

    Why doesn't this example work for me?

    I am trying to compile the following example using Visual C++:

    Code:
    /* ---- AbstractWindow.h ---- */
    class AbstractWindow {
    	// --- previous class definition here ---
     
    	public:
    		virtual bool OnCommand (int ctrlId, int notifyCode) { return false; }
    		virtual bool OnDestroy () { ::PostQuitMessage (0); return false; }
    		virtual bool OnClose () { return false; }
    		// --- and so on, add as many handlers as necessary ---
    		// --- and define their default behavior ---
    		// --- usually they return 0, but check MSDN for details ---
    };
     
    /* ---- AbstractWindow.cpp ---- */
    LRESULT CALLBACK AbstractWindow::msgRouter (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
    {
    	AbstractWindow *wnd = 0;	
     
    	if (message == WM_NCCREATE) {
    		wnd = (AbstractWindow *) ((LPCREATESTRUCT(lParam))->lpCreateParams);
    		::SetWindowLong (hwnd, GWL_USERDATA, long(wnd));
    		wnd->OnNCCreate (/* params */);
    	} else {
    		wnd = (AbstractWindow *) (::GetWindowLong (hwnd, GWL_USERDATA));
     
    		if (wnd) {
    			switch (message)
    			{
    				case WM_COMMAND:
    					return OnCommand (LOWORD (wParam), HIWORD(wParam))
    				case WM_DESTROY:
    					return OnDestroy ();
    				case WM_CLOSE:
    					return OnClose ();
     
    				// --- and so on, it'll be a lot of work to do,
    				// but most apps don't use every window message ---
     
    				default:	// for the messages you did not define any handlers
    					return ::DefWindowProc (hwnd, message, wParam, lParam);
    			}
    		}
    		else	// for messages that arrive prior to WM_NCCREATE 
    			// and the HWND -> AbstractWindow * association was not made
    			return ::DefWindowProc (hwnd, message, wParam, lParam);
    	}
    }
    but for some reason I keep getting the following errors:

    Code:
    .\test.cpp(97) : error C2352: 'AbstractWindow::OnCommand' : illegal call of non-static member function
            .\test.cpp(43) : see declaration of 'AbstractWindow::OnCommand'
    .\test.cpp(99) : error C2352: 'AbstractWindow::OnClose' : illegal call of non-static member function
            .\test.cpp(45) : see declaration of 'AbstractWindow::OnClose'
    .\test.cpp(101) : error C2352: 'AbstractWindow::OnDestroy' : illegal call of non-static member function
            .\test.cpp(44) : see declaration of 'AbstractWindow::OnDestroy'
    I'm not sure I understand why these functions have to be static. Here is the full example of the class that I'm forming:

    Code:
    class AbstractWindow
    {
    protected:
    
    	HWND      _hwnd;
    	LPCSTR    _className;
    
    	list<HWND> children;
    
    public:
    
    	//default constructor
    	AbstractWindow () { }
    
    	//member functions
    	static  LRESULT CALLBACK msgRouter     (HWND, UINT, WPARAM, LPARAM);
    
    	virtual bool Create        (char *, int, int, int, int);
    	virtual bool OnCommand     (int ctrlId, int notifyCode) { return false; }
    	virtual bool OnDestroy	   (void) { ::PostQuitMessage (0); return false; }
    	virtual bool OnClose       (void) { DestroyWindow (_hwnd); return false; }
    	virtual bool OnNCCreate    (void) { MessageBox (NULL, "NCCreate", "NCCreate", MB_OK); return false; }
    
    	bool AddButton     (char *, int, int, int, int, int);
    	bool AddTextBox    (char *, int, int, int, int, int);
    	bool AddComboBox   (char**, int, int, int, int, int);
    	bool AddStaticText (char *, int, int, int, int, int);
    };
    
    bool AbstractWindow::Create (char *name, int x, int y, int width, int height)
    {
    	_hwnd = CreateWindowEx (0, _className, name, WS_OVERLAPPEDWINDOW, x, y, width, height,
    			NULL, NULL, GetModuleHandle (NULL), this);
    
    	if (!_hwnd)
    		return false;
    
    	return true;
    }
    
    LRESULT CALLBACK AbstractWindow::msgRouter(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
    {
    	AbstractWindow *wnd = 0;
    
    	if (msg == WM_NCCREATE)
    	{
    		wnd = (AbstractWindow *) ((LPCREATESTRUCT) lParam)->lpCreateParams;
    		::SetWindowLong (hwnd, GWL_USERDATA, long (wnd));
    		wnd->OnNCCreate ();
    	}
    
    	wnd = (AbstractWindow *) (::GetWindowLong (hwnd, GWL_USERDATA));
    
    	if (wnd)
    	{
    		switch (msg)
    		{
    		case WM_COMMAND:
    			return OnCommand (LOWORD (wParam), HIWORD (wParam));
    		case WM_CLOSE:
    			return OnClose ();
    		case WM_DESTROY:
    			return OnDestroy ();
    		default:
    			return DefWindowProc (hwnd, msg, wParam, lParam);
    		}
    	}
    
    	else
    		return DefWindowProc (hwnd, msg, wParam, lParam);
    }
    
    bool AbstractWindow::AddButton (char *caption, int xPos, int yPos, int width, int height, int id)
    {
    	HWND child = CreateWindowEx (0, "BUTTON", caption, WS_CHILD | WS_VISIBLE, xPos, yPos,
    		width, height, _hwnd, (HMENU) id, GetModuleHandle (NULL), NULL);
    
    	if (child)
    	{
    		children.push_front (child);
    		return true;
    	}
    	else
    	{
    		DestroyWindow (child);
    		return false;
    	}
    }
    Any help would be GREAT!!! And insight i suppose, cuz i guess i dont quite understand static, as many times as i read about it everywhere i can.
    HA! I WIN!

  2. #2
    Registered User
    Join Date
    May 2006
    Posts
    903
    Well it's easy enough. You neither instantiated an object of AbstractWindow nor made it static (which would require the class::static_method() syntax). Therefore, your call is lost in the global space and the compiler reports an error.

  3. #3
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Since your msgRouter function is static, it implies that all member function calls are also static.

    static member functions do not have the "this" pointer parameter that normal member functions have, and if you want to call normal member functions, the object you want it to operate on must be specified. My guess would be that you wan to use:
    Code:
    					return wnd->OnCommand (LOWORD (wParam), HIWORD(wParam));
    or something along those lines.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  4. #4
    Registered User
    Join Date
    Mar 2006
    Posts
    150
    Words cannot express my gratefulness... i always miss the simple things for some reason. alot of oop concepts are still a little hard for me i guess. thanx guys!
    HA! I WIN!

  5. #5
    Registered User
    Join Date
    Mar 2006
    Posts
    150
    Ok, now i have another question. I have added code to make a tray icon appear when the window is minimized. when i run the program and minimize the window, the icon appears fine, but when i mouse over it, it disappears and apparently the message for the icon isn't even being handled based on test MessageBoxes i added. Here is the code:

    Code:
    #define TASKBAR_RESTORE 0x2000
    
    using namespace std;
    
    class SimpleWindowClass : protected WNDCLASSEX
    {
    public:
    
    	SimpleWindowClass (const TCHAR * className);
    
    	virtual bool Register ();
    	virtual const TCHAR * className () const { return lpszClassName; }
    
    protected:
    
    };
    
    class AbstractWindow
    {
    protected:
    
    	HWND      _hwnd;
    	LPCSTR    _className;
    
    	list<HWND> children;
    
    public:
    
    	//default constructor
    	AbstractWindow () { }
    
    	//member functions
    	static LRESULT CALLBACK msgRouter (HWND, UINT, WPARAM, LPARAM);
    
    	virtual bool Create        (char *, int, int, int, int);
    	virtual bool OnCommand     (int ctrlId, int notifyCode) { return false; }
    	virtual bool OnSysCommand  (int ctrlId, int notifyCode) { return false; }
    	virtual bool OnDestroy	   (void) { ::PostQuitMessage (0); return false; }
    	virtual bool OnClose       (void) { DestroyWindow (_hwnd); return false; }
    	virtual bool OnNCCreate    (void) { return false; }
    	virtual bool OnTaskBar     (int notifyCode) { return false; }
    
    	bool AddButton     (char *, int, int, int, int, int);
    	bool AddTextBox    (char *, int, int, int, int, int);
    	bool AddComboBox   (char**, int, int, int, int, int);
    	bool AddStaticText (char *, int, int, int, int, int);
    };
    
    class SimpleWindow : public AbstractWindow
    {
    private:
    
    	NOTIFYICONDATA icon_dat;
    
    public:
    
    	SimpleWindow (const TCHAR *className);
    
    	void Show ();
    	void Hide ();
    
    	virtual bool OnCommand    (int ctrlId, int notifyCode);
    	virtual bool OnSysCommand (int ctrlId, int notifyCode);
    	virtual bool OnTaskBar    (int notifyCode);
    };
    
    bool AbstractWindow::Create (char *name, int x, int y, int width, int height)
    {
    	_hwnd = CreateWindowEx (0, _className, name, WS_OVERLAPPEDWINDOW, x, y, width, height,
    			NULL, NULL, GetModuleHandle (NULL), this);
    
    	if (!_hwnd)
    		return false;
    
    	return true;
    }
    
    LRESULT CALLBACK AbstractWindow::msgRouter(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
    {
    	AbstractWindow *wnd = 0;
    
    	if (msg == WM_NCCREATE)
    	{
    		wnd = (AbstractWindow *) ((LPCREATESTRUCT) lParam)->lpCreateParams;
    		::SetWindowLong (hwnd, GWL_USERDATA, long (wnd));
    		wnd->OnNCCreate ();
    	}
    
    	wnd = (AbstractWindow *) (::GetWindowLong (hwnd, GWL_USERDATA));
    
    	if (wnd)
    	{
    		switch (msg)
    		{
    		case WM_COMMAND:
    			MessageBox (NULL, "Command action", "Hey!", MB_OK);
    			return wnd->OnCommand (LOWORD (wParam), HIWORD (wParam));
    		case WM_SYSCOMMAND:
    			MessageBox (NULL, "SysCommand action", "Hey!", MB_OK);
    			return wnd->OnSysCommand (LOWORD (wParam), HIWORD (wParam));
    		case WM_CLOSE:
    			MessageBox (NULL, "Close action", "Hey!", MB_OK);
    			return wnd->OnClose ();
    		case WM_DESTROY:
    			MessageBox (NULL, "Destroy action", "Hey!", MB_OK);
    			return wnd->OnDestroy ();
    		case TASKBAR_RESTORE:
    			MessageBox (NULL, "TaskBar action", "Hey!", MB_OK);
    			return wnd->OnTaskBar (LOWORD (lParam));
    		default:
    			return DefWindowProc (hwnd, msg, wParam, lParam);
    		}
    	}
    
    	else
    		return DefWindowProc (hwnd, msg, wParam, lParam);
    }
    
    bool AbstractWindow::AddButton (char *caption, int xPos, int yPos, int width, int height, int id)
    {
    	HWND child = CreateWindowEx (0, "BUTTON", caption, WS_CHILD | WS_VISIBLE, xPos, yPos,
    		width, height, _hwnd, (HMENU) id, GetModuleHandle (NULL), NULL);
    
    	if (child)
    	{
    		children.push_front (child);
    		return true;
    	}
    	else
    	{
    		DestroyWindow (child);
    		return false;
    	}
    }
    
    bool AbstractWindow::AddTextBox (char *initial, int xPos, int yPos, int width, int height, int id)
    {
    	HWND child = CreateWindowEx (0, "EDIT", initial, WS_CHILD | WS_VISIBLE, xPos, yPos,
    		width, height, _hwnd, (HMENU) id, GetModuleHandle (NULL), NULL);
    
    	if (child)
    	{
    		children.push_front (child);
    		return true;
    	}
    	else
    	{
    		DestroyWindow (child);
    		return false;
    	}
    }
    
    SimpleWindowClass::SimpleWindowClass (const TCHAR *className)
    {
    	hInstance     = GetModuleHandle (NULL);
    	lpfnWndProc   = AbstractWindow::msgRouter;
    	lpszClassName = className;
    	lpszMenuName  = 0;
    	cbSize        = sizeof (WNDCLASSEX);
    	cbClsExtra    = 0;
    	cbWndExtra    = 0;
    	style         = 0;
    	hIcon         = ::LoadIcon (NULL, IDI_APPLICATION);
    	hIconSm       = ::LoadIcon (NULL, IDI_APPLICATION);
    	hCursor       = ::LoadCursor (NULL, IDC_ARROW);
    	hbrBackground = (HBRUSH)(COLOR_BACKGROUND+15);
    }
    
    bool SimpleWindowClass::Register (void)
    {
    	if (::RegisterClassEx (this))
    		return true;
    	else
    		return false;
    }
    
    SimpleWindow::SimpleWindow (const TCHAR *className) : AbstractWindow ()
    {
    	_className = className;
    
    	icon_dat.cbSize           = sizeof (NOTIFYICONDATA);
    	icon_dat.hWnd             = _hwnd;
    	icon_dat.uID              = 10;
    	icon_dat.uFlags           = NIF_MESSAGE | NIF_ICON | NIF_TIP;
    	icon_dat.uCallbackMessage = TASKBAR_RESTORE;
    	icon_dat.hIcon            = LoadIcon (NULL, IDI_APPLICATION);
    
    	strcpy (icon_dat.szTip, "App");
    }
    
    void SimpleWindow::Show (void)
    {
    	ShowWindow (_hwnd, SW_SHOW);
    	UpdateWindow (_hwnd);
    }
    void SimpleWindow::Hide (void)
    {
    	ShowWindow (_hwnd, SW_HIDE);
    	UpdateWindow (_hwnd);
    }
    
    bool SimpleWindow::OnCommand (int ctrlId, int notifyCode)
    {
    	switch (notifyCode)
    	{
    	case BN_CLICKED:
    		
    		if (ctrlId == 0)
    			MessageBox (NULL, "You pressed OK!", "Notification", MB_OK);
    		else if (ctrlId == 1)
    			DestroyWindow (_hwnd);
    		break;
    
    	default:
    
    		break;
    	}
    	return true;
    }
    
    bool SimpleWindow::OnTaskBar (int notifyCode)
    {
    	MessageBox (NULL, "You did something in the taskbar", "Hey!", MB_OK);
    
    	switch (notifyCode)
    	{
    	case WM_LBUTTONDOWN:
    
    		Shell_NotifyIcon (NIM_DELETE, &icon_dat);
    		this->Show ();
    		break;
    	}
    	return false;
    }
    
    bool SimpleWindow::OnSysCommand (int ctrlId, int notifyCode)
    {
    	switch (notifyCode)
    	{
    	case SC_MINIMIZE:
    
    		Shell_NotifyIcon (NIM_ADD, &icon_dat);
    		this->Hide ();
    		break;
    	}
    	return false;
    }
    
    int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
    {
    	SimpleWindowClass wndClass ("WinClass");
    	wndClass.Register();
    
    	SimpleWindow myWin ("WinClass");
    
    	myWin.Create ("Hello, world!", 10, 10, 300, 300);
    	myWin.AddButton ("Ok", 10, 10, 50, 30, 0);
    	myWin.AddButton ("Exit", 60, 10, 50, 30, 1);
    
    	myWin.Show ();
    
    	MSG msg;
    	int status;
    
    	while ((status = ::GetMessage (&msg, 0, 0, 0)) != 0)
    	{
    		if (status == -1)
    			break;
    
    		TranslateMessage (&msg);
    		DispatchMessage  (&msg);
    	}
    
    	return msg.wParam;
    }
    Sorry its alot of code. Can anyone tell me why my code for this is wrong? Any other errors feel free to let me know.
    HA! I WIN!

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. strcmp returning 1...
    By Axel in forum C Programming
    Replies: 12
    Last Post: 09-08-2006, 07:48 PM
  2. getline() don't want to work anymore...
    By mikahell in forum C++ Programming
    Replies: 7
    Last Post: 07-31-2006, 10:50 AM
  3. Why don't the tutorials on this site work on my computer?
    By jsrig88 in forum C++ Programming
    Replies: 3
    Last Post: 05-15-2006, 10:39 PM
  4. fopen();
    By GanglyLamb in forum C Programming
    Replies: 8
    Last Post: 11-03-2002, 12:39 PM
  5. DLL __cdecl doesnt seem to work?
    By Xei in forum C++ Programming
    Replies: 6
    Last Post: 08-21-2002, 04:36 PM