【发布时间】:2020-04-19 16:31:17
【问题描述】:
案例
我的基类“Control”子类化 WinAPI 按钮控件:
hWndControl = CreateWindowEx
(
0
, L"BUTTON"
, L"Button"
, WS_VISIBLE | WS_CHILD | BS_OWNERDRAW | WS_EX_TRANSPARENT
, wndRc.left
, wndRc.top
, wndRc.right
, wndRc.bottom
, hWndParent
, 0
, hInstance
, 0
);
void* p_this{reinterpret_cast<void*>(this)}; // avoiding C-style cast
SetWindowSubclass
(
hWndControl
, Control::ControlProc
, 0
, reinterpret_cast<DWORD_PTR>(p_this)
)
据我所知,这需要我将回调定义为静态(我这样做)。 以下是回调示例供参考:
LRESULT CALLBACK Control::ControlProc
(
HWND hWnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
, UINT_PTR uIdSubclass
, DWORD_PTR dwRefData
)
{
// RETRIEVE POINTER TO THIS CLASS OBJECT
void* p_thisV{reinterpret_cast<void*>(dwRefData)}; // avoiding C-style cast
Control* const p_this{reinterpret_cast<Control*>(p_thisV)};
// PROCESS MESSAGES
switch (msg)
{
// DRAWING
case MY_DRAWITEM: // custom message forwarding WM_DRAWITEM from main window
{
p_this->DrawControl();
}
break;
...
}
return DefSubclassProc(hWnd, msg, wParam, lParam);
}
就这里而言,如果我在回调函数中绘制,或者在回调中引用的基类中定义的成员函数中绘制,一切正常。
但我计划在使用相同回调时为多个具有不同外观的不同控件继承此基类。所以我想我会创建在回调的特定点调用的虚函数,我可以在派生类中用每个派生类的自定义行为覆盖它,如下所示:
// Base class header
class Control
{
...
protected:
virtual void DrawControl();
...
};
// Derived class header
class CalendarItem : public Control
{
...
protected:
void DrawControl();
...
};
// Derived class cpp
void CalendarItem::DrawControl()
{
std::unique_ptr<DrawBg> drawBg = std::unique_ptr<DrawBg>(new DrawBg(Control::hWndControl));
// this is the actual drawing mechanism, works, not relevant
}
问题
在线回调函数出现异常:p_this->DrawControl();
异常文本:p_this->**** 为 0x75004D。
您能告诉我如何解决这个问题,或者这样的事情是否可行?
【问题讨论】:
-
你使用多重继承还是虚拟继承?如果是这样,
reinterpret_cast显然是有问题的。 -
@AlexGuteniev 如果所有类型转换之前和之后的指针类型都是相同的类型,这不是问题。
-
旁白:您可以安全地将
reinterpret_cast直接从任何对象指针类型转换为“足够大”的整数类型,如DWORD_PTR,然后返回到原始指针类型。您不需要中间的void*值。 -
@Xzsh4s575sf75 这意味着您将指针传递给堆栈中的临时对象。