Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
MS Windows. Элементы архитектуры и системное программирование..pdf
Скачиваний:
273
Добавлен:
01.05.2014
Размер:
1.98 Mб
Скачать

Реестр Windows.

Автор: Сидякин И.М.

Московский Государственный Технический Университет им. Н.Э. Баумана. Кафедра ИУ-3, (11.1998)

Email:sidiakin@iu3.bmstu.ru

Реестр это централизованная база данных операционной системы, в которой сохраняется информация о конфигурации системы, аппаратных и программных настройках. Реестр заменяет файлы config.sys autoexec.bat и файлы .INI которые использовались для этих целей в версиях Windows 3.x. Однако для обеспечения совместимости с программным обеспечением, разработанным для 16-ти разрядных операционных систем, Windows 95 по-прежнему поддерживает использование этих файлов. Реестр в отличие от текстовых INI файлов разработан как двоичная база данных. Для просмотра и модификации реестра используют программу Редактор Реестра (REGEDIT.EXE) или набор API функций Windows. Реестр используют различные программные компоненты операционной системы. Общая структура взаимодействия системных модулей с реестром приведена на рисунке 1.

Инициализация

 

 

 

 

Аппаратная

Поиск

 

(Setup)

 

 

 

 

устройств

 

 

 

 

 

конфигурация

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Конфигурация

Версия

и

 

конфигурация

 

пользователей

 

 

 

 

Средства

 

 

 

 

 

 

 

 

администриров

 

 

 

 

Реестр Windows

 

 

 

 

Системное

 

ания

 

 

 

 

 

 

 

 

 

ядро Windows

 

 

 

 

 

 

 

 

 

Управление

 

 

 

 

 

 

Использование ресурсов и

 

 

 

 

 

 

загрузкой

 

 

 

 

 

конфигурация

 

 

 

 

Драйверы аппаратуры

Рисунок 1. Использование Реестра.

Новые записи вносятся в реестр, при установке нового оборудования и программного обеспечения. Большое количество настроек в реестре можно изменить через Панель Управления.

Все 32-х разрядные операционные системы Windows используют реестр, однако, структуры их реестров несколько отличаются друг от друга. Далее в основном будет рассматриваться структура реестра ОС Windows 95.

85

Структура реестра Windows.

Наиболее просто изучить структуру реестра с помощью программы RegEdit.Exe. Эта программа отображает содержимое реестра в виде древовидной структуры.

Рисунок 2. Структура Реестра.

Левое окно содержит структуру подкаталогов реестра. Эти подкаталоги называются ключами (keys). Каждый ключ в реестре может содержать список значений (values). Каждое значение имеет имя и данные. Например, на рисунке 2 ключ

HKEY_LOCAL_MACHINE\System\Control содержит два значения. Первое с именем

Default данные, которого не определены (value not set). Второе, с именем Current User, которое равно строке «Joe». Кроме значений ключ может содержать подключи

(subkeys). Например, System это подключ ключа HKEY_LOCAL_MACHINE. Структура реестра напоминает структуру каталогов файловой системы с каталогами (ключами) и файлами (значениями). Каждое значение реестра имеет тип. Например: REG_BINARYдвоичные данные, REG_DWORD - двойное слово, REG_SZ - asciiz строка. Эти типы используются наиболее часто.

Рисунок 3. Редактирование Реестра. RegEdit.exe.

На рисунке 3 показано как помощью программы regedit в реестр добавляются новые ключи и значения.

86

Корневые ключи (Root Keys).

В реестре Windows имеется шесть так называемых корневых ключей. Два основных ключа HKEY_LOCAL_MACHINE и HKEY_USERS распределяют информацию хранящуюся в реестре на два раздела: информация о компьютере и информация о пользователе.

HKEY_CLASSES_ROOT

Записи этого ключа используются для сохранения настроек приложений использующих технологии DDE и OLE. В частности в подключе CLSID регистрируются компоненты COM. Здесь также хранятся записи связывающие типы данных (типы файлов) с приложениями которые их обрабатывают (см. главу «Оболочка Windows»). Этот ключ отображается в ключ HKEY_LOCAL_MACHINE\SOFTWARE\Classes. Это означает, что одну и ту же информацию можно получить через тот или другой ключ. В реестре такой двойной способ доступа к одним и тем же данным применяется для удобства.

