Sign in to follow this  
Andy474

Overloading Functions

Recommended Posts

1st, here is my Code the class Declaration class mWindow { //Set's up Varibles ... ... //tobe Overloaded Functions static bool Close() {return true;} //Runs shutdown Functions bool Init() {return true;}; static bool Render() {return true;} } ok, the three Functions Init() / Close() and Render() are supposed to be overloaded, however ... The Close is called in the WndProc() message loop on WM_DESTROY. and only seems to like it if its static. Here is the Class derived from mWindow, which overloads the Functions class WinSetup : public mWindow { private: public: //Overloaded functions WinSetup(); bool Init(); bool Close(); bool Render(); }; Now the Functions Should to my understanding overload ... and the Init() works perfectly, the problem is with the Render Function is not being called through WndProc(); do i need to overload WndProc? LRESULT CALLBACK mWindow::WndProc(HWND hWnd , UINT Msg, WPARAM wParam, LPARAM lParam) { switch(Msg) { case WM_DESTROY: Close(); PostQuitMessage(WM_QUIT); break; case WM_CREATE: break; case WM_PAINT: Render(); break; default: return DefWindowProc(hWnd, Msg, wParam, lParam); } return 0; }

Share this post


Link to post
Share on other sites
If you have base class functionality that you want to replace with derived class behavior then you should define the functions as virtual.

Share this post


Link to post
Share on other sites
You can't use static methods polymorphically. Remember, the only methods that are overridden are virtual methods, and they cannot be static.

The problem is that your WndProc has no context, it does not know which Window instance to manipulate. This is why you had to make the functions static for them to compile.

The solution is to either only allow a single Window instance, or use some other method to obtain a Window instance inside the WndProc. The former is pretty easy, make a global Window instance (or pointer to a derived instance) and use that. It is inelegant however.

The latter is addressed by this article.

Share this post


Link to post
Share on other sites
with my WndProc, how do i declare it to only use a Specified instance (i have m_hWnd defined as a Member Handle in my mWindow Class seems that this would be the easiest way, i did think that i needed to declare as virtual.


LRESULT CALLBACK mWindow::WndProc(HWND hWnd , UINT Msg, WPARAM wParam, LPARAM lParam)
{
switch(Msg)
{
case WM_DESTROY:
Close();
PostQuitMessage(WM_QUIT);
break;
case WM_CREATE:
break;
case WM_PAINT:
Render();
break;

default:
return DefWindowProc(hWnd, Msg, wParam, lParam);
}
return 0;
}

as I am new to the Win32 API I am not Familiar with other Methods use with message handling

Share this post


Link to post
Share on other sites
ok, so what i need to do is :

class myClass
{
void msgHandle(); //Contains code(a)
static LRESULT CALLBACK WndProc(...);
}

//
m_wcex.lpfnWndProc = &msgHandle



Share this post


Link to post
Share on other sites
Ok, so I read you code, and I think I can understand some(:P) of it
at the moment i get the following errors here

class mWindow
{
public:
//Other code emmited
void WndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);
static LRESULT CALLBACK StaticWndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);
}
LRESULT CALLBACK StaticWndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
if (LONG_PTR user_data = GetWindowLongPtr(hWnd, GWLP_USERDATA))
{
mWindow* this_window = reinterpret_cast<mWindow *>(user_data);
return this_window->WndProc(hWnd, Msg, wParam, lParam); // cannot return this
}
if (Msg == WM_NCCREATE)
{
LPCREATESTRUCT create_struct = reinterpret_cast<LPCREATESTRUCT>(lParam);
void * lpCreateParam = create_struct->lpCreateParams;
mWindow * this_window = reinterpret_cast<mWindow *>(lpCreateParam);
SetWindowLongPtr(hWnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(this_window));
return this_window->WndProc(hWnd, Msg, wParam, lParam); //Cannot return this
}

return DefWindowProc(hWnd, Msg, wParam, lParam);
}

1>c:\users\alex\documents\visual studio 2008\projects\win basics\win basics\mwindow.cpp(102) : error C2440: 'return' : cannot convert from 'void' to 'LRESULT'
1> Expressions of type void cannot be converted to other types
1>c:\users\alex\documents\visual studio 2008\projects\win basics\win basics\mwindow.cpp(110) : error C2440: 'type cast' : cannot convert from 'void' to 'LRESULT'
1> Expressions of type void cannot be converted to other types

