Поделиться через


Сведения о классах окон

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

Перед созданием окна этого класса процесс должен зарегистрировать класс окна. Регистрация класса окна связывает процедуру окна, стили классов и другие атрибуты класса с именем класса. Если процесс задает имя класса в функции CreateWindow или CreateWindowEx , система создает окно с процедурой окна, стилями и другими атрибутами, связанными с этим именем класса.

В этом разделе рассматриваются следующие разделы.

Типы классов окон

Существует три типа классов окон:

Эти типы различаются в области и в том, когда и как они регистрируются и уничтожаются.

Системные классы

Системный класс — это класс окон, зарегистрированный системой. Многие системные классы доступны для всех используемых процессов, а другие используются только внутренне системой. Так как система регистрирует эти классы, процесс не может их уничтожить.

Система регистрирует системные классы для процесса в первый раз, когда один из его потоков вызывает функцию User или Windows Graphics Device Interface (GDI).

Каждое приложение получает собственную копию системных классов. Все 16-разрядные приложения под управлением Windows в том же VDM, что и на 16-разрядной версии Windows, делят системные классы.

В следующей таблице описаны системные классы, доступные для использования всеми процессами.

Класс Описание
Кнопка Класс для кнопки.
ComboBox Класс для combo box.
Изменить Класс для элемента управления редактированием.
ЛистБокс Класс для поля списка.
MDIClient Класс для окна клиента MDI.
Полоса прокрутки Класс для полосы прокрутки.
Статика Класс для статического элемента управления.

 

В следующей таблице описаны системные классы, доступные только для использования системой. Они перечислены здесь для полноты.

Класс Описание
ComboLBox Класс для элемента списка, находящегося в комбинированном списке.
DDEMLEvent Класс для событий библиотеки управления динамическим обменом данными (DDEML).
Сообщение Класс окна, предназначенного только для сообщений.
#32768 Класс для меню.
#32769 Класс для окна рабочего стола.
#32770 Класс для диалогового окна.
#32771 Класс для окна переключения задач.
#32772 Класс для заголовков значков.

 

Глобальные классы приложений

Глобальный класс приложения — это класс окна, зарегистрированный исполняемым файлом или библиотекой DLL, доступной всем остальным модулям в процессе. Например, .dll может вызвать функцию RegisterClassEx , чтобы зарегистрировать класс окон, определяющий пользовательский элемент управления как глобальный класс приложения, чтобы процесс, загружающий .dll, может создавать экземпляры пользовательского элемента управления.

Чтобы создать класс, который можно использовать в каждом процессе, создайте класс окна в .dll и загрузите .dll в каждом процессе. Чтобы загрузить .dll в каждом процессе, добавьте его имя в значение AppInit_DLLs в следующем разделе реестра:

\ HKEY_LOCAL_MACHINEПрограммное обеспечение\Корпорация Майкрософт\Windows NT\CurrentVersion\Виндоус

При каждом запуске процесса система загружает указанные .dll в контексте только что запущенного процесса перед вызовом функции точки входа. .dll должен зарегистрировать класс во время процедуры инициализации и указать стиль CS_GLOBALCLASS . Дополнительные сведения см. в разделе "Стили классов".

Чтобы удалить глобальный класс приложения и освободить связанное с ним хранилище, используйте функцию UnregisterClass .

Локальные классы приложений

Локальный класс приложения — это любой класс окна, который исполняемый файл или .dll регистрирует для исключительно своего использования. Хотя можно зарегистрировать любое количество локальных классов, обычно регистрируются только один. Этот класс окна поддерживает процедуру окна главного окна приложения.

Система уничтожает локальный класс при закрытии модуля. Приложение также может использовать функцию UnregisterClass для удаления локального класса и освобождения хранилища, связанного с ним.

Как система находит класс Window

Система поддерживает список структур для каждого из трех типов классов окон. Когда приложение вызывает функцию CreateWindow или CreateWindowEx для создания окна с указанным классом, система использует следующую процедуру для поиска класса.

  1. Найдите список локальных классов приложения для класса с указанным именем, дескриптор экземпляра которого соответствует дескриптору экземпляра модуля. (Несколько модулей могут использовать одно и то же имя для регистрации локальных классов в одном процессе.)
  2. Если имя не находится в списке локальных классов приложения, выполните поиск по списку глобальных классов приложений.
  3. Если имя не находится в списке глобальных классов приложения, выполните поиск по списку системных классов.

