Thread: WindowProc in a class

  1. #1
    Registered User
    Join Date
    Aug 2001
    Posts
    41

    WindowProc in a class

    Hi everybody,

    I had a question, and I guess it is about conversions too. I'm building a class that handles my own GUI, and now I want it to handle the messages posted to the window it belongs to. So I thought I could subclass it. But I can't set the windowproc of the window to a member of the class, I keep getting a conversion error:

    c:\program files\visual studio\vc6\projecten\gui test\guiclass.cpp(40) : error C2440: 'type cast' : cannot convert from 'long (__cdecl ClsGUI::*)(struct HWND__ *,unsigned int,unsigned int,long)' to 'long'
    Conversion is a valid standard conversion, which can be performed implicitly or by use of static_cast, C-style cast or function-style cast

    with the code

    SetWindowLong(hWnd, GWL_WNDPROC, (long)windowProc);

    where windowProc is a member of the GUI class.

    Is there a way to do this? Or is it impossible, because of the way classes work? The members have addresses don't they? Then why can't I pass it to the function? Or am I mistaking and don't classes work this way?
    And should I use a class for this type of thing? I guess I'm sort of remaking the Windows API, but I wanted to keep it simple and encapsule it in a class. Should I forget about the class and just use functions? (I guess you won't need more than one instance of the GUI class anyway...)

    and BTW should I restrict the maximum frames per second?

    Joren

  2. #2
    of Zen Hall zen's Avatar
    Join Date
    Aug 2001
    Posts
    1,007
    Your callback function wont match the function required due to the hidden this pointer (an extra argument). Check this link for some tips on how to get around it.
    zen

  3. #3
    Registered User
    Join Date
    Aug 2001
    Posts
    41
    Thanks a lot!!!

    I already found out that pointers to members work diffirently than normal pointers, but I didn't find a way around this yet. That link was really helpfull.

    One thing I don't understand:

    The above mentioned solutions are the easiest ways to get around this problem, but are not the only ones. If you're good in assembly (which I'm not, so I'm not even going to try and explain it), you can write a little stub that allows you to use a non static member function as a callback. For this you need to write a piece of inline assembly in a static member of the class, and use it as callback. This stub then handles parameters to the *real* non static member that does the real work. This is very similar to what Microsoft's own Active Template Library (ATL) does for it's window procedure implementation.
    I don't get how you can use a non static member function as a callback and then give another *real* (???) non static member the focus without using another var with the pointer to the class.
    Just curious...

    [edit]
    And what kind of protection has the static member got to (or can) have?
    [/edit]

    Joren
    Last edited by Mox; 10-24-2001 at 02:54 PM.

  4. #4
    of Zen Hall zen's Avatar
    Join Date
    Aug 2001
    Posts
    1,007
    I don't get how you can use a non static member function as a callback and then give another *real* (???) non static member the focus without using another var with the pointer to the class.
    Just curious...
    I've no idea how it works as it's pretty advanced, but this is how it's done in ATL (ATL thunks) -

    Code:
     class CWndProcThunk
    {
    public:
    	union
    	{
    		_AtlCreateWndData cd;
    		_WndProcThunk thunk;
    	};
    	void Init(WNDPROC proc, void* pThis)
    	{
    #if defined (_M_IX86)
    		thunk.m_mov = 0x042444C7;  //C7 44 24 0C
    		thunk.m_this = (DWORD)pThis;
    		thunk.m_jmp = 0xe9;
    		thunk.m_relproc = (int)proc - ((int)this+sizeof(_WndProcThunk));
    #elif defined (_M_ALPHA)
    		thunk.ldah_at = (0x279f0000 | HIWORD(proc)) + (LOWORD(proc)>>15);
    		thunk.ldah_a0 = (0x261f0000 | HIWORD(pThis)) + (LOWORD(pThis)>>15);
    		thunk.lda_at = 0x239c0000 | LOWORD(proc);
    		thunk.lda_a0 = 0x22100000 | LOWORD(pThis);
    		thunk.jmp = 0x6bfc0000;
    #endif
    		// write block from data cache and
    		//  flush from instruction cache
    		FlushInstructionCache(GetCurrentProcess(), &thunk, sizeof(thunk));
    	}
    };
    I'm not sure what you mean by protection but as you'll be passing the this pointer in as the extra data it should be ok.
    zen

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Class design problem
    By h3ro in forum C++ Programming
    Replies: 10
    Last Post: 12-19-2008, 09:10 AM
  2. Specializing class
    By Elysia in forum C++ Programming
    Replies: 6
    Last Post: 09-28-2008, 04:30 AM
  3. matrix class
    By shuo in forum C++ Programming
    Replies: 2
    Last Post: 07-13-2007, 01:03 AM
  4. Screwy Linker Error - VC2005
    By Tonto in forum C++ Programming
    Replies: 5
    Last Post: 06-19-2007, 02:39 PM