HKEY_CURRENT_USER

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

HKEY_LOCAL_MACHINE

Записи ключа описывают физическое состояние компьютера, включая данные о системной памяти, установленной аппаратуре и программном обеспечении. Этот ключ содержит подключи в которых хранится информация о конфигурации, в том числе самонастраивающихся устройств (Plug and Play), сетевых настроек, настроек программного обеспечения, и другая системная информация. Назначение некоторых подключей приводится ниже.

Подключ \Enum содержит древовидную структуру с информацией о всём установленном оборудовании. Каждая ветвь дерева соответствует одной из шин на которых размещаются устройства. Например, отдельные ветви дерева имеются для устройств SCSI (подключ SCSI), устройств PCI (подключ PCI), самонастраивающихся устройств ISA (подключ ISAPNP), сетевых адаптеров (подключ Network) и системных устройств (подключ Root и подключ BIOS). К системным устройствам настройки которых хранятся в подключе Root относятся например материнская плата, мышь, последовательные порты. К шине BIOS относятся контроллеры прерываний и ПДП, системный таймер и т.п. Из этого перечисления можно заключить, что шина это логическое понятие не всегда соответствующее обычной интерпретации этого слова. В частности BIOS и Root так же считаются отдельными шинами.

Подключ \Software содержит настройки установленного программного обеспечения. Здесь приложения хранят свои конфигурационные параметры. При установке приложения программа инсталлятор (например, созданная с помощью InstallShield) создаёт в реестре подключи следующего формата:

HKEY_LOCAL_MACHINE\Software\НазваниеКомпании\НазваниеПрограммногоПродукта\ Версия

HKEY_LOCAL_MACHINE\Software\CompanyName\ProductName\Version

Операционная система также хранит ряд своих настроек в ключе, имеющем такой формат:

HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion.

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

HKEY_USERS

87

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

HKEY_CURRENT_CONFIG

Этот ключ отображается в подключ HKEY_LOCAL_MACHINE\Config. Здесь хранятся настройки не входящие в раздел информации о пользователе. Например, настройки текущего выбранного принтера и настройки дисплейного адаптера.

HKEY_DYN_DATA

Этот ключ имеется только в реестрах Windows 95 и Windows 98. Часть реестра, которая хранится в этом ключе, загружается в память. Подключи и значения этого ключа используются для организации обмена данными между пользовательскими приложениями и драйверами, расположенными в нулевом кольце. Важным свойством реестра является то, что он доступен из нулевого и третьего кольца защиты. Драйверы в частности используют ключ HKEY_DYN_DATA для передачи своих текущих параметров пользовательским приложениям. Подключ \ConfigManager\Enum содержит информацию о текущем состоянии аппаратных устройств зарегистрированных в подключе \Enum корневого ключа HKEY_LOCAL_MACHINE.

HKEY_PERFORMANCE_DATA

Этот ключ используется в реестре NT для доступа к текущему состоянию оборудования. В реестрах операционных систем Windows 95/98 этот ключ отсутствует. На самом деле реестр Windows NT не имеет физического пространства, в котором хранится информация этого ключа. Вместо этого операция чтения значения или подключа транслируется системой в вызов соответствующего программного модуля (драйвера) который возвращает запрашиваемый параметр.

Функции API для работы с реестром.

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

Работа с реестром начинается с открытия или создания ключа. Эта операция выполняется функцией RegCreateKeyEx или RegOpenKeyEx.

LONG RegCreateKeyEx(

//

ссылка на корневой ключ

HKEY hKey,

LPCTSTR lpSubKey,

//

адрес строки с именем подключа

DWORD Reserved,

//

зарезервировано

LPTSTR lpClass,

//

адрес строки с именем класса ключа

DWORD dwOptions,

//

флаги

REGSAM samDesired, //

права доступа

LPSECURITY_ATTRIBUTES

lpSecurityAttributes, // адрес структуры

 

//

прав доступа

PHKEY phkResult,

адрес возвращаемой ссылки на ключ

LPDWORD lpdwDisposition // как был открыт ключ (адрес)

);

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

HKEY_CLASSES_ROOT

HKEY_CURRENT_CONFIG

HKEY_CURRENT_USER

HKEY_LOCAL_MACHINE

HKEY_USERS

