在 C 类中对 windows 按钮控件进行子类化

此示例显示如何通过指定固定大小来操作按钮理想大小。

class ButtonSubclass {
public:

    ButtonSubclass(HWND hWndButton) {
        SetWindowSubclass(hWndButton, MyButtonSubclassProc, 1, (DWORD_PTR) this);
    }
    ~ButtonSuclass() {
        RemoveWindowSubclass(hWndButton, MyButtonSubclassProc, 1, (DWORD_PTR) this);
    }

protected:

    static LRESULT CALLBACK MyButtonSubclassProc(
           HWND hWnd, UINT Msg, WPARAM w, LPARAM l, DWORD_PTR RefData) {

        ButtonSubclass* o = reinterpret_cast<ButtonSubclass*>(RefData);

        if (Msg == BCM_GETIDEALSIZE) {
            reinterpret_cast<SIZE*>(lParam)->cx = 100;
            reinterpret_cast<SIZE*>(lParam)->cy = 100;
            return TRUE;
        }
        return DefSubclassProc(hWnd, Msg, w, l);
    }
}

安装和删除子类过程

以下方法安装或删除子类回调。SubclassIdSubclassProc 的组合唯一地标识子类。没有引用计数,用不同的 RefData 多次调用 SetWindowSubclass 只更新该值但不会导致多次调用子类回调。

BOOL SetWindowSubclass(HWND hWnd, SUBCLASSPROC SubclassProc, UINT_PTR SubclassId, DWORD_PTR RefData);
BOOL RemoveWindowSubclass(HWND hWnd, SUBCLASSPROC SubclassProc, UINT_PTR SubclassId);

要检索在最后一个 SetWindowSubclasscall 中传递的参考数据,可以使用 GetWindowSubclass 方法。

BOOL GetWindowSubclass(HWND hWnd, SUBCLASSPROC SubclassProc, UINT_PTR SubclassId, DORD_PTR* RefData);
参数 详情
hWnd 子窗口的句柄。
SubclassProc 子类回调过程。
SubclassId 用户指定的 ID 用于标识子类,以及子类过程唯一标识子类。它可以简单地是任意连续的数字。
RefData 用户指定的数据。含义由申请决定。它以未修改的方式传递给子类回调。例如,它可以是指向类实例的对象指针。

子类回调负责调用 window 的子类链中的下一个处理程序。DefSubclassProc 调用 window 的子类链中的下一个处理程序。最后一个处理程序调用原始窗口过程。它应该在任何子类回调过程中调用,除非消息完全由应用程序处理。

LRESULT DefSubclassProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);
参数 详情
hWnd 消息源自的窗口句柄
消息 窗口消息
wParam 中 WPARAM 参数,此值取决于特定的窗口消息
lParam LPARAM 参数,此值取决于特定的窗口消息

SUBCLASSPROC

它类似于 WINDOWPROC 回调,但包含一个额外的参数 RefData

typedef LRESULT (CALLBACK *SUBCLASSPROC)(
    HWND hWnd,
    UINT Msg,
    WPARAM wParam,
    LPARAM lParam,
    UINT_PTR SubclassId,
    DWORD_PTR RefData
);