Статический HWND — зачем он нужен?

Хорошо, ЕДИНСТВЕННАЯ причина, по которой я спрашиваю, заключается в том, что я прочитал, что HWND - это указатель, указатели изменяют исходное значение, а не создают дубликат, который хранится в этом месте памяти.

Но на самом деле он не действует как указатель, потому что я говорю это, потому что если бы у меня был оператор switch, пример:

void ExampleFunction(int iSwitch)
{
    HWND hButton;

    switch (iSwitch)
    {
     case 1:
     hButton = CreateWindow( Blah Blah blah); //<-- Shouldn't it return to hButton's location.
     break;

     case 2: 
     ShowWindow(hButton, SW_SHOW); //<-- Ops forgot what was stored in hButton.
     break;
    }
}

Но посмотреть как новый программист C++ Win32, не следует ли об этом забыть? Просто найдя адрес памяти, а затем захватив содержимое внутри. Если не изменится адрес памяти и т.д.

Я действительно не знаю, не могли бы вы уточнить? Спасибо.


person Trevin Corkery    schedule 17.10.2015    source источник
comment
Пожалуйста, попробуйте создать минимальный, полный и проверяемый пример, потому что в коде вопроса отсутствует много контекста.   -  person Some programmer dude    schedule 17.10.2015
comment
Думайте о HWND как о значении, которое идентифицирует окно. Все, что вы когда-либо делаете, это передаете его функциям, которым нужно знать, к какому окну вы обращаетесь.   -  person David Heffernan    schedule 17.10.2015
comment
указатели изменяют исходное значение вместо создания дубликата, который хранится в этом месте памяти Это очень упрощенный и неточный способ определения указателей.   -  person Lightness Races in Orbit    schedule 17.10.2015
comment
@Lightness Races in Orbit - Ну, читая книги, они, как правило, дают вам упрощенный способ описания чего-либо вместо того, чтобы иметь 5 глав, просто описывающих, что такое указатель. Поэтому я просто скопировал то, что услышал, прочитав 6-е издание C++ Primer Plus.   -  person Trevin Corkery    schedule 17.10.2015
comment
@TrevinCorkery: Хорошо, но я также сказал неточно. Это привело вас к этому недоразумению. Разве это ни о чем не говорит?   -  person Lightness Races in Orbit    schedule 17.10.2015
comment
В пользовательской среде это непрозрачный токен. Перестаньте думать об этом как о чем-то другом. Сохранение данных о состоянии GUI в обработчиках сообщений и т. д. зависит от вас.   -  person Martin James    schedule 17.10.2015
comment
Только заголовок: «Статический HWND — зачем он нужен?» это неверно. Это не обязательно. Для фреймворков с графическим интерфейсом обычно есть хотя бы один «статический» объект верхнего уровня для представления всего приложения, но это не HWND.   -  person Martin James    schedule 17.10.2015
comment
Это не конкретный вопрос Windows API, и поведение, которое смущает OP, не является исключительным для HWND. ОП не понимает, почему они должны объявлять локальные переменные статическими, чтобы они сохраняли свои значения при вызовах функций. Не знаю, как правильно ответить на этот вопрос, но все же попробую.   -  person andlabs    schedule 17.10.2015
comment
Возможный дубликат области действия и времени жизни переменной   -  person IInspectable    schedule 05.03.2018


Ответы (2)


Вероятно, это не самый качественный ответ; предложения по улучшению приветствуются.

Вы правы, предполагая, что значение HWND никогда не меняется, пока окно, на которое указывает HWND, остается активным.

Я предполагаю, что вы написали такой код:

LRESULT CALLBACK wndproc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    HWND button;

    switch (uMsg) {
    case WM_CREATE:
        button = CreateWindowEx(...);
        break;
    case WM_COMMAND:
        if (lParam == (LPARAM) button)
            /* button was clicked; do something */;
    }
    return DefWindowProc(...);
}

и удивляться, почему это не работает, но меняется

    HWND button;

to

    static HWND button;

исправляет это.

Это не свойство HWND. Ничто о сбое кода не связано с тем, что значение HWND изменилось. На самом деле, это вообще не имеет ничего общего с Windows, а все, что связано с C.

Причина, по которой код не работает, заключается в том, что переменная button создается заново каждый раз при вызове функции wndproc(). Видите ли, оконная процедура вызывается много раз, по одному разу для каждого сообщения, которое окно получает во время выполнения вашей программы. Каждый раз вы получаете совершенно новую переменную button, а значение, которое переменная button имела в предыдущих вызовах, теряется. Указатель все еще там, но он не хранится ни в какой переменной или в каком-либо другом месте памяти! Окно не уничтожено. Вы просто не можете добраться до него обычными средствами.

Что делает static, так это сообщает C, что вы хотите, чтобы переменная оставалась при каждом вызове функции. Так что теперь каждый вызов вашей оконной процедуры имеет один и тот же button, и это значение указателя больше не теряется.

Это быстрое решение, и оно не очень хорошо масштабируется для очень больших проектов. В этих случаях лучше использовать структуры, содержащие дескрипторы окон, (возможно) глобальные переменные или использование GWLP_USERDATA или других cbWndExtra байтов. Я предполагаю, что лучший вопрос заключается в том, почему это быстрое исправление продолжает предлагаться в качестве решения подобных проблем других людей здесь, в переполнении стека (или, по крайней мере, почему это быстрое исправление не объясняется), но это то, о чем мы должны думать как сообщество.

Просто помните, что по умолчанию в большинстве языков (не только в C и C++!) локальные переменные функции существуют только на время вызова каждой отдельной функции.

person andlabs    schedule 17.10.2015

В коде в вопросе отсутствует много контекста (так что здесь просто угадывать вслепую), но если код находится в отдельной функции, а переменная hButton является локальной переменной в этой функции, то вы должны помнить, что локальные переменные выходят области действия, когда функция, в которой они находятся, возвращается, и при следующем вызове функции переменная является совершенно новой, уникальной для этого вызова и только для этого вызова.

Также стоит упомянуть, что нестатические локальные переменные никоим образом не инициализируются автоматически. Если вы не инициализируете такую ​​переменную явно, ее значение будет неопределенным, и любое ее использование (кроме инициализации) приведет к неопределенному поведению.

person Some programmer dude    schedule 17.10.2015
comment
Это был не мой реальный код, я знаю, что его много не хватает, потому что я не копировал и не вставлял, я просто написал его здесь для примера, и спасибо, что описали это мне. Теперь я понимаю, что вы, вероятно, имели в виду, HWND и Switch были в одной и той же функции, поэтому я отредактирую основной пост, чтобы сделать это более понятным. - person Trevin Corkery; 17.10.2015
comment
Это был не мой настоящий код. Я знаю, что его много не хватает, потому что я не копировал и не вставлял, я просто написал его здесь для примера, и спасибо, что описали его мне. Пожалуйста, не надо. никогда не делай этого. Не размещайте поддельный код. Не тратьте время каждого. - person David Heffernan; 18.10.2015