How to access a non-static function from within a static one

Started by
6 comments, last by Subotron 21 years, 3 months ago
My windowproc function is a part of my window class. Windowproc is forced to be static, so I made it like that. My problem is now that I cannot access the non-static functions from other classes. (If I want to destroy the app from within windowproc (say if you get a destroy message) I cannot call App->Destroy() Renderer->Destroy() etc) Is there a way to solve this? I think making all the destroy and other needed functions static is not the right way... that''d make everything very complicated... Thanks in advance!
Advertisement
I see two simple methods :

- store a pointer to the instance of your class inside the Win32 windows with SetWindowLong(HWND window, int index, LONG value) and then you can retrieve it with GetWindowLong(HWND window, int index) inside your winproc, then convert it with reinterpret_cast<>. Don''t forget to modify the value of the WNDCLASS structure of your window class to accept extra data. See MSDN for further info.
The drawback may be the reinterpret_cast<> especially with virtual inheritance.

- create a global std::map that store a pointer of your instance keyed with the handle of the win32 window.
The drawback here may be having a global, and having an additionnal instance to manage.



----
David Sporn AKA Sporniket
Have an argument of the static function be a pointer to an instance of the class.

class base {
static void somethingStatic(base* pObject, ...);
virtual void somethingDynamic(...);
}

somethingStatic calls somethingDynamic on pObject.
quote:Original post by petewood
Have an argument of the static function be a pointer to an instance of the class.


In this case it''s not possible, as the definition of WindowProc is out of our control...
To our point of view, it''s a third party API.


----
David Sporn AKA Sporniket
what''s the signature? isn''t it possible to get a pointer to the specific object somehow?
I''ve just copied this code out of an article in cuj.com. The full code is available in the August 2000 zip file under the name Hanov (Steve)


  class CWindow{public:    CWindow();protected:    static LRESULT CALLBACK BaseWndProc(HWND hwnd, UINT msg,        WPARAM wParam, LPARAM lParam);        virtual LRESULT WindowProc(HWND hwnd, UINT msg,        WPARAM wParam, LPARAM lParam, PBOOL pbProcessed);    WNDCLASSEX _WndClass;    DWORD _dwExtendedStyle;    DWORD _dwStyle;    LPSTR _pszClassName;    LPSTR _pszTitle;};  



  LRESULT CALLBACK CWindow::BaseWndProc(HWND hwnd, UINT msg,    WPARAM wParam, LPARAM lParam){    //A pointer to the object is passed in the CREATESTRUCT    if(msg == WM_NCCREATE)        SetWindowLongPtr(hwnd, GWLP_USERDATA,        (LONG_PTR)((LPCREATESTRUCT)lParam)->lpCreateParams);        BOOL bProcessed = FALSE;    LRESULT lResult;        //Retrieve the pointer    CWindow *pObj =         (CWindow *)GetWindowLongPtr(hwnd, GWLP_USERDATA);    //Filter message through child classes    if(pObj)        lResult = pObj->WindowProc(hwnd, msg, wParam, lParam,            &bProcessed);    if(bProcessed)        return lResult;    else    {        //If message was unprocessed, send it back to Windows.        return DefWindowProc(hwnd, msg, wParam, lParam);    }}LRESULT CWindow::WindowProc(HWND hwnd, UINT msg, WPARAM wParam,    LPARAM lParam, PBOOL pbProcessed){    //This may be overridden to process messages.    *pbProcessed = FALSE;    return NULL;}  
The code above require special initializations when the window is created. I would rather keep a singleton (global) hash table where I map window handles (hWnd) to CWindow pointers. This way when the window proc is called i look up a CWindow pointer using hWnd and dispatch the call to the abstract message handler in CWindow. There is a small pitfall here since two (if i remember correct) WM_ messages are sent at window creation before you have a chance to add the CWindow pointer to your hash table. These two messages are simply dispatched to the DefWindowProc winapi function.


HashTable g_HashTable;


LRESULT CALLBACK CWindow::BaseWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam){
//Lookup the pointer, if its not present NULL is returned
CWindow* ptr = g_HashTable[hwnd];

//Call abstract method if we got a pointer
if( ptr != 0 )
ptr->WindowProc( ... );
//Else let the winapi handle the message
else
DefWindowProc( ... );
}

Thanks petewood, that''s exactly what I said in my first solution . (ah, not exactly, I used the former version of the functions -without "Ptr"- )

----
David Sporn AKA Sporniket

This topic is closed to new replies.

Advertisement