Windows NT: HKEY_PERFORMANCE_DATA

Windows 95 и Windows 98: HKEY_DYN_DATA

88

lpSubKey это указатель на строку оканчивающуюся нулём (asciiz строку) которая содержит имя подключа. Имя должно начинаться с символа ‘\’.Например

‘\Software\MyCompany\MyApplication’.

lpClass - указатель на asciiz строку с именем класса ключа (типа ключа). Например

‘REG_SZ’.

dwOptions по умолчанию равен REG_OPTION_NON_VOLATILE. В этом случае данные записанные под этим ключом сохранятся после перезагрузки компьютера. Windows 95 не поддерживает других вариантов.

SamDesired определяет права доступа к ключу. Например, KEY_ALL_ACCESS - полный доступ или KEY_EXECUTE - разрешено только чтение. Параметр LpSecurityAttributes в Windows 95 не используется и должен быть равен NULL.

Функция возвращает по указателю phkResult ссылку на созданый или открытый ключ, а

по указателю lpdwDisposition константу REG_CREATED_NEW_KEY, если ключ был создан или константу REG_OPENED_EXISTING_KEY, если был открыт уже существующий ключ.

Пример создания ключа:

Result = RegCreateKeyEx( HKEY_CLASSES_ROOT, «\MyKey», 0, "REG_SZ", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, 0,

&hKey, &dwDisposition);

Функция CloseKey закрывает ключ. Эту функцию необходимо вызвать после окончания работы с ключом и значениями внутри ключа.

LONG RegCloseKey(

HKEY hKey // ссылка на ключ

);

Операционная система кэширует операции записи в реестр. Это означает что данные, записанные в реестр, сохраняются на диск не во время операции записи, а впоследствии в «удобное» с точки зрения системы время. Для того чтобы заставить систему сохранить данные на диске минуя кэш, следует использовать функцию

RegFlushKey.

Функция RegDeleteKey предназначена для удаления ключей.

LONG RegDeleteKey(

HKEY hKey, // ссылка на открытый корневой ключ LPCTSTR lpSubKey // адрес строки с именем подключа

);

Для удаления ключа не нужно его открывать.

В Windows NT ключ может быть удалён только в том случае, если он не содержит подключей.

Функция RegSetValueEx используется для записи значений в ключе. В параметрах этой функции следует указать ссылку на ране открытый ключ.

LONG RegSetValueEx(

// ссылка на ключ, в который записывается

HKEY hKey,

значение

 

LPCTSTR lpValueName, // указатель на строку с именем значения

DWORD Reserved,

// зарезервировано

DWORD dwType,

// флаг типа значения

CONST

BYTE *lpData,

//

адрес данных значения

DWORD

cbData

//

размер данных значения

);

Например:

Result = RegSetValueEx (hKey, «MyValue», 0, REG_SZ, (BYTE *)lpData, dwDataLen);

89

С помощью функции RegQueryValue можно прочитать значение, размещённое в заданном ключе.

LONG RegQueryValueEx(

HKEY hKey, // ссылка на ключ в котором размещено значение LPTSTR lpValueName, // указатель на строку с именем значения LPDWORD lpReserved, // зарезервировано

LPDWORD lpType, // адрес буфера для типа значения LPBYTE lpData, // адрес буфера для данных значения

LPDWORD lpcbData // адрес буфера для размера данных значения

);

Например:

Result = RegQueryValueEx(hKey, «MyValue», 0, «REG_SZ»,

(BYTE *)lpData, dwDataLen);

Windows API также содержит функции RegEnumKey и RegEnumValue которые позволяют организовать сканирование по ветвям структуры реестра и спискам значений.

Пример работы с реестром на Delphi.

В Delphi для работы с реестром можно использовать функции API, однако, удобнее воспользоваться надстройкой над этими функциями реализованной в виде класса

TRegistry.

Uses Registry, RegStr;

Var Reg : TRegistry;

DisabeVxD : Boolean;

Reg := TRegistry.Create; Reg.RootKey :=HKEY_LOCAL_MACHINE;

if Reg.OpenKey(REGSTR_PATH_CLASS +'\LTMI\HOST', True) then begin

if DisableVxD then begin

if Reg.ValueExists('StaticVxD') then Reg.DeleteValue('StaticVxD');

end