Все окна, созданные приложением, используют эту процедуру, включая окна, созданные системой от имени приложения, например диалоговые окна. Можно переопределить системные классы, не затрагивая другие приложения. То есть приложение может зарегистрировать локальный класс приложения с тем же именем, что и системный класс. Это заменяет системный класс в контексте приложения, но не запрещает другим приложениям использовать системный класс.

Регистрация класса окна

Класс окна определяет атрибуты окна, такие как его стиль, значок, курсор, меню и процедура окна. Первым шагом при регистрации класса окна является заполнение структуры WNDCLASSEX сведениями о классе окна. Дополнительные сведения см. в разделе "Элементы класса Окна". Затем передайте структуру функции RegisterClassEx . Дополнительные сведения см. в разделе "Использование классов окон".

Чтобы зарегистрировать глобальный класс приложения, укажите стиль CS_GLOBALCLASS в элементе стиля структуры WNDCLASSEX . При регистрации локального класса приложения не указывайте стиль CS_GLOBALCLASS .

Если вы регистрируете класс окна с помощью версии ANSI RegisterClassEx, RegisterClassExA, приложение запрашивает, чтобы система передавала текстовые параметры сообщений в окна созданного класса, используя набор символов ANSI. Если вы регистрируете класс с помощью версии Unicode RegisterClassEx, RegisterClassExW, приложение запрашивает, чтобы система передавала текстовые параметры сообщений в окна созданного класса, используя набор символов Unicode. Функция IsWindowUnicode позволяет приложениям запрашивать характер каждого окна. Дополнительные сведения о функциях ANSI и Юникоде см. в соглашениях о прототипах функций.

Исполняемый файл или DLL, зарегистрированный классом, является владельцем класса. Система определяет принадлежность класса из члена hInstance структуры WNDCLASSEX, переданной функции RegisterClassEx при регистрации класса. Для библиотек DLL элемент hInstance должен быть дескриптором .dll экземпляра.

Класс не уничтожается, когда выгружается .dll, которому он принадлежит. Таким образом, если система вызывает процедуру окна для окна этого класса, это приведет к нарушению доступа, так как .dll, содержащая процедуру окна, больше не находится в памяти. Процесс должен уничтожить все окна этого класса перед выгрузкой .dll и вызвать функцию UnregisterClass.

Элементы класса Window

Элементы класса окон определяют поведение окон по умолчанию, принадлежащих к классу. Приложение, которое регистрирует класс окна, назначает элементы классу, задав соответствующие члены в структуре WNDCLASSEX и передав структуру функции RegisterClassEx . Функции GetClassInfoEx и GetClassLong извлекают сведения о заданном классе окна. Функция SetClassLong изменяет элементы локального или глобального класса, уже зарегистрированного приложением.

Хотя полный класс окна состоит из многих элементов, система требует только того, чтобы приложение указало имя класса, адрес процедуры окна и дескриптор экземпляра. Используйте другие элементы для определения атрибутов по умолчанию для окон класса, таких как форма курсора и содержимое меню для окна. Необходимо инициализировать все неиспользуемые элементы структуры WNDCLASSEX до нуля или NULL. Элементы класса окна, как показано в следующей таблице.

Элемент Цель
имя класса Отличает класс от других зарегистрированных классов.
Адрес процедуры окна Указатель на функцию, которая обрабатывает все сообщения, отправленные в окна в классе, и определяет поведение окна.
Дескриптор экземпляра Определяет приложение или .dll, зарегистрировав класс.
Курсор класса Определяет курсор мыши, отображаемый системой для окна класса.
Значки классов Определяет большой значок и маленький значок.
Кисть фона класса Определяет цвет и шаблон, заполняющий клиентскую область при открытии или перерисовке окна.
Меню классов Задает меню по умолчанию для окон, которые явно не определяют меню.
Стили классов Определяет, как обновить окно после перемещения или изменения его размера, как обрабатывать двойные щелчки мыши, как выделить пространство для контекста устройства и другие аспекты окна.
Память экстра класса Указывает объем дополнительной памяти в байтах, который система должна зарезервировать для класса. Все окна в классе совместно используют дополнительную память и могут использовать его для любой определяемой приложением цели. Система инициализирует эту память до нуля.
Дополнительная память окна Указывает объем дополнительной памяти в байтах, который система должна зарезервировать для каждого окна, относящегося к классу. Дополнительную память можно использовать для любой определяемой приложением цели. Система инициализирует эту память до нуля.

 

Имя класса

Каждому классу окна требуется имя класса, чтобы отличить один класс от другого. Назначьте имя класса, задав элемент lpszClassName структуры WNDCLASSEX адресу строки, завершаемой значением NULL, указывающей имя. Так как классы окон являются конкретными процессами, имена классов окон должны быть уникальными только в рамках одного процесса. Кроме того, так как имена классов занимают место в частной таблице атомов системы, следует хранить строки имен класса как можно короче.

