在 class 中结束 Window 过程
Wrapping up a Window Procedure in a class
我想为透明的 WinAPI 标签创建一个简单的 C++ class(使用标准 "static" class 实现)。为此,我创建了一个静态控件并将其 Window 过程覆盖为以下过程:
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++ 将它包装起来 class 这样我就不必为我想在我的程序中使用的每个标签创建一个新的 Window 过程。我希望覆盖的 Window 过程成为一个成员函数,然后使用 this
来使用标签实例的存储数据(要显示的文本,如下所示:DrawText(hdc, this->Text, strlen(this->Text), &rc, DT_CENTER | DT_VCENTER);
)
但是,成员函数要求 this
作为第一个参数传递,而由于这是回调,我无法控制 Windows 调用该函数的方式。
有没有其他方法可以将它包装在一个紧凑的 class 中,这样我就不必为每个标签创建一个单独的 Window 过程?
您可以在文本字段的用户数据中存储一个指针:
myTextField->hWnd = CreateWindow( /*parameters*/ );
SetWindowLongPtr(myTextField->hWnd, GWLP_USERDATA, (LONG_PTR)myTextField);
在你的 window 过程中:
LRESULT CALLBACK WndProc_Override(HWND hwnd, UINT Message, WPARAM wparam, LPARAM lparam)
{
MyTextFieldClass * myTextField = (MyTextFieldClass *)GetWindowLongPtr(hWnd,GWLP_USERDATA);
/* rest of method */
}
如果您需要在 window 构建期间访问您的 class,您可以这样做:
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;
}
}
我想为透明的 WinAPI 标签创建一个简单的 C++ class(使用标准 "static" class 实现)。为此,我创建了一个静态控件并将其 Window 过程覆盖为以下过程:
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++ 将它包装起来 class 这样我就不必为我想在我的程序中使用的每个标签创建一个新的 Window 过程。我希望覆盖的 Window 过程成为一个成员函数,然后使用 this
来使用标签实例的存储数据(要显示的文本,如下所示:DrawText(hdc, this->Text, strlen(this->Text), &rc, DT_CENTER | DT_VCENTER);
)
但是,成员函数要求 this
作为第一个参数传递,而由于这是回调,我无法控制 Windows 调用该函数的方式。
有没有其他方法可以将它包装在一个紧凑的 class 中,这样我就不必为每个标签创建一个单独的 Window 过程?
您可以在文本字段的用户数据中存储一个指针:
myTextField->hWnd = CreateWindow( /*parameters*/ );
SetWindowLongPtr(myTextField->hWnd, GWLP_USERDATA, (LONG_PTR)myTextField);
在你的 window 过程中:
LRESULT CALLBACK WndProc_Override(HWND hwnd, UINT Message, WPARAM wparam, LPARAM lparam)
{
MyTextFieldClass * myTextField = (MyTextFieldClass *)GetWindowLongPtr(hWnd,GWLP_USERDATA);
/* rest of method */
}
如果您需要在 window 构建期间访问您的 class,您可以这样做:
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;
}
}