else if Not Reg.ValueExists('StaticVxD') then Reg.WriteString('StaticVxD', 'tmihost.vxd');

Reg.CloseKey;

end;

Reg.Destroy;

REGSTR_PATH_CLASS это константа определённая в модуле RegStr - 'System\CurrentControlSet\Services\Class’. В примере в ключе с полным именем HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\Class\LTMI\HOST создаётся строковое значение ‘StaticVxD’. Этому значению присваивается строка ‘tmihost.vxd’. Значение создаётся в случае если DisableVxD равно TRUE и удаляется, если

DisableVxD равно FALSE.

HKEY_LOCAL_MACHINE

|System

|CurrentControlSet

|Services

|Class

|LTMI

|HOST

StaticVxD = ‘tmihost.vxd’

90

Файлы реестра.

Реестр Windows 95 хранится в двух файлах. Раздел с информацией о пользователе хранится в файле USER.DAT, а раздел с информацией о компьютере в файле SYSTEM.DAT. По умолчанию оба файла размещаются в каталоге Windows\System. При загрузке опреационной системы создаются копии этих файлов - USER.DA0 и SYSTEM.DA0. Если работа Windows завершается аварийно содержимое файлов USER и SYSTEM может быть повреждено. В этом случае система пытается автоматически восстановить эти файлы из копий. Однако в ряде случаев автоматическое восстановление реестра невозможно (Если копии также повреждены). Реестр можно сохранить и восстановить (если он был прежде сохранён) вручную с помощью программы RegEdit. Эта программа может быть запущена из командной строки в случае если оболочка Windows не загружается из за повреждений в реестре .

Содержимое реестра полностью или частично можно экспортировать в текстовый файл

иимпортировать из текстового файла. В ряде случаев для внесения записей в реестр применяется технология импорта записей из текстового файла. Для этого можно использовать редактор реестра RegEdit или функции API: RegLoadKey, RegReplaceKey

иRegRestoreKey. Ключи реестра вместе с содержимым сохраняются в текстовом файле функцией RegSaveKey. Ниже приводится пример такого текстового файла:

REGEDIT4

[HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\SAMPDRV] "ImagePath"="\\SystemRoot\\system32\\drivers\\sampdrv.sys" "Type"=dword:00000001

"Start"=dword:00000001

"Group"="Base"

"ErrorControl"=dword:00000001

Этот файл с расширением .reg содержит информацию необходимую для регистрации драйвера WDM sampdrv.sys в реестре Windows 98.

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

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

91

Оболочка Windows (Shell).

Автор: Сидякин И.М.

Московский Государственный Технический Университет им. Н.Э. Баумана. Кафедра ИУ-3, (11.1998)

Email:sidiakin@iu3.bmstu.ru

Оболочка Windows это модуль операционной системы, который отвечает за интерфейс с пользователем. Оболочка представляет «видимую» часть операционной системы. Оболочка включает набор компонентов, которые позволяют оператору перемещаться по системе каталогов, запускать программы, производить различные настройки и т.п. Оболочка допускает программное управление её компонентами. Оболочка Windows расширяема. Это означает, что к Оболочке могут быть легко добавлены новые компоненты. Так называемые Расширения Оболочки (Shell extensions) разрабатываются по правилам объектов (COM). В этой главе вопрос проектирования расширений оболочки с использованием COM технологий не рассматривается. Далее будут приведены несколько полезных примеров использования свойств Оболочки в обход интерфейсов COM.

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

Связь документов и приложений.

Тип файла традиционно определяется его расширением. Расширения файлов регистрируются в реестре. Каждому расширению можно так же через реестр поставить в соответствие набор свойств. Например, можно связать файл данных с иконкой, которая будет отображаться вместе с именем файла в окне Проводника. Можно также связать расширение файла данных с приложением, которое работает с файлами этого типа. Для организации такой связи следует вначале зарегистрировать расширение файла данных. В корневом ключе HKEY_CLASSES_ROOT создаётся подключ с именем расширения файла данных. Например ,для файла с расширением .MFE (my files extension) создаётся ключ:

HKEY_CLASSES_ROOT\.MFE

Сразу после создания ключа он содержит единственное неопределённое значение с именем (Default) Это значение надо проинициализировать строкой содержащей имя типа документа. Например:

(Default) = MyFiles

