Member functions as child window procedures

This is a discussion on Member functions as child window procedures within the Windows Programming forums, part of the Platform Specific Boards category; Hi all, In the situation that you create a class to represent a child window, how do you deal with ...

  1. #1
    Registered User filler_bunny's Avatar
    Join Date
    Feb 2003
    Posts
    87

    Member functions as child window procedures

    Hi all,

    In the situation that you create a class to represent a child window, how do you deal with the windows procedure for the child class in an OOP sense?

    The difficulty I am having is that I cannot use a member function from this class as the windows procedure. i.e.

    Code:
    class ChildWindow
    {
        public:
            ChildWindow();
             LRESULT CALLBACK ChildWndProc(HWND, UINT, WPARAM, LPARAM);
    };
    So how is it done? Friend functions? or wha?

    Cheers.
    Visual C++ .net
    Windows XP profesional

  2. #2
    Even death may die... Dante Shamest's Avatar
    Join Date
    Apr 2003
    Location
    Malaysia
    Posts
    970
    The class should have a static window procedure, which redirects to each window's instance window procedure.

  3. #3
    Registered User filler_bunny's Avatar
    Join Date
    Feb 2003
    Posts
    87
    Thanks for the quick reply, I just want to clarify what your saying! It seems to work..

    So, you would have a static windows procedure as a member of my window class...
    Code:
    static LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
    {
        return ChildWndProc(hwnd, msg, wParam, lParam);
    }
    Which in turn calls another function that was declared at global scope.
    Code:
    LRESULT CALLBACK ChildWndProc(HWND, UINT, WPARAM, LPARAM)
    {
        [...]
    }
    Visual C++ .net
    Windows XP profesional

  4. #4
    Even death may die... Dante Shamest's Avatar
    Join Date
    Apr 2003
    Location
    Malaysia
    Posts
    970
    No, I meant letting your static member function redirect to each window's instance member function.

    I'm not sure what your end-goal is though, so whatever I'm saying here might not apply.
    Last edited by Dante Shamest; 03-04-2004 at 04:54 AM.

  5. #5
    Registered User filler_bunny's Avatar
    Join Date
    Feb 2003
    Posts
    87
    Well, I was just trying to write a class that I could use to create a child window of a main parent window.

    This child window has it's own windows procedure.

    During the initialisation of the windows class, I was trying to set the windows procedure:

    wcx.lpfnWndProc = WndProc;

    where WndProc is a member function of the class - but that is not possible. So I guess I am asking, how do you do it?

    I guess I am not getting this:
    instance member function.
    What do you mean?
    Visual C++ .net
    Windows XP profesional

  6. #6
    Even death may die... Dante Shamest's Avatar
    Join Date
    Apr 2003
    Location
    Malaysia
    Posts
    970
    When you say "child" window, are you talking about a child window like a button or an edit control?

    Or are you talking a window owned by the owner window, like a dialog box?

    >> instance member function.

    A class method that is not static.

    >> where WndProc is a member function of the class - but that is not possible. So I guess I am asking, how do you do it?

    Just use a static member function then. No need for it to call a global function.

  7. #7
    Registered User filler_bunny's Avatar
    Join Date
    Feb 2003
    Posts
    87
    When you say "child" window, are you talking about a child window like a button or an edit control?
    Not quite, it is another client area that sites on the surface. Think of how MS Paint splits the windows into different segments, or child windows. Each with its own message procedure. (See attached image - each side is it's own window - I was going to have buttons on the left client area, and render graphics to the right client area).

    >> where WndProc is a member function of the class - but that is not possible. So I guess I am asking, how do you do it?

    Just use a static member function then. No need for it to call a global function.
    Code:
    LRESULT CALLBACK CChildWindow::MyProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
    {
    	switch(msg)
    	{
    	case WM_DESTROY:
    		PostQuitMessage(0);
    		return 0;
    	}
    	return DefWindowProc(hwnd, msg, wParam, lParam);
    }
    Well, this compiles - I am not sure why I didn't try this earlier. MyProc is declared as a static member function.. This would be the correct way to do this?

    Thanks for all your help again.
    Attached Images Attached Images  
    Visual C++ .net
    Windows XP profesional

  8. #8
    Even death may die... Dante Shamest's Avatar
    Join Date
    Apr 2003
    Location
    Malaysia
    Posts
    970
    MyProc is declared as a static member function.. This would be the correct way to do this?
    Yes. WNDPROC needs the address of the procedure to be a global or static one.

  9. #9
    Registered User filler_bunny's Avatar
    Join Date
    Feb 2003
    Posts
    87
    Sweet, thank you very much for your help / patience.
    Visual C++ .net
    Windows XP profesional

  10. #10
    Registered User filler_bunny's Avatar
    Join Date
    Feb 2003
    Posts
    87
    So - just another question.

    All member functions or objects within the class that are to be used within the static windows procedure would also have to be static?

    I mean the answer is obvious, they would have to be. But is the best way to do it? How do other programmers out there do it? Would they instead use a global windows procedure for their child windows that wraps a method within the class?

    Cheers,

    FB
    Visual C++ .net
    Windows XP profesional

  11. #11
    erstwhile
    Join Date
    Jan 2002
    Posts
    2,227
    That's one way. A more common approach is to pass this as the last parameter of CreateWindowEx and set/retrieve it within the static wndproc and use it to forward messages to a non-static 'window procedure' member function.

    Here's an offsite description but ignore the last couple of sentences because they're incorrect (GWL_USERDATA is available for dialog use; DWL_USER is just an 'extra' for dialogs).

    This topic has been discussed quite a lot here in the past and a review of some of those discussions may also be of some interest to you (I haven't checked them all for relevance):

    W32 message routing
    Error: "illegal call of non-static member function"
    Skeleton Window: Message Handler in a Class?
    Classes and static call back procedures
    thread contains very simple example
    more static/class problems
    deriving a class with a wndproc
    subclassing a wndproc from within a class
    WM_NCCREATE problem...
    reducing global variables in windows programs
    Last edited by Ken Fitlike; 03-07-2004 at 04:36 AM.
    CProgramming FAQ
    Caution: this person may be a carrier of the misinformation virus.

  12. #12
    Registered User filler_bunny's Avatar
    Join Date
    Feb 2003
    Posts
    87
    Thanks for the links.. look, i've been through this a hundred times and I just can't see what i am doing wrong.

    I create the window...
    Code:
    hwnd = CreateWindowEx(0,
     		              TEXT("ChildClass"),
    			      TEXT(""),
    			      WS_CHILDWINDOW | WS_VISIBLE,
    			      0, 0,
    			      100, 100,
    			      hParent,
    		              NULL,
    			      hInstance,
    			      this);
    And then I try to get the data.. in the WM_CREATE message, WM_NCCREATE, prior to processing any messages. It doesn't matter how I go about it I just can't get the pointer to the class! Any ideas?
    Code:
    	CChild *child = 0; 
    	child = (CChild *)GetWindowLong(hwnd, GWL_USERDATA);
    Looking under the debugger, child is not set - I have tried everything but I can't get the value back. Any ideas...
    Visual C++ .net
    Windows XP profesional

  13. #13
    &TH of undefined behavior Fordy's Avatar
    Join Date
    Aug 2001
    Posts
    5,789
    >>CChild *child = 0;

    For a start, you are going to want to make this static or global. Otherwise the variable will fall out of scope as soon as another message is processed

  14. #14
    Registered User filler_bunny's Avatar
    Join Date
    Feb 2003
    Posts
    87
    Yes true, but it doesn't make a difference in this case since I have also tried setting the value of child and then using it immediately after while the variable is still in scope...

    I just can't wrap my head around this. Is there some kind of trick to doing this? Can you obtain the pointer while processing any message and using GetWindowLong?
    Visual C++ .net
    Windows XP profesional

  15. #15
    erstwhile
    Join Date
    Jan 2002
    Posts
    2,227
    Originally posted by filler_bunny
    Thanks for the links.. look, i've been through this a hundred times and I just can't see what i am doing wrong.
    That's easy - you're not reading up on the information provided to you Those links I suggested, in particular the 'offsite description' and the 'simple example', should have given you more than enough information to both recognise and solve your latest problem.

    Still, it may be that you just can't see the wood for the trees just now so...

    1. Passing this as CreateWindowEx just makes this available - it doesn't magically associate it with the window. You have to do that yourself.

    2. If the result of GetWindowLongPtr is NULL then you need to use SetWindowLongPtr to associate this with your window. This is typically done in WM_NCCREATE (or WM_INITDIALOG for a dialog)as it's the first place you have access to this through the CREATESTRUCT passed as the LPARAM to your (static) window procedure.

    3. If GetWindowLongPtr returns a non-NULL value you can cast it to your c++ class pointer and use that pointer accordingly.

    ie
    Code:
    CChild *child = (CChild *)GetWindowLongPtr(hwnd, GWL_USERDATA);
    if (!child)
      {
      /*need to attach 'this' to window*/
      /*assuming WM_NCCREATE msg:*/
      CREATESTRUCT *cs=(CREATESTRUCT*)lParam;
      child=(CChild*)cs->lpCreateParams;
      /* next step is the one you're missing*/
      SetWindowLongPtr(hwnd, GWL_USERDATA, (LONG_PTR) child);
      }
    else
      {
      /* ptr's good so do stuff normally */
      }
    CProgramming FAQ
    Caution: this person may be a carrier of the misinformation virus.

Page 1 of 2 12 LastLast
Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Linking OpenGL in Dev-C++
    By linkofazeroth in forum Game Programming
    Replies: 4
    Last Post: 09-13-2005, 10:17 AM
  2. Problem with Visual C++ Object-Oriented Programming Book.
    By GameGenie in forum C++ Programming
    Replies: 9
    Last Post: 08-29-2005, 11:21 PM
  3. Pong is completed!!!
    By Shamino in forum Game Programming
    Replies: 11
    Last Post: 05-26-2005, 10:50 AM
  4. OpenGL and Windows
    By sean345 in forum Game Programming
    Replies: 5
    Last Post: 06-24-2002, 10:14 PM
  5. Tab Controls - API
    By -KEN- in forum Windows Programming
    Replies: 7
    Last Post: 06-02-2002, 09:44 AM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21