Archived

This topic is now archived and is closed to further replies.

Put NeHe's Tutorial in a Class

This topic is 5500 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi i''ve wanted to try to generate my own openGL Class with the functions from the tutorial. all works fine but the LRESULT CALLBACK WnDProc - Function will not work in my Class. When I trie to acces the WndProc function in CreateGLWindow() at the point: wc.lpfnWndProc = (WNDPROC) WndProc; I get an error: error C2440: ''type casT'' : '''' couldn''t be transfered in ''long (__stdcall *)(struct HWND__ *,unsigned int, unsigned int, long) Why do I get this error? How to fix it? kaepteniglo

Share this post


Link to post
Share on other sites
No, thx.

But now I got a lot of errors while compiling.

In the new CALLBACK WndProc-Function:

For example

illegal reference to a dataelement ''COGL::active'' in a static member function.

COGL is my Class-Name and active is one of the variables used by NeHe''s Tut.

kaepteniglo

Share this post


Link to post
Share on other sites
http://www.mvps.org/windev/cpp/class.html

An explanation on why it doesn''t work. I had a better link but I''ve lost it.

Afaik there are two ways to solve the problem. One of them is what Crispy suggested and involves making the callback static. The problem is that a static member fuction is not bound to a specific object and thus does not have a ''this'' pointer. That''s why you get the new error. The link above explains (in short) how to solve it. Another solution involves making the callback a friend of your class instead of making it part of it.

Share this post


Link to post
Share on other sites
quote:
Original post by kaepteniglo
No, thx.

But now I got a lot of errors while compiling.

In the new CALLBACK WndProc-Function:

For example

illegal reference to a dataelement ''COGL::active'' in a static member function.

COGL is my Class-Name and active is one of the variables used by NeHe''s Tut.

kaepteniglo


is active a public or private variable.
If its private, then you can''t access it outside your class.
Only the functions inside your class can access it.
Either make it public or make a public function GetActiveVariable() that returns the value of active.

Share this post


Link to post
Share on other sites
quote:

is active a public or private variable.
If its private, then you can''t access it outside your class.
Only the functions inside your class can access it.
Either make it public or make a public function GetActiveVariable() that returns the value of active.




ah, no

the reason you get:

illegal reference to a dataelement ''COGL::active'' in a static member function.

is because the member is just that, a member of an instance of a class. A static function is basically the same as a C function in that you can call it anywhere without an actual object to call from
eg:

COGL::staticFunctionName();

would be fine anywhere, instead of:

COGL ogl;
ogl.normalFunctionName();

This should make it pretty obvious that you can''t access a member of a class in a static function because the this pointer does not exist.
ie, you can call the function without ever actually making a COGL object... Hence how can the members of a COGL object possibly be accessed when non have been created?

it''s hard to discribe.

btw, don''t fix this by making the members static. You will just fall into a bigger and bigger hole if you do that, not understanding the meaning of what your doing. (You also have to declare static members outside of a class declaration so their initial values can be set, which will lead to more compiler errors if you don''t know what your doing)

Share this post


Link to post
Share on other sites
Hi, thx 4 your help.

now I can use the Callback-Function.

But now I have some other Problems.

My Callback is:

LRESULT CALLBACK COGL::WndProc(HWND hWnd,UINT uMsg,WPARAM wParam, LPARAM lParam)
{
COGL *ogl = new COGL;

switch (uMsg) {
case WM_ACTIVATE: {
if (!HIWORD(wParam)) {
ogl->active=TRUE; }
else
{
ogl->active=FALSE; }

return 0; }
case WM_SYSCOMMAND: {
switch (wParam) {
case SC_SCREENSAVE: case SC_MONITORPOWER: return 0; }
break; }
case WM_CLOSE: {
PostQuitMessage(0); return 0; }
case WM_KEYDOWN: {
ogl->keys[wParam] = TRUE; return 0; }
case WM_KEYUP: {
ogl->keys[wParam] = FALSE; return 0; }
case WM_SIZE: {
ogl->ReSizeGLScene(LOWORD(lParam),HIWORD(lParam)); return 0; }
}
return DefWindowProc(hWnd,uMsg,wParam,lParam);
}

When the program runs, and I press the F1-Key (to resize screen) nothing happens.

I got the error keys[]: no this operator when i debug the program.

I think keys and other commands doesn't get the wParam argument.

Why?

kaepteniglo

[edited by - kaepteniglo on November 21, 2002 4:33:05 AM]

Share this post


Link to post
Share on other sites
Could you explain why you create a new instance of COGL in the callback?
I hope you have understood the problem.

You can't make the callback a regular member-function, because it won't fit the specified callback declaration. This is because a member-function carries an invisible 'this-pointer'.
A member-function needs the 'this-pointer' to access it's member variables. A static member-function has no 'this-pointer'. So if you make the callback static you have solved that particular problem. But you now have a new problem. You want to be able to access your member functions/variables from your callback, right? To do this you need the 'this-pointer'. The very thing we just got rid of! What we need to do is somehow store the 'this-pointer' in a place where we can access it from the callback.

How to do this is explained in the links I supplied in previous posts. The explanations in those are unfortunatly not as clear as those in the article I had when I learned this. But as I said earlier, I can't find it again

Anyway, if I remember correctly, these are the steps you need to do.

1. You should pass your 'this-pointer' in the last parameter in CreateWindowEx.


  
CreateWindowEx(
...,
...,
.
.
(void*)this
);


2. In WM_NCCREATE, lParam consists of a CREATESTRUCT. The 'lpCreateParams' member of CREATESTRUCT will now contain your 'this-pointer'.
Fetch it and store it in thw windows userdata area. That way you can get the 'this-pointer' whenever you need it.


  
COGL *wnd;
if(message == WM_NCCREATE)
{
// Fetch the 'this pointer'

wnd = (COGL*)(((LPCREATESTRUCT)lparam)->lpCreateParams);

// and store it in your windows userdata.

::SetWindowLong(hwnd, GWL_USERDATA, (long)(wnd));
}


3. Later, whenever you need the 'this-pointer' you can get it from the windows extra data. Like this.


  
wnd = (COGL*)(::GetWindowLong(hwnd, GWL_USERDATA));

// Now you can use 'wnd' to access your member variables/functions

wnd->ReSizeGLScene(LOWORD(lParam),HIWORD(lParam));


Btw I don't know if this code will compile, I took the code from the gamedev tutorial, and simplified it(took away the reinterpret_cast).

[edited by - lowlevel on November 22, 2002 8:52:46 AM]

Share this post


Link to post
Share on other sites