Имя типа является одновременно именем нового подключа который должен быть создан в том же корневом ключе HKEY_CLASSES_ROOT.

HKEY_CLASSES_ROOT\MyFiles

Вэтом ключе будут храниться все свойства документа нового типа.

Взначении (Default) этого ключа указывается строка, которая будет отображаться в Проводнике вместе с именем файла документа в колонке Type.

Следует отметить, что допускается ссылка на один и тот же ключ типа документа из нескольких ключей расширений.

92

Рисунок 1. Окно Проводника.

Для того чтобы связать тип документа с иконкой следует добавить в ключ типа документа подключ (не значение) с именем DefaultIcon.

HKEY_CLASSES_ROOT\MyFiles\DefaultIcon

Значение (Default) этого подключа должно содержать строку с именем файла, в котором находится иконка и (если из файла берётся не первая по списку иконка) её индекс.

(Default) = C:\Program Files\MyAppDir\MyApp.exe ,1

В этом примере иконка располагается в файле MyApp.exe и её индекс равен 1.

Оболочка может автоматически создавать новые файлы документов типы, которых зарегистрированы в реестре. Эта операция производится, например, через меню File- >New Проводника. Для того чтобы это работало необходимо добавить в ключ расширения файла подключ с именем ShellNew. В нашем случае:

HKEY_CLASSES_ROOT\.MFE\ShellNew

В этот подключ можно записать следующие значения: (В начале указано имя значения затем его данные)

NullFile «»

Оболочка создаёт пустой файл с заданным расширением.

FileName «Path»

Оболочка создаёт новый файл и копирует в него содержимое файла с именем ‘Path’.

Data Двоичные данные

Оболочка создаёт новый файл и копирует в него двоичные данные значения Data.

Command Командная строка

Оболочка выполняет указанную командную строку. Этот способ используется, в случае если какое либо приложение самостоятельно создаёт свои файлы данных.

Записи реестра могут использоваться для добавления специфических для документа операций. Проводник имеет стандартную систему пунктов меню содержащую список операций над файлами данных. Эти операции перечислены в меню File и в всплывающем меню. Этот список может быть расширен или изменён. Вначале следует создать подключ с именем Shell в ключе типа документа:

93

HKEY_CLASSES_ROOT\MyFiles\Shell

Затем создать в этом подключе дополнительные подключи для каждого из пунктов меню. Например:

HKEY_CLASSES_ROOT\MyFiles\Shell\Edit

HKEY_CLASSES_ROOT\MyFiles\Shell\Open

Значения (Default) задают строки отображаемые в пунктах меню Проводника. Например «&Edit» (символ & определяет горячую клавишу).

Далее необходимо связать пункт меню с действием. Для этого в каждом подключе соответствующем пункту меню следует создать подключ с именем Command. Значение (Default) подключа Сommand должно содержать командную строку которая будет выполнятся при выборе пункта меню. Например:

HKEY_CLASSES_ROOT\ MyFiles\Shell\Edit\Command

(Default) = C:\Program Files\MyAppDir\MyApp.Exe %1

%1 указывает на то, имя файла данных будет передано приложению MyApp.exe при запуске через командную строку.

Запуск приложений в процессе загрузки операционной системы.

Иногда возникает необходимость в запуске приложений (например, антивирусов) при загрузке ОС. Эта задача так же легко решается с помощью реестра.

В реестре имеется два ключа: HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\RunOnce

и

HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run

Ключ RunOnce используется для однократного запуска приложений. Записи в этом ключе удаляются после загрузки системы. Приложения, которые зарегистрированы в ключе Run будут запускаться всякий раз при загрузке ОС.

Например, для однократного запуска приложения MyApp.exe следует добавить в ключ RunOnce следующее значение:

MyAppId = «C:\Program Files\MyAppDir\MyApp.exe»

Имя значения MyAppId должно быть уникально в этом ключе.

Размещение иконки в поле статуса Панели задач.

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

Рисунок 2. Панель задач.

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

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

94

Функция Shell_NotifyIcon.

WINSHELLAPI BOOL WINAPI Shell_NotifyIcon(

DWORD dwMessage,

// код операции

PNOTIFYICONDATA pnid

// указатель на структуру

NOTIFYICONDATA

 

);

 

Параметр dwMessage может принимать одно из трёх значений: NIM_ADD - добавить иконку

