c++ - 使用 SetWindowSubclass 在自定义类中子类化按钮

标签 c++ winapi subclassing

<分区>

我正在尝试编写一个类来处理按钮的创建及其内部消息。我希望将所有代码都包含在类本身中。这可能很简单或不可能,因为我对 Winapi 和 C++ 比较陌生,更广泛地使用了 vb.net。我无法找到一个例子来完成这个看似简单的转换。我确实找到了建议我使用备用 API 或使用 SetWindowLongPtr 的示例,有人告诉我 SetWindowSubclass 是更好的选择。我尝试的代码如下:

#pragma once
#include <iostream>
#include <Windows.h>
#include <Commctrl.h>

using namespace std;

    class button {
    public:
        bool initialize();
        buttton(int x, int y, int length, int width, LPCWSTR text, HWND parent, HINSTANCE hInstance);  // This is the constructor

    private:
        LPCWSTR text = L"Button";
        int height = 25;
        int width = 100;
        int x = 0;
        int y = 0;
        HWND parent;
        HWND thisHandle;
        HINSTANCE thisInstance;
        bool initialized = false;
        LRESULT CALLBACK mySubClassProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData);

    };


    button::button(int x, int y, int height, int width, LPCWSTR text, HWND parent, HINSTANCE hInstance) {
        this->x = x;
        this->y = y;
        this->height = height;
        this->width = width;
        this->text = text;
        this->parent = parent;
        thisInstance = hInstance;
    }
        bool button::initialize()
    {
        thisHandle = CreateWindowW(
            L"BUTTON",  // Predefined class; Unicode assumed 
            text,      // Button text 
            WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON | WS_CLIPSIBLINGS | BS_NOTIFY,  // Styles 
            x,         // x position 
            y,         // y position 
            width,        // Button width
            height,        // Button height
            parent,     // Parent window
            NULL,       // No ID.
            thisInstance,
            NULL);      // Pointer not needed.
        if (!thisHandle)
        {
            return false;
        }
        initialized = true;
        //Problem Code****
        SetWindowSubclass(thisHandle, mySubClassProc, 1, 0);
        //****  
        return true;
    }

    LRESULT CALLBACK button::mySubClassProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData) {

        //Code handling messages here.
    }
}

这会引发错误:

argument of type "LRESULT (__stdcall button::*)(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData)" is incompatible with parameter of type "SUBCLASSPROC"

我希望有人能解释一个简单的解决方案,或者建议 Winapi 中的替代方案,因为我希望学习 native Windows 和 C++,而不是依赖其他库。

最佳答案

您正在尝试使用非静态类方法 作为子类回调。这是行不通的,因为非静态类方法有一个 API 无法传递的隐藏 this 参数。

要执行您正在尝试的操作,您必须删除 this 参数(您可以使用 SetWindowSubclass()dwRefData 参数代替) ,通过:

  1. 使用静态类方法:

    class button {
    public:
        bool initialize();
        ...
    
    private:
        ...
    
        static LRESULT CALLBACK mySubClassProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData);
    
    };
    
    bool button::initialize()
    {
        ...
        SetWindowSubclass(thisHandle, mySubClassProc, 1, (DWORD_PTR) this);
        return true;
    }
    
    LRESULT CALLBACK button::mySubClassProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData)
    {
        button *pThis = (button*) dwRefData;
    
        //Code handling messages here.
    }
    
  2. 使用非成员函数:

    class button {
    public:
        bool initialize();
        ...
    };
    
    LRESULT CALLBACK myButtonSubClassProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData)
    {
        button *pBtn = (button*) dwRefData;
        //Code handling messages here.
    }
    
    bool button::initialize()
    {
        ...
        SetWindowSubclass(thisHandle, myButtonSubClassProc, 1, (DWORD_PTR) this);
        return true;
    }
    

关于c++ - 使用 SetWindowSubclass 在自定义类中子类化按钮,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40823536/

相关文章:

c++ - 如何使用 Boost Spirit 解析像转义字符串这样的 CSV?

c++ - 赋值运算符重载

c++ - 在 C++ 中调用当前命名空间之外的函数

C++堆排序困惑

c++ - 为什么我的 DirectInput8 堆栈会溢出?

objective-c - 在子类中重铸属性

javascript - javascript中的继承模式

c++ - 如何获取进程相对时间

c++ - WaitForSingleObject 信号过早 ImageMagick 转换

c - 使用 GWL_WNDPROC 子类化 richedit 的问题