Продолжительность жизни объектов интеллектуальных указателей, объявленных и инициализированных внутри сообщения WndPro c (WM_CREATE) - PullRequest
0 голосов
/ 09 мая 2020

Если я объявлю и инициализирую объект в функции обратного вызова главного окна следующим образом:

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 оставаться инициализированным после сообщения break of WM_CREATE? А если нет, то где находится лучшее место для его объявления, чтобы его область действия не ограничивалась областью case?

Объект foo создает элементы управления в главном окне кстати, поэтому я думаю, что необходимо дать ему дожить до конца времени выполнения.

Я подозреваю, что он не выживет. Я подумываю объявить их как глобальные переменные (но мне не нравится этот вариант по очевидным причинам) или как объекты stati c в функции обратного вызова (но за пределами switch). Но могут быть варианты лучше, которых я не вижу, поэтому обращаюсь к вам за советом.

Спасибо за помощь!

1 Ответ

3 голосов
/ 09 мая 2020

Вот разработка предложения 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 согласно комментариям.

...