NIM_DELETE - удалить иконку NIM_MODIFY - изменить параметры иконки

pnid - указатель на структуру, которая должна быть размещена и инициализирована перед вызовом функции.

Функция возвращает FALSE в случае ошибки.

Структура NOTIFYICONDATA.

typedef struct _NOTIFYICONDATA { DWORD cbSize;

HWND hWnd; UINT uID; UINT uFlags;

UINT uCallbackMessage; HICON hIcon;

char szTip[64];

} NOTIFYICONDATA, *PNOTIFYICONDATA;

Поля структуры

cbSize

Размер структуры NOTIFYICONDATA.

hWnd

Указатель окна которому будут транслироваться сообщения от иконки.

uID

Произвольный идентификатор иконки.

uFlags

Флаги указывающие какие из полей структуры заданы.

NIF_ICON Поле hIcon инициализировано. NIF_MESSAGEПоле uCallbackMessage инициализировано. NIF_TIP Поле szTip инициализировано.

uCallbackMessage

Код сообщения от иконки. Задаётся, как и идентификатор иконки программистом. Сообщение с таким кодом транслируется окну hWnd приложения, как реакция на событие мыши в поле иконки.

hIcon

Указатель на рисунок иконки.

szTip

Всплывающий над иконкой текст.

Пример.

Ниже приведены фрагменты программы написанной на Microsoft Visual C 5.0. В данном примере CTaskBar это класс главного окна приложения. К классу добавлены три метода: AddTaskBarIcon, который размещает иконку в поле статуса, DelTaskBarIcon, который удаляет иконку и обработчик сообщения WM_TASKBAR (= WM_USER+1) OnTaskBarNotify. Пример также показывает, как установить обработчик нестандартного сообщения (WM_TASKBAR).

95

//определения

 

//идентификатор

иконки

#define

TB_ID

100

#define

WM_TASKBAR

WM_USER+1

//код сообщения

от иконки

...

//описание класса окна приложения class CTaskBar : public CDialog

{

...

//прототип процедуры добавления иконки в поле статуса

void DelTaskBarIcon();

//прототип процедуры удаления иконки из поля статуса void AddTaskBarIcon();

...

//прототип обработчика сообщения в описании класса СTaskBar afx_msg LONG OnTaskBarNotify(UINT, LONG);

...

} //конец описания класса окна

...

//добавление обработчика сообщения в карту сообщений окна

BEGIN_MESSAGE_MAP(CTaskBar, CDialog)

...

ON_MESSAGE(WM_TASKBAR, OnTaskBarNotify)

...

END_MESSAGE_MAP()

...

//Процедура размещения иконки в поле статуса. void CTaskBar::AddTaskBarIcon()

{

BOOL res;

NOTIFYICONDATA tnid;

LPSTR lpszTip = "Тест.";

//иконка приложения

HICON hicon

=

AfxGetApp()->LoadIcon(IDR_MAINFRAME);

tnid.cbSize

=

sizeof(NOTIFYICONDATA);

//указатель

(handle) окна хранится в переменной m_hWnd класса окна.

tnid.hWnd =

m_hWnd;

//указатель окна

tnid.uID =

TB_ID;

//идентификатор иконки

tnid.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP; tnid.uCallbackMessage = WM_TASKBAR;

tnid.hIcon = hicon; if (lpszTip)

lstrcpyn(tnid.szTip, lpszTip, sizeof(tnid.szTip));

else

tnid.szTip[0] = '\0'; //если всплывающая надпись не нужна res = Shell_NotifyIcon(NIM_ADD, &tnid);

if (hicon) DestroyIcon(hicon); return;

}

...

//Процедура удаления иконки из поля статуса void CTaskBar::DelTaskBarIcon()

{

BOOL res; NOTIFYICONDATA tnid;

tnid.cbSize = sizeof(NOTIFYICONDATA);

//указатель (handle) окна хранится в переменной m_hWnd класса окна. tnid.hWnd = m_hWnd ;

tnid.uID = TB_ID;

res = Shell_NotifyIcon(NIM_DELETE, &tnid); return;

}

...

//Обработчик сообщений от иконки

LONG CTaskBar::OnTaskBarNotify(UINT wParam, LONG lParam)

