Реализация COM-объекта страницы свойств
Расширение таблицы свойств — это COM-объект, реализованный как сервер в proc. Расширение листа свойств должно реализовывать интерфейсы IShellExtInit и IShellPropSheetExt. Расширение листа свойств создается, когда пользователь отображает лист свойств для объекта класса, для которого расширение листа свойств зарегистрировано в описателях отображения класса.
- Реализация IShellExtInit
- Реализация IShellPropSheetExt
- Передача объекта расширения на страницу свойств
- Работа с объектом уведомления
- Разное
- Таблицы свойств с несколькими выборами
- Новые возможности Windows Server 2003
- Связанные статьи
Реализация IShellExtInit
После создания экземпляра объекта COM расширения таблицы свойств вызывается метод IShellExtInit::Initialize . IShellExtInit::Initialize предоставляет расширение листа свойств с объектом IDataObject , содержащим данные, относящиеся к объекту каталога, который применяется листом свойств.
IDataObject содержит данные в формате CFSTR_DSOBJECTNAMES. Формат данных CFSTR_DSOBJECTNAMES — это HGLOBAL, содержащий структуру DSOBJECTNAMES. Структура DSOBJECTNAMES содержит данные объекта каталога, которые применяет расширение листа свойств.
IDataObject также содержит данные в формате CFSTR_DS_DISPLAY_SPEC_OPTIONS. Формат данных CFSTR_DS_DISPLAY_SPEC_OPTIONS — это HGLOBAL, содержащий структуру DSDISPLAYSPECOPTIONS. DSDISPLAYSPECOPTIONS содержит данные конфигурации для использования расширением.
Если любое значение, отличное от S_OK, возвращается из IShellExtInit::Initialize, лист свойств не отображается.
Параметры pidlFolder и hkeyProgID метода IShellExtInit::Initialize не используются.
Указатель IDataObject можно сохранить расширением, добавив число ссылок iDataObject. Этот интерфейс должен быть освобожден, если больше не требуется.
Реализация IShellPropSheetExt
После возвращения IShellExtInit::Initialize вызывается метод IShellPropSheetExt::AddPages. Расширение листа свойств должно добавить страницу или страницы во время этого метода. Страница свойств создается путем заполнения структуры PROPSHEETPAGE и передачи этой структуры функции CreatePropertySheetPage. Затем страница свойств добавляется в лист свойств путем вызова функции обратного вызова, переданной в IShellPropSheetExt::AddPages в параметре lpfnAddPage .
Если любое значение, отличное от S_OK , возвращается из IShellPropSheetExt::AddPages, лист свойств не отображается.
Если расширение листа свойств не требуется для добавления страниц в лист свойств, он не должен вызывать функцию обратного вызова, переданную в IShellPropSheetExt::AddPages в параметре lpfnAddPage .
Метод IShellPropSheetExt::ReplacePage не используется.
Передача объекта расширения на страницу свойств
Объект расширения листа свойств не зависит от страницы свойств. Во многих случаях желательно использовать объект расширения или другой объект на странице свойств. Для этого задайте элемент lParam структуры PROPSHEETPAGE указателем объекта. Затем страница свойств может получить это значение при обработке сообщения WM_INITDIALOG . Для страницы свойств параметр lParam сообщения WM_INITDIALOG является указателем на структуру PROPSHEETPAGE. Получите указатель объекта, приведя lParam сообщения WM_INITDIALOG к указателю PROPSHEETPAGE, а затем извлекая элемент lParam структуры PROPSHEETPAGE.
В следующем примере кода C++ показано, как передать объект на страницу свойств.
case WM_INITDIALOG:
{
LPPROPSHEETPAGE pPage = (LPPROPSHEETPAGE)lParam;
if(NULL != pPage)
{
CPropSheetExt *pPropSheetExt;
pPropSheetExt = (CPropSheetExt*)pPage->lParam;
if(pPropSheetExt)
{
return pPropSheetExt>OnInitDialog(wParam, lParam);
}
}
}
break;
Помните, что после вызова IShellPropSheetExt::AddPages лист свойств выпустит объект расширения листа свойств и никогда не будет использовать его снова. Это означает, что объект расширения будет удален перед отображением страницы свойств. Когда страница пытается получить доступ к указателю объекта, память будет освобождена, а указатель не будет допустимым. Чтобы исправить это, увеличьте число ссылок для объекта расширения при добавлении страницы, а затем отпустите объект при уничтожении диалогового окна страницы свойств. Это создает еще одну проблему, так как диалоговое окно страницы свойств не создается до первого отображения страницы. Если пользователь никогда не выбирает страницу расширения, страница никогда не создается и уничтожается. Это приводит к тому, что объект расширения никогда не освобождается, поэтому возникает утечка памяти. Чтобы избежать этого, реализуйте функцию обратного вызова страницы свойств. Для этого добавьте флаг PSP_USECALLBACK в элемент dwFlags структуры PROPSHEETPAGE и задайте для элемента pfnCallback структуры PROPSHEETPAGE адрес реализованной функции PropSheetPageProc. Когда функция PropSheetPageProc получает уведомление PSPCB_RELEASE, параметр ppsp объекта PropSheetPageProc содержит указатель на структуру PROPSHEETPAGE. Элемент lParam структуры PROPSHEETPAGE содержит указатель расширения, который можно использовать для освобождения объекта.
В следующем примере кода C++ показано, как освободить объект расширения.
UINT CALLBACK CPropSheetExt::PageCallbackProc( HWND hWnd,
UINT uMsg,
LPPROPSHEETPAGE ppsp)
{
switch(uMsg)
{
case PSPCB_CREATE:
// Must return TRUE to enable the page to be created.
return TRUE;
case PSPCB_RELEASE:
{
/*
Release the object. This is called even if the page dialog box was
never actually created.
*/
CPropSheetExt *pPropSheetExt = (CPropSheetExt*)ppsp->lParam;
if(pPropSheetExt)
{
pPropSheetExt->Release();
}
}
break;
}
return FALSE;
}
Работа с объектом уведомления
Так как страницы расширения листа свойств отображаются на листе свойств, созданном компонентом, неизвестным расширению, необходимо использовать диспетчер для обработки передачи данных между страницами расширений и листом свойств. Этот "диспетчер" называется объектом уведомления. Объект уведомления работает в качестве модератора между отдельными страницами и листом свойств.
При инициализации объекта расширения листа свойств расширение должно создать объект уведомления, вызвав ADsPropCreateNotifyObj, передав IDataObject, полученный из IShellExtInit::Initialize и имени объекта каталога. Не обязательно увеличивать число ссылок интерфейса IDataObject , так как объект уведомления, созданный функцией ADsPropCreateNotifyObj , будет выполнять это. Дескриптор объекта уведомления, предоставленный ADsPropCreateNotifyObj , должен быть сохранен для последующего использования. ADsPropCreateNotifyObj можно вызывать во время IShellExtInit::Initialize или IShellPropSheetExt::AddPages. После завершения работы расширения листа свойств он должен отправить WM_ADSPROP_NOTIFY_EXIT сообщение в объект уведомления. Это приводит к уничтожению объекта уведомления. Это лучше всего сделать, когда функция PropSheetPageProc получает уведомление PSPCB_RELEASE .
Расширение листа свойств может получить данные в дополнение к данным, предоставленным форматом буфера обмена CFSTR_DSOBJECTNAMES , вызвав ADsPropGetInitInfo. Одним из преимуществ использования ADsPropGetInitInfo является то, что он предоставляет объект IDirectoryObject, используемый для программной работы с объектом каталога.
Примечание.
В отличие от большинства методов и функций COM, ADsPropGetInitInfo не увеличивает число ссылок для объекта IDirectoryObject. IDirectoryObject не должен быть выпущен, если только число ссылок не увеличивается вручную.
При первом создании страницы свойств расширение должно зарегистрировать страницу с объектом уведомления, вызвав ADsPropSetHwnd с дескриптором окна страницы.
ADsPropCheckIfWritable — это служебная функция, которую можно использовать для определения возможности записи свойства.
Разное
Дескриптор страницы свойства передается в процедуру диалогового окна страницы. Лист свойств является прямым родительским элементом страницы свойства, поэтому дескриптор листа свойств можно получить, вызвав функцию GetParent с дескриптором страницы свойств.
При изменении содержимого страницы расширения расширение должно использовать макрос PropSheet_Changed для уведомления листа свойств об изменениях. Затем лист свойств включает кнопку "Применить".
Таблицы свойств с несколькими выборами
В операционных системах Windows Server 2003 и более поздних версий оснастки MMC active Directory поддерживают расширения листов свойств для нескольких объектов каталога. Эти листы свойств отображаются при просмотре свойств для нескольких элементов одновременно. Основное различие между расширением листа свойств с одним выделением и расширением листа свойств с несколькими выборами заключается в том, что структура DSOBJECTNAMES, предоставляемая форматом буфера обмена CFSTR_DSOBJECTNAMES в IShellExtInit::Initialize, будет содержать несколько структур DSOBJECT.
При создании объекта уведомления расширение листа свойств с несколькими выборами должно передавать уникальное имя, предоставленное оснасткой, а не имя, созданное расширением. Чтобы получить уникальное имя, запросить формат буфера обмена CFSTR_DS_MULTISELECTPROPPAGE из IDataObject, полученного из IShellExtInit::Initialize. Эти данные — это HGLOBAL , содержащий строку Юникода, завершающую значение NULL, которая является уникальным именем. Затем это уникальное имя передается функции ADsPropCreateNotifyObj для создания объекта уведомления. Пример функции CreateADsNotificationObject в примере кода для реализации COM-объекта таблицы свойств демонстрирует правильное выполнение этого действия, а также совместимость с более ранними версиями оснастки, которые не поддерживают листы свойств с несколькими выборами.
Для листов свойств с несколькими выборами система привязывается только к первому объекту в массиве DSOBJECT . Из-за этого ADsPropGetInitInfo предоставляет только атрибуты IDirectoryObject и записи для первого объекта в массиве. Другие объекты в массиве не привязаны к.
Расширение листа свойств с несколькими выборами зарегистрировано в атрибуте adminMultiselectPropertyPages .
Новые возможности Windows Server 2003
Ниже приведены новые возможности Windows Server 2003.
Если страница свойств обнаруживает ошибку, можно вызвать ADsPropSendErrorMessage с соответствующими данными об ошибках. ADsPropSendErrorMessage будет хранить все сообщения об ошибках в очереди. Эти сообщения будут отображаться при следующем вызове ADsPropShowErrorDialog. При возвращении ADsPropShowErrorDialog удаляются очереди сообщений.
Windows Server 2003 представляет функцию ADsPropSetHwndWithTitle . Эта функция похожа на ADsPropSetHwnd, но включает заголовок страницы. Это позволяет отображать диалоговое окно ошибки, отображаемое ADsPropShowErrorDialog , чтобы предоставить пользователю более полезные данные. Если расширение листа свойств использует функцию ADsPropShowErrorDialog, расширение должно использовать ADsPropSetHwndWithTitle, а не ADsPropSetHwnd.
См. также