Compartir a través de


Implementar el objeto COM de la página de propiedades

Una extensión de hoja de propiedades es un objeto COM implementado como un servidor en proceso. La extensión de hoja de propiedades debe implementar las interfaces IShellExtInit e IShellPropSheetExt . Se crea una instancia de una extensión de hoja de propiedades cuando el usuario muestra la hoja de propiedades de un objeto de una clase para la que se ha registrado la extensión de hoja de propiedades en el especificador de presentación de la clase .

Implementación de IShellExtInit

Después de crear una instancia del objeto COM de extensión de hoja de propiedades, se llama al método IShellExtInit::Initialize . IShellExtInit::Initialize proporciona la extensión de hoja de propiedades con un objeto IDataObject que contiene datos que pertenecen al objeto de directorio que aplica la hoja de propiedades.

IDataObject contiene datos en el formato CFSTR_DSOBJECTNAMES. El formato de datos CFSTR_DSOBJECTNAMES es un HGLOBAL que contiene una estructura DSOBJECTNAMES . La estructura DSOBJECTNAMES contiene datos de objeto de directorio que se aplica la extensión de hoja de propiedades.

IDataObject también contiene datos en el formato CFSTR_DS_DISPLAY_SPEC_OPTIONS. El formato de datos CFSTR_DS_DISPLAY_SPEC_OPTIONS es un HGLOBAL que contiene una estructura DSDISPLAYSPECOPTIONS . DSDISPLAYSPECOPTIONS contiene los datos de configuración que usa la extensión.

Si se devuelve un valor distinto de S_OK desde IShellExtInit::Initialize, no se muestra la hoja de propiedades.

No se usan los parámetros pidlFolder y hkeyProgID del método IShellExtInit::Initialize .

El puntero IDataObject se puede guardar mediante la extensión incrementando el recuento de referencias del IDataObject. Esta interfaz debe liberarse cuando ya no sea necesario.

Implementación de IShellPropSheetExt

Después de que se devuelva IShellExtInit::Initialize , se llama al método IShellPropSheetExt::AddPages . La extensión de hoja de propiedades debe agregar la página o las páginas durante este método. Se crea una página de propiedades rellenando una estructura PROPSHEETPAGE y pasando esta estructura a la función CreatePropertySheetPage . A continuación, la página de propiedades se agrega a la hoja de propiedades llamando a la función de devolución de llamada que se pasa a IShellPropSheetExt::AddPages en el parámetro lpfnAddPage .

Si se devuelve un valor distinto de S_OK desde IShellPropSheetExt::AddPages, no se muestra la hoja de propiedades.

Si la extensión de hoja de propiedades no es necesaria para agregar páginas a la hoja de propiedades, no debe llamar a la función de devolución de llamada pasada a IShellPropSheetExt::AddPages en el parámetro lpfnAddPage .

No se usa el método IShellPropSheetExt::ReplacePage .

Pasar el objeto de extensión a la página de propiedades

El objeto de extensión de hoja de propiedades es independiente de la página de propiedades. En muchos casos, es conveniente poder usar el objeto de extensión, o algún otro objeto, desde la página de propiedades. Para ello, establezca el miembro lParam de la estructura PROPSHEETPAGE en el puntero de objeto. Después, la página de propiedades puede recuperar este valor cuando procesa el mensaje de WM_INITDIALOG . Para una página de propiedades, el parámetro lParam del mensaje WM_INITDIALOG es un puntero a la estructura PROPSHEETPAGE . Recupere el puntero de objeto convirtiendo el lParam del mensaje de WM_INITDIALOG en un puntero PROPSHEETPAGE y, a continuación, recuperando el miembro lParam de la estructura PROPSHEETPAGE .

En el ejemplo de código de C++ siguiente se muestra cómo pasar un objeto a una página de propiedades.