Функция GetClassName извлекает имя класса, к которому принадлежит данное окно.

Адрес функции обработки окна

Каждому классу требуется адрес процедуры окна для определения точки входа процедуры окна, используемой для обработки всех сообщений для окон в классе. Система передает сообщения в процедуру, когда необходимо, чтобы окно выполнило задачи, такие как прорисовка клиентской зоны или реагирование на входные данные от пользователя. Процесс назначает процедуру окна классу, копируя его адрес в член lpfnWndProc структуры WNDCLASSEX . Для получения дополнительной информации см. раздел Процедуры окна.

Дескриптор экземпляра

Для каждого класса окна требуется дескриптор экземпляра, чтобы идентифицировать приложение или .dll, который зарегистрировал класс. Система требует, чтобы дескриптор экземпляра отслеживал все модули. Система назначает идентификатор каждой копии запущенного исполняемого файла или .dll.

Система передает дескриптор экземпляра в функцию точки входа каждого исполняемого файла (см. WinMain) и .dll (см. DllMain). Исполняемый файл или .dll назначает этому экземпляру дескриптор класса, копируя его в элемент hInstance структуры WNDCLASSEX .

Курсор класса

Курсор класса определяет форму курсора, если он находится в клиентской области окна в классе. Система автоматически задает курсор заданной фигуре при входе курсора в клиентскую область окна и гарантирует, что она сохраняет эту фигуру, пока она остается в клиентской области. Чтобы назначить фигуру курсора классу окна, загрузите предопределенную фигуру курсора с помощью функции LoadCursor , а затем назначьте возвращенный дескриптор курсора элементу hCursor структуры WNDCLASSEX . Кроме того, предоставьте пользовательский ресурс курсора и используйте функцию LoadCursor , чтобы загрузить ее из ресурсов приложения.

Система не требует курсора класса. Если приложение задает элемент hCursor структуры WNDCLASSEX значение NULL, курсор класса не определен. В системе предполагается, что окно устанавливает фигуру курсора при каждом переходе курсора в окно. Окно может задать фигуру курсора, вызвав функцию SetCursor всякий раз, когда окно получает сообщение WM_MOUSEMOVE . Дополнительные сведения о курсорах см. в разделе "Курсоры".

Значки классов

Значок класса — это изображение, которое система использует для представления окна определенного класса. Приложение может иметь два значка класса — один большой и один маленький. Система отображает значок большого класса окна в окне переключения задач, которое отображается при нажатии клавиш ALT+TAB, а также в представлениях больших значков панели задач и обозревателя. Маленький значок класса отображается в строке заголовка окна и в представлениях небольших значков панели задач и обозревателя.

Чтобы назначить большой и маленький значок классу окна, укажите дескриптор значков в элементах hIcon и hIconSm структуры WNDCLASSEX . Размеры значков должны соответствовать требуемым измерениям для значков большого и небольшого класса. Для значка большого класса можно определить необходимые измерения, указав SM_CXICON и SM_CYICON значения в вызове функции GetSystemMetrics . Для значка небольшого класса укажите значения SM_CXSMICON и SM_CYSMICON . Дополнительные сведения см. в разделе "Значки".

Если приложение задает члены hIcon и hIconSm структуры WNDCLASSEX значение NULL, система использует значок приложения по умолчанию в качестве значков большого и небольшого класса для класса окна. Если указать значок большого класса, но не небольшой, система создает небольшой значок класса на основе большого. Однако если указать небольшой значок класса, но не большой, система использует значок приложения по умолчанию в качестве значка большого класса и указанного значка в качестве значка небольшого класса.

Вы можете переопределить большой или маленький значок класса окна для определенного окна с помощью сообщения WM_SETICON. Вы можете получить текущий значок большого или небольшого класса с помощью сообщения WM_GETICON .

Кисть для фона класса

Фоновая кисть класса подготавливает клиентскую область окна для последующего рисования приложением. Система использует кисть для заполнения клиентской области сплошным цветом или шаблоном, тем самым удаляя все предыдущие изображения из этого расположения, принадлежат ли они окну или нет. Система уведомляет окно о том, что его фон должен быть окрашен, отправив WM_ERASEBKGND сообщение в окно. Дополнительные сведения см. в разделе "Кисти".

Чтобы назначить фоновую кисть классу, создайте кисть с помощью соответствующих функций GDI и назначьте возвращенный дескриптор кисти члену hbrBackground структуры WNDCLASSEX.

