在 WndProc 消息中声明和初始化的智能指针对象的生命周期 (WM_CREATE)
Lifespan of smart pointer objects declared and initialized inside WndProc message (WM_CREATE)
如果我在主 window 回调函数中声明并初始化对象,如下所示:
LRESULT CALLBACK WndProc
(
HWND hWnd // handle to window of this process
, UINT msg // message constant
, WPARAM wParam // holder of message parameters
, LPARAM lParam // holder of message parameters
)
{
switch (msg)
{
case WM_CREATE:
{
std::unique_ptr<Foo> foo = std::unique_ptr<Foo>(new Foo);
}
break;
}
}
对象 foo
会在 WM_CREATE
消息的 break
之后保持初始化状态吗?如果不是,那么最好在哪里声明它,以便它的范围不受case
范围的限制?
顺便说一下,foo
对象正在主 window 中创建控件,所以我认为要求是让它一直存在到运行时结束。
我怀疑它活不下去了。我正在考虑将它们声明为全局变量(但出于显而易见的原因我不喜欢该选项)或声明为回调函数中的静态对象(但在 switch
之外)。但是我可能没有看到更好的选择,所以我正在寻求您的建议。
感谢您的帮助!
这是 RbMm 建议的处理,我自己在自己的代码中使用了它。智能指针在这里提供的东西很少,所以使用它真的没有多大意义。请注意,为简洁起见,我使用了 C 风格的转换,但如果您愿意,也可以使用 reinterpret_cast
。
class MyWindowData { ... };
MyWindowData *window_data = new MyWindowData;
HWND hWnd = CreateWindow (... ... ..., (LPARAM) window_data);
LRESULT CALLBACK WndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_NCCREATE:
CREATESTRUCT *cs = (CREATESTRUCT *) lParam;
SetWindowLongPtr (hWnd, GWLP_USERDATA, cs->lpCreateParams);
break;
case NC_DESTROY:
MyWindowData *window_data = (MyWindowData *) GetWindowLongPtr (hWnd, GWLP_USERDATA);
SetWindowLongPtr (hWnd, GWLP_USERDATA, 0);
delete window_data;
break;
}
// return something here;
}
然后你可以这样做:
MyWindowData *window_data = (MyWindowData *) GetWindowLongPtr (hWnd, GWLP_USERDATA);
在您需要时随时检索 MyWindowData
,但检查是否返回零,以防 WM_NCCREATE
不是您的 WNDPROC
根据评论收到的第一条消息。
如果我在主 window 回调函数中声明并初始化对象,如下所示:
LRESULT CALLBACK WndProc
(
HWND hWnd // handle to window of this process
, UINT msg // message constant
, WPARAM wParam // holder of message parameters
, LPARAM lParam // holder of message parameters
)
{
switch (msg)
{
case WM_CREATE:
{
std::unique_ptr<Foo> foo = std::unique_ptr<Foo>(new Foo);
}
break;
}
}
对象 foo
会在 WM_CREATE
消息的 break
之后保持初始化状态吗?如果不是,那么最好在哪里声明它,以便它的范围不受case
范围的限制?
顺便说一下,foo
对象正在主 window 中创建控件,所以我认为要求是让它一直存在到运行时结束。
我怀疑它活不下去了。我正在考虑将它们声明为全局变量(但出于显而易见的原因我不喜欢该选项)或声明为回调函数中的静态对象(但在 switch
之外)。但是我可能没有看到更好的选择,所以我正在寻求您的建议。
感谢您的帮助!
这是 RbMm 建议的处理,我自己在自己的代码中使用了它。智能指针在这里提供的东西很少,所以使用它真的没有多大意义。请注意,为简洁起见,我使用了 C 风格的转换,但如果您愿意,也可以使用 reinterpret_cast
。
class MyWindowData { ... };
MyWindowData *window_data = new MyWindowData;
HWND hWnd = CreateWindow (... ... ..., (LPARAM) window_data);
LRESULT CALLBACK WndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_NCCREATE:
CREATESTRUCT *cs = (CREATESTRUCT *) lParam;
SetWindowLongPtr (hWnd, GWLP_USERDATA, cs->lpCreateParams);
break;
case NC_DESTROY:
MyWindowData *window_data = (MyWindowData *) GetWindowLongPtr (hWnd, GWLP_USERDATA);
SetWindowLongPtr (hWnd, GWLP_USERDATA, 0);
delete window_data;
break;
}
// return something here;
}
然后你可以这样做:
MyWindowData *window_data = (MyWindowData *) GetWindowLongPtr (hWnd, GWLP_USERDATA);
在您需要时随时检索 MyWindowData
,但检查是否返回零,以防 WM_NCCREATE
不是您的 WNDPROC
根据评论收到的第一条消息。