case WM_INITDIALOG:
    {
        LPPROPSHEETPAGE pPage = (LPPROPSHEETPAGE)lParam;

        if(NULL != pPage)
        {
            CPropSheetExt *pPropSheetExt;
            pPropSheetExt = (CPropSheetExt*)pPage->lParam;

            if(pPropSheetExt)
            {
                return pPropSheetExt>OnInitDialog(wParam, lParam);
            }
        }
    }
    break;

Tenga en cuenta que después de llamar a IShellPropSheetExt::AddPages , la hoja de propiedades liberará el objeto de extensión de hoja de propiedades y nunca lo usará de nuevo. Esto significa que el objeto de extensión se eliminaría antes de que se muestre la página de propiedades. Cuando la página intenta acceder al puntero de objeto, la memoria se liberará y el puntero no será válido. Para corregirlo, incremente el recuento de referencias del objeto de extensión cuando se agregue la página y, a continuación, libere el objeto cuando se destruya el cuadro de diálogo de página de propiedades. Esto crea otro problema porque el cuadro de diálogo de la página de propiedades no se crea hasta la primera vez que se muestra la página. Si el usuario nunca selecciona la página de extensión, la página nunca se crea y destruye. Esto da lugar a que el objeto de extensión nunca se libere, por lo que se produce una pérdida de memoria. Para evitar esto, implemente una función de devolución de llamada de página de propiedades. Para ello, agregue la marca PSP_USECALLBACK al miembro dwFlags de la estructura PROPSHEETPAGE y establezca el miembro pfnCallback de la estructura PROPSHEETPAGE en la dirección de la función PropSheetPageProc implementada. Cuando la función PropSheetPageProc recibe la notificación PSPCB_RELEASE , el parámetro ppsp del PropSheetPageProc contiene un puntero a la estructura PROPSHEETPAGE . El miembro lParam de la estructura PROPSHEETPAGE contiene el puntero de extensión que se puede usar para liberar el objeto.

En el ejemplo de código de C++ siguiente se muestra cómo liberar un objeto de extensión.

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;
}

Trabajar con el objeto Notification

Dado que las páginas de extensión de la hoja de propiedades se muestran dentro de una hoja de propiedades creada por un componente desconocido para la extensión, es necesario usar un "administrador" para controlar la transferencia de datos entre las páginas de extensión y la hoja de propiedades. Este "administrador" se denomina objeto de notificación. El objeto de notificación funciona como moderador entre las páginas individuales y la hoja de propiedades.

Cuando se inicializa el objeto de extensión de hoja de propiedades, la extensión debe crear un objeto de notificación llamando a ADsPropCreateNotifyObj, pasando el IDataObject obtenido de IShellExtInit::Initialize y el nombre del objeto de directorio. No es necesario incrementar el recuento de referencias de la interfaz IDataObject , ya que el objeto de notificación creado por la función ADsPropCreateNotifyObj lo hará. El identificador de objeto de notificación proporcionado por ADsPropCreateNotifyObj debe guardarse para su uso posterior. Se puede llamar a ADsPropCreateNotifyObj durante IShellExtInit::Initialize o IShellPropSheetExt::AddPages. Cuando se cierra la extensión de la hoja de propiedades, debe enviar un mensaje WM_ADSPROP_NOTIFY_EXIT al objeto de notificación. Esto hace que el objeto de notificación se destruya. Esto se hace mejor cuando la función PropSheetPageProc recibe la notificación PSPCB_RELEASE .

La extensión de hoja de propiedades puede obtener datos además de los proporcionados por el formato del Portapapeles de CFSTR_DSOBJECTNAMES llamando a ADsPropGetInitInfo. Una de las ventajas de usar ADsPropGetInitInfo es que proporciona un objeto IDirectoryObject que se usa para trabajar mediante programación con el objeto de directorio.

Nota

A diferencia de la mayoría de los métodos y funciones COM, ADsPropGetInitInfo no incrementa el recuento de referencias para el objeto IDirectoryObject . IDirectoryObject no debe liberarse a menos que el recuento de referencias se incremente manualmente en primer lugar.

 