Вместо создания кисти приложение может задать элемент hbrBackground одному из стандартных значений цвета системы. Список стандартных системных значений цветов см. в разделе SetSysColors.

Чтобы использовать стандартный системный цвет, приложение должно увеличить значение цвета фона на один. Например, COLOR_BACKGROUND + 1 — это системный цвет фона. Кроме того, можно использовать функцию GetSysColorBrush для получения идентификатора кисточки, соответствующей стандартному цвету системы, а затем указать идентификатор в члене hbrBackground структуры WNDCLASSEX.

Система не требует, чтобы у класса окна была кисть фона. Если для этого параметра задано значение NULL, окно должно покрасить собственный фон при получении сообщения WM_ERASEBKGND .

Меню классов

Меню класса определяет меню по умолчанию, которое будет использоваться окнами в классе, если явное меню не задано при создании окон. Меню — это список команд, из которых пользователь может выбрать действия для приложения для выполнения.

Вы можете назначить меню классу, задав элемент lpszMenuName структуры WNDCLASSEX в адрес строки, завершающейся значением NULL, которая указывает имя ресурса меню. Предполагается, что меню является ресурсом в данном приложении. Система автоматически загружает меню при необходимости. Если ресурс меню определяется целым числом, а не именем, приложение может задать элемент lpszMenuName для этого целого числа, применяя макрос MAKEINTRESOURCE перед назначением значения.

Система не требует меню класса. Если приложение задает член lpszMenuName структуры WNDCLASSEXзначение NULL, окна в классе не имеют строк меню. Даже если меню класса не задано, приложение по-прежнему может определить строку меню для окна при создании окна.

Если меню задано для класса, а затем создается дочернее окно этого класса, меню игнорируется. Дополнительные сведения см. меню.

Стили классов

Стили классов определяют дополнительные элементы класса окна. Два или более стилей можно объединить с помощью побитового оператора OR (|). Чтобы назначить стиль классу окна, назначьте стиль элементу стиля структуры WNDCLASSEX . Список стилей классов см. в разделе "Стили классов окна".

Классы и контексты устройств

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

Если стиль контекста устройства явно не задан, система предполагает, что каждое окно использует контекст устройства, полученный из пула контекстов, поддерживаемых системой. В таких случаях каждое окно должно получить и инициализировать контекст устройства перед рисованием и освободить его после рисования.

Чтобы избежать получения контекста устройства каждый раз, когда необходимо выполнить отрисовку в окне, приложение может указать стиль CS_OWNDC для класса окна. Этот стиль класса направляет систему на создание контекста частного устройства, то есть для выделения уникального контекста устройства для каждого окна в классе. Приложению требуется только один раз получить контекст, а затем использовать его для всех последующих рисунков.

Память высшего класса

Система внутренне поддерживает структуру WNDCLASSEX для каждого класса окон в системе. Когда приложение регистрирует класс окон, оно может направлять систему на выделение и добавление числа дополнительных байтов памяти в конец структуры WNDCLASSEX . Эта память называется дополнительной памятью класса и разделяется всеми окнами, принадлежащими к классу. Используйте дополнительную память класса для хранения любой информации, относящейся к классу.

Так как дополнительная память выделяется из локальной кучи системы, приложение должно использовать дополнительную память для класса экономно. Функция RegisterClassEx завершается ошибкой, если запрошенная дополнительная память класса превышает 40 байтов. Если приложению требуется более 40 байт, оно должно выделить собственную область памяти и сохранить указатель на эту область в дополнительной памяти класса.

Функции SetClassWord и SetClassLong копируют значение в дополнительную память класса. Чтобы получить значение из дополнительной памяти класса, используйте функции GetClassWord и GetClassLong . Член cbClsExtra структуры WNDCLASSEX указывает объем дополнительной памяти класса для выделения. Приложение, которое не использует дополнительную память класса, должно инициализировать член cbClsExtra до нуля.

Дополнительная память для окна

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

Так как дополнительная память выделяется из системной локальной кучи, приложение должно экономно использовать дополнительную память для окна. Функция RegisterClassEx завершается ошибкой, если запрошенная дополнительная память окна превышает 40 байтов. Если приложению требуется более 40 байт, она должна выделить собственную память и сохранить указатель на память в дополнительном окне.

Функция SetWindowLong копирует значение в дополнительную память. Функция GetWindowLong извлекает значение из дополнительной памяти. Член cbWndExtra структуры WNDCLASSEX указывает объем дополнительной памяти окна, которую нужно выделить. Приложение, которое не использует память, должно инициализировать cbWndExtra до нуля.