由方法修改的成员在退出后将还原



我有一个窗口(Windows),我的wndProc与Windows指南上的基本相同。但是,即使WM_CLOSE被传递(我可以使用 if(msg == WM_CLOSE)),我似乎也无法设置我的 shouldClose 标志。我已经确认我仍然在我的进程消息方法中获取事件。所以我的问题是:发生了什么,我怎样才能让它工作?

编辑:我尝试将窗口数据存储为结构而不是类,一切正常。即。我改变的只是类的类型,以及一些错误。

class Win32Window {
    this(wstring title, int width, int height) {
        immutable wstring className = "glass_def_class_name";
        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();
}

由方法修改的成员在退出后还原

这是当您使用对象的本地副本并对此本地副本进行修改时,但不是真正的对象。我没有看到其他解释

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.lpCreateParamsGetWindowLongPtr(hwnd, GWLP_USERDATA) 之前的额外cast(void*)。我不完全确定为什么这与我的原始代码相反有效,但它似乎有效,当我有时间时,我会做更多的调查。

最新更新