方法修改的成员退出后还原
Member modified by method reverts after it exits
我有一个window (Windows),我的wndProc 与windows 指南上的基本相同。然而,即使 WM_CLOSE 获得通过(并且我可以使用 if(msg == WM_CLOSE)),我似乎无法设置我的 shouldClose 标志。我已经确认我仍然在我的 processMessage 方法中收到事件。所以我的问题是:这是怎么回事,我怎样才能让它发挥作用?
编辑:我尝试将 window 数据存储为结构而不是 class,一切正常。 IE。我只更改了 class 的类型和一些错误。
class Win32Window {
this(wstring title, int width, int height) {
immutable wstring className = "glass_def_class_name[=10=]";
auto hInstance = GetModuleHandle(null);
WNDCLASSW wc;
wc.lpfnWndProc = &windowProc;
wc.hInstance = hInstance;
wc.lpszClassName = &className[0];
RegisterClassW(&wc);
handle = CreateWindowExW(
0,
&className[0],
&title[0],
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
width, height,
null, null,
hInstance,
cast(void*) this);
ShowWindow(handle, SW_NORMAL);
}
~this() {
DestroyWindow(handle);
}
void processEvents() {
MSG msg;
while (PeekMessage(&msg, handle, 0, 0, PM_REMOVE)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
bool shouldClose;
HWND handle;
private:
LRESULT processMessage(UINT msg, WPARAM wp, LPARAM lp) nothrow {
switch (msg) {
case WM_CLOSE:
shouldClose = true;
return 0;
default:
return DefWindowProc(handle, msg, wp, lp);
}
}
}
private extern (Windows) LRESULT windowProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) nothrow {
Win32Window window;
if (msg == WM_CREATE) {
CREATESTRUCT* create = cast(CREATESTRUCT*) lp;
window = cast(Win32Window*) create.lpCreateParams;
SetWindowLongPtr(hwnd, GWLP_USERDATA, cast(LONG_PTR) create.lpCreateParams);
window.handle = hwnd;
}
else {
LONG_PTR ptr = GetWindowLongPtr(hwnd, GWLP_USERDATA);
window = cast(Win32Window* ptr);
}
if (window)
return window.processMessage(msg, wp, lp);
else
return DefWindowProc(hwnd, msg, wp, lp);
}
void main()
{
auto window = new Win32Window("test", 1280, 720);
while(window.shouldClose == false) {
window.processEvents();
}
window.destroy();
}
Member modified by method reverts after it exits
这是您使用对象的本地副本并对该本地副本进行修改,而不是真正对对象进行修改的时候。我不看其他解释
在 windowProc
中,您接下来要执行 Win32Window window = *(cast(Win32Window*) ptr);
- 因此您在 windowProc
中创建初始对象状态的本地副本,然后对该本地副本进行所有修改 - 当然,当您退出 windowProc
时,所有内容都丢失了,正确的代码必须是下一个:
private LRESULT windowProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) nothrow {
Win32Window* window;
if (msg == WM_NCCREATE) {
CREATESTRUCT* create = (CREATESTRUCT*) lp;
window = (Win32Window*) create.lpCreateParams;
SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR) create.lpCreateParams);
window.handle = hwnd;
}
else {
window = (Win32Window*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
}
return window ? window->processMessage(msg, wp, lp) : DefWindowProc(hwnd, msg, wp, lp);
}
事实证明,您实际上不能将指针直接转换为引用。中介是必要的(或类似的东西)。因此,winProc
应该看起来像这样:
private extern (Windows) LRESULT windowProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) nothrow {
Win32Window window;
if (msg == WM_NCCREATE) {
auto create = cast(CREATESTRUCT*) lp;
window = cast(Win32Window) (cast(void*) create.lpCreateParams);
window.handle = hwnd;
SetWindowLongPtr(hwnd, GWLP_USERDATA, cast(LONG_PTR) create.lpCreateParams);
}
else {
window = cast(Win32Window) (cast(void*) GetWindowLongPtr(hwnd, GWLP_USERDATA));
}
return window ? window.processMessage(msg, wp, lp) : DefWindowProc(hwnd, msg, wp, lp);
}
注意 create.lpCreateParams
和 GetWindowLongPtr(hwnd, GWLP_USERDATA)
之前的额外 cast(void*)
。我不完全确定为什么这与我的原始代码相反,但它似乎有效,我会在有空的时候做更多的调查。
我有一个window (Windows),我的wndProc 与windows 指南上的基本相同。然而,即使 WM_CLOSE 获得通过(并且我可以使用 if(msg == WM_CLOSE)),我似乎无法设置我的 shouldClose 标志。我已经确认我仍然在我的 processMessage 方法中收到事件。所以我的问题是:这是怎么回事,我怎样才能让它发挥作用?
编辑:我尝试将 window 数据存储为结构而不是 class,一切正常。 IE。我只更改了 class 的类型和一些错误。
class Win32Window {
this(wstring title, int width, int height) {
immutable wstring className = "glass_def_class_name[=10=]";
auto hInstance = GetModuleHandle(null);
WNDCLASSW wc;
wc.lpfnWndProc = &windowProc;
wc.hInstance = hInstance;
wc.lpszClassName = &className[0];
RegisterClassW(&wc);
handle = CreateWindowExW(
0,
&className[0],
&title[0],
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
width, height,
null, null,
hInstance,
cast(void*) this);
ShowWindow(handle, SW_NORMAL);
}
~this() {
DestroyWindow(handle);
}
void processEvents() {
MSG msg;
while (PeekMessage(&msg, handle, 0, 0, PM_REMOVE)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
bool shouldClose;
HWND handle;
private:
LRESULT processMessage(UINT msg, WPARAM wp, LPARAM lp) nothrow {
switch (msg) {
case WM_CLOSE:
shouldClose = true;
return 0;
default:
return DefWindowProc(handle, msg, wp, lp);
}
}
}
private extern (Windows) LRESULT windowProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) nothrow {
Win32Window window;
if (msg == WM_CREATE) {
CREATESTRUCT* create = cast(CREATESTRUCT*) lp;
window = cast(Win32Window*) create.lpCreateParams;
SetWindowLongPtr(hwnd, GWLP_USERDATA, cast(LONG_PTR) create.lpCreateParams);
window.handle = hwnd;
}
else {
LONG_PTR ptr = GetWindowLongPtr(hwnd, GWLP_USERDATA);
window = cast(Win32Window* ptr);
}
if (window)
return window.processMessage(msg, wp, lp);
else
return DefWindowProc(hwnd, msg, wp, lp);
}
void main()
{
auto window = new Win32Window("test", 1280, 720);
while(window.shouldClose == false) {
window.processEvents();
}
window.destroy();
}
Member modified by method reverts after it exits
这是您使用对象的本地副本并对该本地副本进行修改,而不是真正对对象进行修改的时候。我不看其他解释
在 windowProc
中,您接下来要执行 Win32Window window = *(cast(Win32Window*) ptr);
- 因此您在 windowProc
中创建初始对象状态的本地副本,然后对该本地副本进行所有修改 - 当然,当您退出 windowProc
时,所有内容都丢失了,正确的代码必须是下一个:
private LRESULT windowProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) nothrow {
Win32Window* window;
if (msg == WM_NCCREATE) {
CREATESTRUCT* create = (CREATESTRUCT*) lp;
window = (Win32Window*) create.lpCreateParams;
SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR) create.lpCreateParams);
window.handle = hwnd;
}
else {
window = (Win32Window*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
}
return window ? window->processMessage(msg, wp, lp) : DefWindowProc(hwnd, msg, wp, lp);
}
事实证明,您实际上不能将指针直接转换为引用。中介是必要的(或类似的东西)。因此,winProc
应该看起来像这样:
private extern (Windows) LRESULT windowProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) nothrow {
Win32Window window;
if (msg == WM_NCCREATE) {
auto create = cast(CREATESTRUCT*) lp;
window = cast(Win32Window) (cast(void*) create.lpCreateParams);
window.handle = hwnd;
SetWindowLongPtr(hwnd, GWLP_USERDATA, cast(LONG_PTR) create.lpCreateParams);
}
else {
window = cast(Win32Window) (cast(void*) GetWindowLongPtr(hwnd, GWLP_USERDATA));
}
return window ? window.processMessage(msg, wp, lp) : DefWindowProc(hwnd, msg, wp, lp);
}
注意 create.lpCreateParams
和 GetWindowLongPtr(hwnd, GWLP_USERDATA)
之前的额外 cast(void*)
。我不完全确定为什么这与我的原始代码相反,但它似乎有效,我会在有空的时候做更多的调查。