Win32 C++ Create a Window and Procedure Within a Class

后端 未结 5 1807
刺人心
刺人心 2020-12-09 11:16

Pre-Text/ Question

I am trying to make a fairly simple tool to help debug variable values. For it to be completely self contained within the class i

5条回答
  •  醉话见心
    2020-12-09 11:39

    To use a non-static class method as a window procedure requires a dynamically-allocated thunk, which is an advanced technique that I will not get into it here.

    The alternative is to declare the class method as static, then it will work as a window procedure. Of course, being a static method, it can no longer access non-static class members without an instance pointer. To get that pointer, you can have the class pass its this pointer to the lpParam parameter of CreateWindow/Ex(), then the window procedure can extract that pointer from the WM_NCCREATE message and store it in the window using SetWindowLong/Ptr(GWL_USERDATA). After that, subsequent messages can retrieve that pointer using GetWindowLong/Ptr(GWL_USERDATA) and thus be able to access non-static members of that object. For example:

    class viewvars
    {
    private:
        HWND hWindow;
        LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam);
    
        static LRESULT CALLBACK ThisWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
    public:
        int CreateTestWindow(HINSTANCE hInst);
    };
    

    int viewvars::CreateTestWindow(HINSTANCE hInst)
    { 
        WNDCLASS wincl;
    
        if (!GetClassInfo(hInst, thisClassName, &wincl))
        {
            ...
            wincl.hInstance = hInst;
            wincl.lpszClassName = thisClassName;
            wincl.lpfnWndProc = &ThisWindowProc;
    
            if (RegisterClass(&wincl) == 0)
                return -1;
        }
    
        hWindow = CreateWindow(..., hInst, this);
        if (hWindow == NULL)
            return -1;
    
        ...
    
        MSG msg;
        while (GetMessage(&msg, hWindow, 0, 0))
        {
            TranslateMessage(&msg);  
            DispatchMessage(&msg); 
        }
    
        DestroyWindow(hWindow);
        hWindow = NULL;
    
        return msg.wParam;
    }
    
    LRESULT CALLBACK viewvars::ThisWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
        viewvars *view;
    
        if (message == WM_NCCREATE)
        {
            CREATESTRUCT *cs = (CREATESTRUCT*) lParam; 
            view = (viewvars*) cs->lpCreateParams;
    
            SetLastError(0);
            if (SetWindowLongPtr(hwnd, GWL_USERDATA, (LONG_PTR) view) == 0)
            {
                if (GetLastError() != 0)
                    return FALSE;
            }
        }
        else
        {
            view = (viewvars*) GetWindowLongPtr(hwnd, GWL_USERDATA);
        }
    
        if (view)
            return view->WindowProc(message, wParam, lParam);
    
        return DefWindowProc(hwnd, message, wParam, lParam);
    }
    
    LRESULT viewvars::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
    {
        // you can access non-static members in here...
    
        switch (message)
        {
            case WM_PAINT: 
                return 0;
    
            case WM_DESTROY:
                PostQuitMessage(0);       
                return 0;
    
            default:
                return DefWindowProc(hWindow, message, wParam, lParam);
        }
    }
    

提交回复
热议问题