Cuando se crea la página de propiedades por primera vez, la extensión debe registrar la página con el objeto de notificación llamando a ADsPropSetHwnd con el identificador de ventana de la página.

ADsPropCheckIfWritable es una función de utilidad que la extensión de hoja de propiedades puede usar para determinar si se puede escribir una propiedad.

Varios

El identificador de la página de propiedades se pasa al procedimiento del cuadro de diálogo de página. La hoja de propiedades es el elemento primario directo de la página de propiedades, por lo que el identificador de la hoja de propiedades se puede obtener llamando a la función GetParent con el identificador de página de propiedades.

Cuando cambia el contenido de la página de extensión, la extensión debe usar la macro PropSheet_Changed para notificar a la hoja de propiedades los cambios. A continuación, la hoja de propiedades habilitará el botón Aplicar.

hojas de propiedades de Multiple-Selection

Con Windows Server 2003 y sistemas operativos posteriores, los complementos MMC administrativos de Active Directory admiten extensiones de hoja de propiedades para varios objetos de directorio. Estas hojas de propiedades se muestran cuando las propiedades se ven durante más de un elemento cada vez. La diferencia principal entre una extensión de hoja de propiedades de selección única y una extensión de hoja de propiedades de selección múltiple es que la estructura DSOBJECTNAMES proporcionada por el formato del Portapapeles de CFSTR_DSOBJECTNAMES en IShellExtInit::Initialize contendrá más de una estructura DSOBJECT .

Cuando se crea el objeto de notificación, una extensión de hoja de propiedades de selección múltiple debe pasar un nombre único proporcionado por el complemento en lugar de un nombre creado por la extensión. Para obtener el nombre único, solicite el formato del Portapapeles CFSTR_DS_MULTISELECTPROPPAGE del IDataObject obtenido de IShellExtInit::Initialize. Estos datos son un HGLOBAL que contiene una cadena Unicode terminada en null que es el nombre único. A continuación, este nombre único se pasa a la función ADsPropCreateNotifyObj para crear el objeto de notificación. La función de ejemplo CreateADsNotificationObject en Código de ejemplo para la implementación del objeto COM de hoja de propiedades muestra cómo hacerlo correctamente, así como ser compatible con versiones anteriores del complemento que no admiten hojas de propiedades de selección múltiple.

En el caso de las hojas de propiedades de selección múltiple, el sistema solo se enlaza al primer objeto de la matriz DSOBJECT . Por este motivo, ADsPropGetInitInfo solo proporciona los atributos IDirectoryObject y con capacidad de escritura para el primer objeto de la matriz. Los demás objetos de la matriz no están enlazados.

Una extensión de hoja de propiedades de selección múltiple se registra en el atributo adminMultiselectPropertyPages .

Novedades con Windows Server 2003

Las siguientes características son nuevas con Windows Server 2003.

Si la página de propiedades encuentra un error, se puede llamar a ADsPropSendErrorMessage con los datos de error adecuados. ADsPropSendErrorMessage almacenará todos los mensajes de error en una cola. Estos mensajes se mostrarán la próxima vez que se llame a ADsPropShowErrorDialog . Cuando devuelve ADsPropShowErrorDialog , se eliminan los mensajes en cola.

Windows Server 2003 presenta la función ADsPropSetHwndWithTitle . Esta función es similar a ADsPropSetHwnd, pero incluye el título de página. Esto permite que el cuadro de diálogo de error que muestra ADsPropShowErrorDialog proporcione datos más útiles al usuario. Si la extensión de hoja de propiedades usa la función ADsPropShowErrorDialog , la extensión debe usar ADsPropSetHwndWithTitle en lugar de ADsPropSetHwnd.

Código de ejemplo para la implementación del objeto COM de la hoja de propiedades