Jump to content
  • Advertisement

Archived

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

guppy

Defeated by windows....

This topic is 5995 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

I''ve been writing a windows OO-wrapper class in C++ so that i can just write : window window("name",640,480); // or what ever... now that works perfectly! I thougth that it migth be nice to be able to add event handlers to the window (ala. the way its done i Java). Ofcourse this made my program crash before the window was drawn... After days of debugging I found out that it was not the event handler code that was at fault but rather somthing quite wierd.
  

//This one would normaly find the approiate eventhandler...

long glWindow::callEventHandler(long glwowner, long event, WPARAM wParam, LPARAM lParam)
{
  return -1;
}

//Wrapped non static WndProc


LRESULT CALLBACK glWindow::glWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{

    switch (message)
    {
        case WM_CREATE:
        {
                this->hDC = GetDC(hwnd);
                SetupPixelFormat();                
                this->hRC = wglCreateContext(this->hDC);
                wglMakeCurrent(this->hDC,this->hRC);
                return 0;
                break ;                      
        }
        case WM_CLOSE:
        {
             KillWindow();
             PostQuitMessage(0);
                return 0;
                break ;                      
        }
        default:
                //long l = (this->callEventHandler(long_this, (long)message, wParam, lParam));

                long l = -1;
                if ( l == 0 )             
                   return 0;  
                else
                   return DefWindowProc(hwnd,message,wParam,lParam);
                break ;                 
    }
  
the above runs nicely - no errors but when I uncomment the line "long l = (this->...", comment the line "long l = -1;", rebuilds and run I get the windows error "Program Error OGL_window.exe has generated errors and wil be closed by windows. You need to restart the program. An error log is beeing created." after a lot of hair pulling I find out that by substituting long_this with 0 the program works fine... long_this is defined as: long long_this; in the constructor it is normaly set to: long_this = reinterpret_cast(this); ofcourse I imediately suspected the reinterp cast and set it to long_this = 0; but alas same error and still fixable by substituting long_this by 0 when calling the eventHandler... (the only place long_this is used..) Any ways I must admit my defeat - I simply have no clue as to why a var could crash my progamm.... (as a side note : I need the pointer since eventhandling code migth handle events from more that one window...) Hope someone can figure this one out... /Please excuse my bad spelling - My native language is binary not english |Visit me \Take my advice - I don''''t use it...

Share this post


Link to post
Share on other sites
Advertisement
The general way of passing a ''this'' pointer to your wndproc is to use the SetWindowLongPtr() and GetWindowLongPtr() functions. Just allocate ''extra'' per-instance space for each window when you register your window class by setting cbWndExtra to sizeof(long). Then call SetWindowLongPtr(hwnd, 0, (LONG_PTR)this) to set the value.

In your wndproc, use GetWindowLongPtr(hwnd, 0) to get the pointer to your class. Make sure you test the result to see if you get NULL back, there are a few messages that are received before the value is set.

The other option is to create a global std::map and do a lookup in your message handler, but using the extra window space should be faster and looks a little cleaner.

Good luck.

Share this post


Link to post
Share on other sites
quote:
Original post by JonStelly
The general way of passing a ''this'' pointer to your wndproc is to use the SetWindowLongPtr() and GetWindowLongPtr() functions. Just allocate ''extra'' per-instance space for each window when you register your window class by setting cbWndExtra to sizeof(long). Then call SetWindowLongPtr(hwnd, 0, (LONG_PTR)this) to set the value.

In your wndproc, use GetWindowLongPtr(hwnd, 0) to get the pointer to your class. Make sure you test the result to see if you get NULL back, there are a few messages that are received before the value is set.

The other option is to create a global std::map and do a lookup in your message handler, but using the extra window space should be faster and looks a little cleaner.

Good luck.


From the above responce I can see I have failed to formulate my question Clearly.

Everything works perfectly, until I try to call my event handler from INSIDE my wndproc (the wndproc is unique to each and every object - I know how to do this , it works and is not the problem).

So the problem is either:

1) some wierd ass compiler error relating to the long ''long_this'' (im using Dev-C++ 4.9.4.0 / MingW 2.1)

2) maybe it is not allowed to call other functions outside the wndproc...



/Please excuse my bad spelling - My native language is binary not english
|Visit me
\Take my advice - I don''''t use it...

Share this post


Link to post
Share on other sites
Just for interest, I have found that the book "C++ in Action" has a good description of writing C++ wrappers for the win32 API and is even available online at relisoft!

Share this post


Link to post
Share on other sites
This is more of a suggestion, but if you''re providing a way to handle all messages inside a class, why would you want to have a different wndproc for each window? One of the best benefits of writing a window class is that if you get the message handling correct you should be able to derive from your base window class to get whatever functionality you''re looking for.

But to your current problem, how about you post the whole header and implementation files for your window class, and post your static wndproc function that calls your class specific wndproc.

I''m guessing that the problem is in your static wndproc function. However you''re getting the ''this'' pointer, perhaps you''re not checking for NULL?

Share this post


Link to post
Share on other sites
quote:
Original post by JonStelly
This is more of a suggestion, but if you''re providing a way to handle all messages inside a class, why would you want to have a different wndproc for each window?



with a static wndProc you cannot store HWND, x dim, ydim, name, etc...
and since things like resize, quit, change to fulscreen is allways the same (but need some non static information) ive chosen to hardcode it...



quote:

But to your current problem, how about you post the whole header and implementation files for your window class, and post your static wndproc function that calls your class specific wndproc.

I''m guessing that the problem is in your static wndproc function. However you''re getting the ''this'' pointer, perhaps you''re not checking for NULL?


You are just not going to belive me are you? there is notthing wrong with that code -> when is remove the code to do dynamic event handling the window works perfectly. (im not going to post my entire code here since it is 800+ lines and I know where the error occour - just not why. wich btw is my question)


and btw, my static wndproc is a part of the object - rather nice


  
//in the glWindow.h

static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);

