使用SetWindowSubclass

时间:2016-11-26 21:52:35

标签: 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.
    }
}

这会引发错误:

  

类型“LRESULT(__stdcall button :: *)(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam,UINT_PTR uIdSubclass,DWORD_PTR dwRefData)”的参数与“SUBCLASSPROC”类型的参数不兼容

我希望有人可以解释一个简单的解决方案,或者在Winapi中提出替代方案,因为我希望学习本机窗口和C ++而不依赖于其他库。

1 个答案:

答案 0 :(得分:1)

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

要执行您尝试的操作,您必须删除this参数(您可以使用dwRefData的{​​{1}}参数代替):

  1. 使用静态类方法

    SetWindowSubclass()
  2. 使用非会员功能

    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.
    }