在类中包装窗口过程

Wrapping up a Window Procedure in a class

本文关键字:窗口 过程 包装      更新时间:2023-10-16

我想为透明 WinAPI 标签创建一个简单的C++类(使用标准的"静态"类实现)。为此,我创建了一个静态控件,并将其窗口过程重写为以下控件:

LRESULT CALLBACK WndProc_Override(HWND hwnd, UINT Message, WPARAM wparam, LPARAM lparam)
{
    if (Message == WM_PAINT)
    {
        RECT rc;
        PAINTSTRUCT ps;
        HDC hdc = BeginPaint(hwnd, &ps);
        GetClientRect(hwnd, &rc);
        SetBkMode(hdc, TRANSPARENT);
        DrawText(hdc, Text, strlen(Text), &rc, DT_CENTER | DT_VCENTER);
        EndPaint(hwnd, &ps);
        return 0;
    }
    return CallWindowProc(WndProc_Original, hwnd, Message, wparam, lparam);
}

代码取自 Edward Clements 对这个问题的出色回答: C++ Win32 静态控制透明背景

我想把它包装在一个C++类中,这样我就不必为我想在程序中使用的每个标签创建一个新的窗口过程。我希望被覆盖的窗口过程是一个成员函数,然后使用 this 来使用标签实例的存储数据(要显示的文本,如下所示:DrawText(hdc, this->Text, strlen(this->Text), &rc, DT_CENTER | DT_VCENTER);

但是,成员函数要求this作为第一个参数传递,而由于这是一个回调,因此我无法控制 Windows 如何调用该函数。

有没有其他方法可以将其包装在一个紧凑的类中,这样我就不必为每个标签创建单独的窗口过程?

您可以将指针存储在文本字段的用户数据中:

myTextField->hWnd = CreateWindow( /*parameters*/ );
SetWindowLongPtr(myTextField->hWnd, GWLP_USERDATA, (LONG_PTR)myTextField);

在窗口进程内:

LRESULT CALLBACK WndProc_Override(HWND hwnd, UINT Message, WPARAM wparam, LPARAM lparam)
{
    MyTextFieldClass * myTextField = (MyTextFieldClass *)GetWindowLongPtr(hWnd,GWLP_USERDATA);
    /* rest of method */
}

如果您需要在窗口构建期间访问您的类,您可以通过以下方式执行此操作:

HWND myTextField = CreateWindow( /*normal parameters*/, myTextField);

并在像这样WM_CREATE期间检索它:

LRESULT CALLBACK WndProc_Override(HWND hwnd, UINT Message, WPARAM wparam, LPARAM lparam)
{
     if (WM_CREATE == Message)
     {
          LONG_PTR myPtr = (LONG_PTR)((CREATESTRUCT *)lparam)->lpCreateParams;
          SetWindowLongPtr(hwnd, GWLP_USERDATA, myPtr);
          MyTextfieldClass * myTextField = (MyTextfieldClass *)myPtr;
     }
}