Share this post


Link to post
Share on other sites
ok, i get another error with unresolved external signals if i declare WndProc as a LRESULT, (just so you know, i declared as void, as that's how you declared it in the other post as far as i could see)

1>mWindow.obj : error LNK2019: unresolved external symbol "public: static long __stdcall mWindow::StaticWndProc(struct HWND__ *,unsigned int,unsigned int,long)" (?StaticWndProc@mWindow@@SGJPAUHWND__@@IIJ@Z) referenced in function "public: __thiscall mWindow::mWindow(void)" (??0mWindow@@QAE@XZ)
1>mWindow.obj : error LNK2019: unresolved external symbol "public: long __thiscall mWindow::WndProc(struct HWND__ *,unsigned int,unsigned int,long)" (?WndProc@mWindow@@QAEJPAUHWND__@@IIJ@Z) referenced in function "long __stdcall StaticWndProc(struct HWND__ *,unsigned int,unsigned int,long)" (?StaticWndProc@@YGJPAUHWND__@@IIJ@Z)
1>C:\Users\Alex\Documents\Visual Studio 2008\Projects\Win Basics\Debug\Win Basics.exe : fatal error LNK1120: 2 unresolved externals

Share this post


Link to post
Share on other sites
Key phrases:
Quote:

LNK2019 ... unresolved external symbol ... mWindow::StaticWndProc

LNK2019 ... unresolved external symbol ... mWindow::WndProc

This means that the linker can't find the implementations of functions you have declared.

You will need to implement mWindow::WndProc, much like in your very first post, except you will now be calling member functions rather than static functions.

You need to qualify "StaticWndProc" as being a member function of Window:

class mWindow
{
public:

void WndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);

static LRESULT CALLBACK StaticWndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);

}; // <-- don't forget me

LRESULT CALLBACK mWindow::StaticWndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
// ...
}

If you are pasting code, use [source] and [/source] tags (or code tags for very short snippets) to get syntax highlighting and to preserve indentation.

Share this post


Link to post
Share on other sites
ok, thanks guys, one last question (I hope)

do i still keep the code in my WndProc, and is this still used when messages are called, or is all that messaging now handled in StaticWndProc()?

LRESULT CALLBACK mWindow::WndProc(HWND hWnd , UINT Msg, WPARAM wParam, LPARAM lParam)
{
switch(Msg)
{
case WM_DESTROY:
Close();
PostQuitMessage(WM_QUIT);
break;
case WM_CREATE:
break;
case WM_PAINT:
Render();
break;

default:
return DefWindowProc(hWnd, Msg, wParam, lParam);
}
return 0;
}

Share this post


Link to post
Share on other sites
ok, well whereas i have this code : called with the 'first' window message

if (Msg == WM_NCCREATE)
{
LPCREATESTRUCT create_struct = reinterpret_cast<LPCREATESTRUCT>(lParam);
void * lpCreateParam = create_struct->lpCreateParams;
mWindow * this_window = reinterpret_cast<mWindow *>(lpCreateParam);
SetWindowLongPtr(hWnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(this_window));
return this_window->WndProc(hWnd, Msg, wParam, lParam);
}

do i need to make one of these for the other messages WM_PAINT , WM_DESTORY Ect.?

Share this post


Link to post
Share on other sites
It depends. You *have* to respond to WM_NCCREATE in StaticWndProc to set up the pointer so you can retrieve it later. Whether you want to have a non-static WndProc is up to you. The advantage of making it a member function is that it can be made virtual do a derived class could override it (e.g. to handle additional message types or something).

Alternatively you could call the functions you want from StaticWndProc:

LRESULT CALLBACK StaticWndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
if (LONG_PTR user_data = GetWindowLongPtr(hWnd, GWLP_USERDATA))
{
mWindow* window = reinterpret_cast<mWindow *>(user_data);

switch(Msg)
{
case WM_DESTROY:
window->Close();
PostQuitMessage(WM_QUIT);
break;

case WM_CREATE:
// window->Whatever();
break;

case WM_PAINT:
window->Render();
break;

default:
return DefWindowProc(hWnd, Msg, wParam, lParam);
}
}
}


The advantage of doing it this way is that you don't need to define the additional WndProc member function. The two approaches are quite similar, so it is up to you which you want to use.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this