{

//wParam содержит идентификатор иконки

96

//lParam содержит код сообщения мыши

//в этом примере обрабатывается только код WM_LBUTTONDOWN

if((wParam == TB_ID) && ((UINT)lParam == WM_LBUTTONDOWN)) {

MessageBox("В области иконки нажата левая кнопка мыши.", "Сообщение.", MB_OK);

}

return 1;

}

...

Delphi.

Функция Shell_NotifyIcon, константы, тип TNotifyIconData и указатель на него

PNotifyIconData объявлены в модуле ShellApi. (Delphi 3.0)

Для обработки нестандартного сообщения следует объявить обработчик сообщения при описании класса окна используя ключевое слово message.

const

WM_TASKBAR = WM_USER + 1;

TB_ID

= 100;

type

TTaskBarForm = Class(TForm)

...

Procedure OnTaskBarNotify(Var Msg : TMessage); message WM_TASKBAR;

...

End;

Обработчик сообщения может выглядеть, например, так:

Procedure TTaskBarForm.OnTaskBarNotify(Var Msg : TMessage); begin

if (Msg.wParam = TB_ID)

and (ShortInt(Msg.lParam) = WM_LBUTTONDOWN) then

MessageBox(nil, "В области иконки нажата левая кнопка мыши.", "Сообщение.", mbOk);

end;

Указатель окна (handle) хранится в поле Handle класса окна.

tnid.hWnd := Self.Handle;

Приложения Панели Управления (Control Panel Applets).

Приложения Панели Управления это динамические библиотеки доступные через Окно Панели Управления Windows.

97

Рисунок 3. Панель управления.

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

Создание и регистрация Приложения Панели Управления несложная процедура. Windows поддерживает специальный программный интерфейс Приложений Панели Управления. Как уже было отмечено, Приложение реализуется в виде динамической библиотеки. DLL должна экспортировать функцию с именем CplApplet. Это точка входа Приложения. Система вызывает эту функцию в нескольких случаях. Например, при загрузке Приложения или когда пользователь щёлкает по иконке приложения в окне Панели Управления. Эту функцию, конечно, может вызвать не только Оболочка Windows, но и любое приложение. Ниже приводится интерфейс этой функции:

LONG APIENTRY CPlApplet( HWND hwndCPl,

UINT uMsg ,

LONG lParam1,

LONG lParam2

);

Функция имеет четыре параметра.

HwndCPl - ссылка на окно Панели Управления в случае если функция вызвана Оболочкой.

uMsg - код сообщения.

lParam1 и lParam2 32-х разрядные параметры значения которых зависят от кода сообщения.

Оболочка или какое либо пользовательское приложение может вызвать функцию со следующими кодами сообщений:

CPL_INIT посылается Приложению Панели управления при загрузке.

Вобработчике этого сообщения, как правило, производятся различные процедур по инициализации. Если при инициализации возникли ошибки, функция должна вернуть 0.

Вэтом случае Приложение не будет загружено.

98

Если инициализация проведена успешно, оболочка посылает сообщение CPL_GET_COUNT. Это запрос количества диалоговых окон, которое поддерживает приложение. Учитываются только те окна которые могут быть непосредственно вызваны из окна Панели Управления. Функция возвращает количество таких окон. Для каждого указанного диалогового окна в Панели Управления будет отображаться отдельная иконка.

Затем Оболочка посылает по паре сообщений CPL_INQUIRE и CPL_NEWINQUIRE для каждого из диалоговых окон. В параметре lParam1 передаётся порядковый номер диалогового окна. Приложение должно заполнить структуры CPLINFO или NEWCPLINFO указатели, на которые передаются в параметре lParam2. Буферы для этих структур размещаются вызывающей программой. Эти структуры описывают параметры каждого диалогового окна Приложения. Приложение может обрабатывать сообщения CPL_INQUIRE или CPL_NEWINQUIRE по выбору, однако новые версии оболочки ( начиная с Internet Explorer 4.0) корректно отображают иконки в Окне Панели Управления только в случае если Приложение передаёт параметры диалоговых окон в структуре NEWCPLINFO. Ниже приводится формат структур:

typedef struct tag CPLINFO { int idIcon;

int idName; int idInfo; LONG lData;

} CPLINFO;

typedef

