четверг, 1 апреля 2010 г.

Для чего используется HINSTANCE, передаваемый в CreateWindow и RegisterClass?

Это перевод What is the HINSTANCE passed to CreateWindow and RegisterClass used for? Автор: Реймонд Чен.

Одним из слабо понимаемых параметров функций CreateWindow и RegisterClass является HINSTANCE (передаваемый либо как параметр, либо как поле записи TWndClass).

Одного имени оконного класса ещё не достаточно для уникальной идентификации класса окна. Каждый процесс имеет свой собственный набор оконных классов, поэтому каждая запись в списке оконных классов состоит из описателя экземпляра (instance handle) и имени класса. Например, вот как мог бы выглядеть список оконных классов, если бы программа загрузила две DLL, каждая из которых зарегистрировала класс с именем "MyClass", передавая описатель DLL как HINSTANCE.
   HINSTANCE    Имя класса
1. USER32.DLL   Static
2. USER32.DLL   Button
3. USER32.DLL   Listbox
4. USER32.DLL   Combobox
5. USER32.DLL   Edit
6. A.DLL        MyClass
7. B.DLL        MyClass
Когда наступает время создать окно, каждый модуль передаёт свой описатель для создания окна, а менеджер окон использует его комбинацию с именем класса для поиска нужного оконного класса.
  CreateWindow('MyClass', ..., hinstA, ...); // создаёт класс 6
  CreateWindow('MyClass', ..., hinstB, ...); // создаёт класс 7
  CreateWindow('MyClass', ..., hinstC, ...); // ошибка
Вот почему регистрация несколькими DLL классов с одинаковым именем "MyClass" является нормальной ситуацией; описатель модуля как раз и используется, чтобы их различать.

Однако в описанном выше правиле есть одно исключение. Если вы укажете флаг CS_GLOBALCLASS при регистрации класса, то менеджер окон будет игнорировать описатель модуля во время поиска этого класса. К примеру, все классы из USER32 зарегистрированы как глобальные. Соответственно, любые следующие вызовы создадут элемент управления edit из USER32:
  CreateWindow('edit', ..., hinstA, ...);
  CreateWindow('edit', ..., hinstB, ...);
  CreateWindow('edit', ..., hinstC, ...);
Если вы регистрируете класс для использования другими модулями в их диалоговых окнах, вам нужно регистрировать его с CS_GLOBALCLASS, потому что, как мы видели ранее, во время создания диалогового окна для создания элементов управления выполняется внутренний вызов CreateWindow с передачей описателя диалога в её параметр HINSTANCE. Поскольку обычно описатель диалога равен описателю DLL, создающей диалог (поскольку этот же описатель используется для поиска шаблона диалога), регистрация класса без флага CS_GLOBALCLASS означает что класс окна не будет найден, потому что он был зарегистрирован с описателем DLL, которая реализует класс, а не которая его использует.

В 16-ти битных Windows описатель экземпляра делал и другие вещи, но сегодня, в мире Win32, они уже не актуальны.

Частой ошибкой является передача HINSTANCE какого-то другого модуля (обычно главного исполняемого файла) при регистрации оконного класса. Теперь, когда вы поняли для чего используется HINSTANCE, вы должны суметь объяснить последствия регистрации класса с неверным HINSTANCE.

Комментариев нет:

Отправить комментарий

Можно использовать некоторые HTML-теги, например:

<b>Жирный</b>
<i>Курсив</i>
<a href="http://www.example.com/">Ссылка</a>

Вам необязательно регистрироваться для комментирования - для этого просто выберите из списка "Анонимный" (для анонимного комментария) или "Имя/URL" (для указания вашего имени и ссылки на сайт). Все прочие варианты потребуют от вас входа в вашу учётку (поддерживается OpenID).

Пожалуйста, по возможности используйте "Имя/URL" вместо "Анонимный". URL можно просто не указывать.

Ваше сообщение может быть помечено как спам спам-фильтром - не волнуйтесь, оно появится после проверки администратором.