2017-01-25 2 views
0

У меня есть окно (Windows), и мой wndProc в основном такой же, как и в руководствах по окнам. Однако, несмотря на то, что WM_CLOSE передается (и я могу использовать if (msg == WM_CLOSE)), я не могу установить свой флаг ifClose. Я подтвердил, что все еще получаю событие в методе processMessage. Поэтому мой вопрос таков: что происходит, и как я могу заставить его работать?Член, измененный методом возврата после его завершения

Редактировать: Я пытался хранить данные окна как структуру вместо класса, и все работает отлично. То есть. Все, что я изменил, это тип класса и несколько ошибок.

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

Почему вы удалили все соответствующие коды. Показать MCVE. –

+0

MCVE - много кода. Особенно для создания окна. Конечно, я могу это сделать. – Straivers

+0

Это очень много, если вы не сократите его. Это M. –

ответ

0

Оказывается, вы не можете фактически направить указатель непосредственно на ссылку. Необходим посредник (или что-то в этом роде). Таким образом, 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); 
} 

Обратите внимание на дополнительные cast(void*) перед тем create.lpCreateParams и GetWindowLongPtr(hwnd, GWLP_USERDATA). Я не совсем уверен, почему это работает в отличие от моего исходного кода, но, похоже, он работает, и я буду делать еще несколько исследований, когда у меня будет время.

0

Член модифицирована методом возвращается после того, как он выходит из

это было, когда вы работали с локальной копией объекта, и сделать изменения в эту локальную копию, но на самом деле не возражать. Я не рассматриваю другие объяснения

внутри 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); 
} 
+0

Спасибо, я попробовал это. Он удаляет ошибку нарушения доступа, но значение по-прежнему остается неустойчивым. – Straivers

+0

Используя '* (cast (Win32Window *) GetWindowLongPtr (hwnd, GWLP_USERDATA)', я понимаю, что вы получаете ссылку (в отличие от указателя) на объект. Все объекты в D являются ссылочными типами по умолчанию. – Straivers

+0

@ Straivers - так что вы все еще не исправляете, это означает, что вы работаете не с указателем на объект, а с локальной копией объекта. чудес не существует. Я полностью не понимаю ваш код в 'main'. это ошибка, когда вы копируете/вставляете или сбрасываете настоящий код? здесь 'auto window'- указатель или локальная копия объекта. Я вообще не знаком с языком, на котором вы пишете – RbMm

Смежные вопросы