struct tag NEWCPLINFO {

DWORD

dwSize;

DWORD

dwFlags;

DWORD

dwHelpContext;

LONG

lData;

HICON

hIcon;

TCHAR

szName[32];

TCHAR

szInfo[64];

TCHAR

szHelpFile[128];

} NEWCPLINFO;

dwSize - размер структуры определяется как sizeof(NEWCPLINFO).

Поля dwFlags, dwHelpContext и zsHelpFile не используются.

lData заданное пользователем значение которое впоследствии передается Приложению при вызовах.

hIcon ссылка на иконку диалогового окна. Эта иконка будет отображаться в окне Панели Управления.

szName и szInfo asciiz строки содержащие имена диалогового окна. szName отображается под иконкой. szInfo отображается когда иконка выбрана.

Следует отметить, что структура CPLINFO содержит идентификаторы ресурсов idIcon, idName, idInfo вместо ссылки на иконку и самих строк, как это реализовано в структуре

NEWCPLINFO.

Каждый раз при выборе иконки диалогового окна в Панели Управления Приложение получает сообщение CPL_DBLCLK. Параметр lParam1 содержит порядковый номер диалогового окна а параметр lParam2 значение, заданное параметром lData. Как правило, Приложение по этому сообщению отображает диалоговое окно.

Когда Панель Управления закрывается Приложения получают сообщения CPL_STOP по одному для каждого диалогового окна. lParam1 содержит порядковый номер окна и lParam2 значение lData.

После серии сообщений CPL_STOP непосредственно перед выгрузкой Оболочка посылает Приложению заключительное сообщение CPL_EXIT.

Для регистрации Приложения Панели Управления достаточно изменить расширение исполняемого файла Приложения на .cpl и записать его в каталог Windows\System. Панель Управления перед отображением своего окна сканирует этот каталог в поисках cpl файлов.

99

Пример на Си с использованием структуры CPLINFO:

HUNSTANCE hinst;

LONG CALLBACK CPlApplet(HWND hWnd, UINT uMsg, LPARAM lParam1, LPARAM lParam2)

{

int i = (int) lParam1; LPCPLINFO lpCPlInfo; switch (uMsg) {

case CPL_INIT:

hinst = GetModuleHandle(«MyCPL.cpl»); return TRUE;

case CPL_GETCOUNT:

return NUM_APPLETS; //количество диалоговых окон break;

case CPL_INQUIRE:

//инициализация массива DialоgArray не показана lpCPlInfo = (LPCPLINFO) lParam2;

lpCPlInfo->lData

= 0;

lpCPlInfo->idIcon

= DialogArray[i].IconID;

lpCPlInfo->idName = DialogArray[i].NameStringID;

lpCPlInfo->idInfo

= DialogArray[i].DescStringID;

break;

 

case CPL_DBLCLK:

DialogBox(hinst, MAKEINTRESOURCE( DialogArray[i].DlgTemplateID), hWnd, DialogArray[i].DlgFunction);

break; case CPL_STOP:

break; case CPL_EXIT:

break;

default:

break;

}

return 0;

}

Пример на Паскале с использованием структуры NEWCPLINFO и одним диалоговым окном:

Uses CPL;

Function CPlApplet(hwndCPl : THandle; uMsg : DWORD; lParam1 : LongInt;

lParam2 : LongInt) : LongInt; StdCall;

Begin

Case uMSg of

CPL_INIT:

Begin

MyCPLApplet := 1; {Ok} End;

CPL_GETCOUNT:

begin

MyCPLApplet := 1; {одно окно} end;

CPL_NEWINQUIRE: begin

with pNEWCPLInfo(lParam2)^ do begin

dwSize := SizeOf(TNewCPLInfo); dwFlags:= 0;

dwHelpContext:= 0; lData := 0;

100

hIcon := LoadIcon(hInstance, 'MAINICON'); szName := 'Пример'#00;

szInfo := 'Пример Приложения Панели Управления'#00; szHelpFile:= '';

end;

 

MyCPLApplet := 0;

 

end;

 

CPL_DBLCLK:

 

begin

{эта функция отображает диалоговое окно }

ViewDialogBox;

{или так:

MessageDlg(‘А вот и я’, mtInformation, [mbOk], 0);

}

MyCPLApplet := 0; end;

Else MyCPLApplet := 0; End;

End;

...

exports CPlApplet;

...

101