Want to win a PS4? Go Premium and enter to win our High-Tech Treats giveaway. Enter to Win

x
?
Solved

C++, OOP, my Windowing class structure question.

Posted on 2001-06-20
7
Medium Priority
?
302 Views
Last Modified: 2010-04-02
I've written a class to create windows which can then have OpenGL graphics put in them.

My current project consists of 3 files:
CWindow.cpp
CWindow.h
Main.cpp

Right now, CWindow.h has a function prototype for LRESULT CALLBACK msgHandler(...), which is my message handling function.  The message handler is located in Main.cpp, along with the functions to draw an OpenGL scene.  I want to move the message handler into the CWindow file somehow, to encapsulate my windows better.  Unfortunately, I can't get this to work, the program just crashes (Gives me a windows messagebox saying program has performed an illegal operation).

It would be nice if I could make the message handler a member function or something.  The problem is that because the handler is just a function in CWindow.cpp, it can't access the class members like member functions can.

In my current implementation with the msg handler in Main.cpp, I have created a global CWindow pointer (globWin), and then in the message handler I have code like:

CASE WM_ACTIVATE:
{
if (globWin->bActive == TRUE)
.
.
.
}

I don't know what to do if I put the message handler in the class file.  Could I make the message handler a friend function and then use the THIS pointer in place of globWin?
0
Comment
Question by:Sketchy
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
7 Comments
 

Author Comment

by:Sketchy
ID: 6212391
Oh BTW if I do it this way will it be possible to overload the message handler for a child class of CWindow (say a window that has some special features or something, maybe even for a button class)
0
 
LVL 30

Expert Comment

by:Axter
ID: 6212566
Post the code.
0
 
LVL 5

Expert Comment

by:garboua
ID: 6212671
well, you should have a method to update and fetch all your class members.  our message handler can call the appropriate function, class member function.
0
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 

Author Comment

by:Sketchy
ID: 6212901
As per Axter's request, here is the code (its too big for me to post right here).

http://members.home.net/l-reynolds/newCode.zip

I've spiffed up the code a bit so that its easier to follow.

I've seen some code that does what I want, but its hard to understand.  Basically rather that using classes, the dude used a struct, then he added that as additional info when he called CreateWindowEx  (the last parameter), then in his message handler, he extracted the struct data(containing the variables, but NO functions) using GetWindowLong or something like that, put that data into a new temporary struct, and then used the temp struct members in the message handler.  

I tried putting a struct inside my class which contained all the member variables, and it seemed to work, except in my ToggleFullscreen member function it would crash on the SetWindowLong part (I think it had issues with putting the new hWnd data into the struct or something like that).  So I gave up on that.

I then had this great (I thought) idea.  I created a struct, who's only component was a pointer to a CWindow.  Then in CWindow, I added an instance of the struct. When i called CreateWindowEx, I used that struct as the additional component (last parameter), and then in the message handler I tried to extract that struct to access the object, but I just couldn't get it to work.  I think the main problem was that at some point i needed to set the structs pointer variable equal to the current object.  I tried using this->struct->objpointer = this and stuff but it just crashed.

Sorry for the long post wow.

--Thx in advance

0
 

Accepted Solution

by:
wkmatt42 earned 500 total points
ID: 6216785
If all you want to do is associate your class with a window handle, you can do this after you create the window using the API function SetWindowLong as follows:

::SetWindowLong(hwnd, GWL_USERDATA, (LONG)pWindow);

Then, in your message handler, you fetch a pointer to the class associated with a window:

CWindow* pWindow = (CWindow*)::GetWindowLong(hwnd, GWL_USERDATA);

You can then call methods of CWindow directly.

To encapsulate you message handler, you can either create a message handler method in your class and call it from the main window handler. Alternatively, you can create a static method in your class to do the message handling. I prefer the latter since it avoids the need for a global variable or a global message handler.

For example:

class CWindow
{
public:
    static LRESULT CALLBACK msgHandler( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam );

    ...
};

When you register your window class (using RegisterClassEx), set wc.lpfnWndProc to (WndProc)msgHandler.

Check the API documentation for SetWindowClass and GetWindowClass if any of that was confusing.

- Matt
0
 

Author Comment

by:Sketchy
ID: 6217473
Thanks Matt, that's just what I wanted hehe.  I tried doing something very similar but I was stupid because I put it in the RegisterWindowClass function, rather than at the end of the constructor.


Basically, here is what I had to do to get it to work:

1) put msgHandler in class as a static member
2) put that CWindow* pWindow = (CWindow*)::GetWindowLong(hwnd, GWL_USERDATA); at the top of the message handler
3) put SetWindowLong(hwnd, GWL_USERDATA, (LONG)this) at the end of the constructor

:) :) :)
0
 
LVL 30

Expert Comment

by:Axter
ID: 6218050
Hi Sketchy,
If wkmatt42 answered your question, can you please convert his comment to an answer, so your question will get moved out of the un-answered list.

Thanks
0

Featured Post

What’s Wrong with Your Cloud Strategy ?

Even as many CIOs are embracing a cloud-first strategy, the reality is that moving to the cloud is a lengthy process and the end-state is likely to be a blend of multiple clouds—public and private. Learn why multicloud solutions matter in this webinar by Nimble Storage.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Written by John Humphreys C++ Threading and the POSIX Library This article will cover the basic information that you need to know in order to make use of the POSIX threading library available for C and C++ on UNIX and most Linux systems.   [s…
Go is an acronym of golang, is a programming language developed Google in 2007. Go is a new language that is mostly in the C family, with significant input from Pascal/Modula/Oberon family. Hence Go arisen as low-level language with fast compilation…
The goal of the video will be to teach the user the concept of local variables and scope. An example of a locally defined variable will be given as well as an explanation of what scope is in C++. The local variable and concept of scope will be relat…
The viewer will learn how to user default arguments when defining functions. This method of defining functions will be contrasted with the non-default-argument of defining functions.

636 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question