【问题标题】:Wrapping up a Window Procedure in a class [duplicate]在一个类中包装一个窗口过程[重复]
【发布时间】:2015-05-16 08:13:27
【问题描述】:

我想为透明的 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 Static Control Transparent Background

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

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

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

【问题讨论】:

  • 是的。你试过搜索吗?
  • 回调方法可以声明为static,因此它们不需要this 参数,但如果您需要访问对象的数据。
  • @MarkRansom 正是我的想法,但我想不出任何在静态函数中访问数据的方法。
  • @Drop 搜索什么,究竟是什么?这是一个罕见的概念性问题。如果您碰巧找到了可以回答此问题的网站,请善待并与我们分享。
  • It is a rare, conceptual issue 你在开玩笑吗? stackoverflow.com/search?q=wndproc+class 确实是一个独特的问题。它是如何获得支持的?

标签: c++ winapi visual-c++


【解决方案1】:

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

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

【讨论】:

  • 效果很好,非常感谢:)
  • 我们通常在WM_NCCREATE而不是WM_CREATE上捕获指针
猜你喜欢
  • 2018-11-11
  • 1970-01-01
  • 1970-01-01
  • 2019-05-25
  • 1970-01-01
  • 1970-01-01
  • 2016-09-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多