//in glWindow.cpp

LRESULT CALLBACK glWindow::WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{

glWindow *self = 0; //as oposed to ''this'' ;)


if(message == WM_NCCREATE)
{ // if the window is just beeing created we need to store window handle our self..

// don''t ask - nobody seem to know why - except that it wont get set otherwise...

self = reinterpret_cast<glWindow *>(((LPCREATESTRUCT)lParam)->lpCreateParams);
SetWindowLong(hwnd, GWL_USERDATA, reinterpret_cast<long>(self));
// save window handle

self->hwnd=hwnd;
}
else
self = reinterpret_cast<glWindow *>(::GetWindowLong(hwnd, GWL_USERDATA));

//now call the real message handler!

return self->glWndProc(hwnd, message, wParam, lParam);
}





/Please excuse my bad spelling - My native language is binary not english
|Visit me
\Take my advice - I don''''t use it...

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
I don''t think you understand callback methods. They are static and can''t exist for individual objects. They have no this pointer.

Cheers
Chris

Share this post


Link to post
Share on other sites
quote:
Original post by Anonymous Poster
I don''t think you understand callback methods. They are static and can''t exist for individual objects. They have no this pointer.

Cheers
Chris


*sigh*

the WndProc (the callback method) is the same for all objects - it then gets the address of the obejct from GWL_USERDATA (you stored it there when creating the window), cast it as an object of the correct type and invokes the obejcts specific message handler.

please stop replying unless you actualy READ the previous posts...



Ahh well just foget about it, ill try and solve the problem on my own....

/Please excuse my bad spelling - My native language is binary not english
|Visit me
\Take my advice - I don''''t use it...

Share this post


Link to post
Share on other sites
You''re only testing for WM_NCCREATE. You''re assuming GetWindowLongPtr() is returning the correct value otherwise, which it won''t. The value you set with SetWindowLongPtr() is cached and won''t be updated until the window is resized or created. So the value you get from GetWindowLongPtr() will return NULL until it gets one of those messages, and there are several that get handled BEFORE WM_CREATE other than WM_NCCREATE.

Next time you ask for help, try not to treat someone like they''re not as smart as you for trying to help. If you were really all that smart, you would have figured this out in a couple hours, not a couple days.

Cheers.


  
LRESULT CALLBACK glWindow::WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam){
glWindow *self = 0; //as oposed to ''this'' ;)

if(message == WM_NCCREATE)
{
// if the window is just beeing created we need to store window handle our self..

// don''t ask - nobody seem to know why - except that it wont get set otherwise...

self = reinterpret_cast<glWindow *>(((LPCREATESTRUCT)lParam)->lpCreateParams);
SetWindowLong(hwnd, GWL_USERDATA, reinterpret_cast<long>(self));
// save window handle

self->hwnd=hwnd;
}
else
{
self = reinterpret_cast<glWindow *>(::GetWindowLong(hwnd, GWL_USERDATA));
}

if(self != NULL)
{
return self->glWndProc(hwnd, message, wParam, lParam);
}
else
{
return DefWindowProc(hwnd, message, wParam, lParam);
}
}

Share this post


Link to post
Share on other sites
quote:
Original post by JonStelly
You''re only testing for WM_NCCREATE. You''re assuming GetWindowLongPtr() is returning the correct value otherwise, which it won''t. The value you set with SetWindowLongPtr() is cached and won''t be updated until the window is resized or created. So the value you get from GetWindowLongPtr() will return NULL until it gets one of those messages, and there are several that get handled BEFORE WM_CREATE other than WM_NCCREATE.

Next time you ask for help, try not to treat someone like they''re not as smart as you for trying to help. If you were really all that smart, you would have figured this out in a couple hours, not a couple days.

Cheers.



I must admit I was a bit grumpy in my previous replys - Im just a bit tired of ppl not beleaving me


While your last post makes sense it handles a event that through out my days of debugging have not occoured..

the problem ocours inside the wnd proc that i call with this line...

self->glWndProc(hwnd, message, wParam, lParam);

im none to shure about it but it seems that the problem is that there is a limit to how deep you method calls can be inside a CALLBACK function... :|

ps: ill be sure to keep a more civil tounge in my future replys (but please do read the previous posts anyways)



/Please excuse my bad spelling - My native language is binary not english
|Visit me
\Take my advice - I don''''t use it...

Share this post


Link to post
Share on other sites

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!