C++ Winapi - 在 class 中结束 subclass 的回调

C++ Winapi - wrapping up a callback of subclass in a class

我想创建一个 class 用于创建静态控件。问题是当 subclassing 控件时,回调应该是静态的,这意味着我将无法访问回调内的非静态变量和函数。

我一直在努力使我的代码工作,但仍然没有成功。

MyClass.cpp

#include "MyClass.h"

MyClass::MyClass(){
    non_static_variable = 0; //default is zero.
}

LRESULT CALLBACK MyClass::SubClassProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData) {

    MyClass* pThis = reinterpret_cast<MyClass*>(dwRefData);
    
    char buffer[5];
    sprintf_s(buffer, "The value of non_static_variable is: %d \n", pThis->non_static_variable);
    OutputDebugStringA(buffer);    
        
    switch (uMsg) {
        case WM_PAINT: {
            // do nothing for now
            return 0;
        }

        case WM_NCDESTROY: {
            RemoveWindowSubclass(hwnd, SubClassProc, uIdSubclass);
            break;
        }
    }        
    return DefSubclassProc(hwnd, uMsg, wParam, lParam);
}

void MyClass::CreateStaticControl(HWND WindowHandle) {
    
    StaticControl = CreateWindowEx(0, L"STATIC", NULL, WS_CHILD | WS_VISIBLE | SS_OWNERDRAW, x, y, width, height, WindowHandle, NULL, NULL, this); 
    SetWindowSubclass(StaticControl, &SubClassProc, ID, reinterpret_cast<DWORD_PTR>(this));
}

void MyClass::SetValue(int value){
    non_static_variable = value; //test if I can access this in callback
}

MyClass.h

#include "header.h"

public:
    MyClass();

    void CreateStaticControl(HWND window);
    void SetValue(int value);
    static LRESULT CALLBACK SubClassProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData);

private:
    int non_static_variable;
    HWND StaticControl;

};

然后从我的 window 主程序调用 WM_CREATE 中的 class,我是这样使用的。

...
case WM_CREATE:{
   MyClass myClass;
   myClass.CreateStaticControl(hwnd);
   myClass.SetValue(888);
   break;
}

您可能认为这是与其他人的重复,我发现了很多,但由于这是关于 subclassing 的,而且我无权访问 WM_NCCREATE 我可以'没有正确设置我的 class 的指针。谁能帮帮我?

编辑: 我输入了我的确切代码。

您可以使用SetWindowSubclass()dwRefData参数将this指针传递给回调的dwRefData参数。然后您可以对该参数进行类型转换以访问非静态成员。根本不需要使用 GWLP_USERDATA(特别是因为您在设置 GWLP_USERDATA 时没有正确使用回调的 lParam)。

试试这个:

MyClass.h

class MyClass {

public:
    MyClass();

    void CreateStaticControl(HWND window);
    static LRESULT CALLBACK SubClassProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData);

private:
    int non_static_variable;
    HWND StaticControl;

};

MyClass.cpp:

void MyClass::CreateStaticControl(HWND WindowHandle) {
    StaticControl = CreateWindowEx(0, L"STATIC", NULL, WS_CHILD | WS_VISIBLE | SS_OWNERDRAW, x, y, width, height, WindowHandle, NULL, NULL, this); 
    SetWindowSubclass(StaticControl, &SubClassProc, ID, reinterpret_cast<DWORD_PTR>(this));
}

LRESULT CALLBACK MyClass::SubClassProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData) {

    MyClass* pThis = reinterpret_cast<MyClass*>(dwRefData);
        
    switch (uMsg) {
        case WM_PAINT: {
                
            // use pThis->non_static_variable as needed...
                
            return 0;
        }

        case WM_NCDESTROY: {
            RemoveWindowSubclass(hwnd, SubClassProc, uIdSubclass);
            break;
        }
    }        

    return DefSubclassProc(hwnd, uMsg, wParam, lParam);
}