2011-07-19 6 views
9

que tienen un componente que estoy construyendo en Delphi XE que quiero ser utilizados de la siguiente manera:Desmarque "Habilitar temas de tiempo de ejecución" o elimine el manifiesto interno en Delphi XE?

  1. usuario crea un nuevo proyecto en blanco.

  2. El usuario elimina mi componente en el formulario.

  3. Se ejecuta algún código especial de Designtime en mi componente, que cambiará las Opciones del proyecto para desmarcar la casilla "Habilitar temas de tiempo de ejecución" en las opciones del proyecto. No estoy seguro de que esto sea posible, así que estoy preguntando si es posible.

Si # 3 no es posible, entonces necesito otra solución a mi problema de "usabilidad" con este componente; El problema que tengo es que si los usuarios no deshabilitan el archivo de manifiesto vinculado estáticamente desmarcando Enable Runtime Themes, entonces ese manifiesto generado estáticamente que está vinculado al EXE parece anular los archivos de manifiesto externos que quiero tener fuera del EXE, en disco. También necesito modificar estos manifiestos en tiempo de ejecución, por lo tanto, la necesidad de manifiestos externos. Por supuesto, puedo habilitar la funcionalidad de Runtime Theme utilizando estos manifiestos, cuando es conveniente hacerlo. Una segunda pregunta es acerca de la prioridad de los manifiestos externos e internos; ¿Puede un manifiesto externo tener prioridad sobre el recurso manifiesto interno que está vinculado a las aplicaciones Delphi cuando se marca "Habilitar temas de tiempo de ejecución"?

soluciones aceptable distinto de # 3:

A. De alguna manera hacen que Delphi para no generar un manifiesto. B. De alguna manera, en tiempo de ejecución, Windows reconoce y prioriza archivos .manifest externos incluso cuando se encuentra uno interno.

C. Menos buena solución; En tiempo de ejecución, después de que falla CoCreateInstance en mi componente, puedo enumerar recursos, informar que un manifiesto externo está presente y nos está haciendo perder el control, y confiar en los desarrolladores que usan mi componente leyendo los mensajes de error de tiempo de ejecución que mi componente escupe, diciéndoles que deshabiliten runtime themes checkbox y reconstruir su aplicación. Extraer y leer un manifiesto ya está cubierto en otra pregunta de stackoverflow here, con código C++ que podría convertirse fácilmente en Delphi.

Actualización La respuesta aceptada hace exactamente lo que solicité, pero se considera un truco, y la respuesta de David sobre los contextos de activación es mucho más sensata y es el enfoque recomendado.

Update2 El manifiesto incorporado normalmente se reemplaza en las versiones posteriores de Delphi (XE5 y posterior) al especificar explícitamente qué manifiesto desea vincular, a través de la configuración del proyecto.

+2

# 3 es definitivamente posible, las opciones del proyecto se exponen a través de la interfaz 'IOTAProjectOptions'. –

+4

[Lectura interesante] (http://blogs.msdn.com/b/patricka/archive/2009/12/09/answers-to-several-application-manifest-mysteries-and-questions.aspx). Parece que en XP, el manifiesto externo tiene mayor prioridad que el embebido, mientras que en Vista + es al revés. –

Respuesta

11

Creo que he encontrado una solución de trabajo para lo que usted solicitó, es decir. para deshabilitar los temas de tiempo de ejecución de las opciones del proyecto cuando se crea una instancia de su componente (eliminada en un formulario, o un formulario/módulo que contiene una instancia de este se abre en el IDE). Esto no impide que el usuario vuelva a habilitar los temas de tiempo de ejecución de forma manual más tarde, pero tal vez todavía sea útil para usted.

Por cierto, IOTAProjectOptions no parece ayudar en este caso; parece que se necesita IOTAProjectResource.

TestComponentU.pas (parte del paquete de tiempo de ejecución):

unit TestComponentU; 

interface 

uses 
    Windows, Classes; 

type 
    ITestComponentDesign = interface 
    function DisableRuntimeThemes: Boolean; 
    end; 

    TTestComponent = class(TComponent) 
    public 
    constructor Create(AOwner: TComponent); override; 
    end; 

var 
    TestComponentDesign: ITestComponentDesign = nil; 

implementation 

uses 
    Dialogs; 

constructor TTestComponent.Create(AOwner: TComponent); 
begin 
    inherited Create(AOwner); 
    if (csDesigning in ComponentState) and Assigned(TestComponentDesign) and 
    TestComponentDesign.DisableRuntimeThemes then 
    ShowMessage('Project runtime themes disabled'); 
end; 

end. 

TestComponentRegU.pas (parte del paquete de diseño instalado en el IDE):

unit TestComponentRegU; 

interface 

procedure Register; 

implementation 

uses 
    Windows, Classes, SysUtils, TestComponentU, ToolsAPI; 

type 
    TTestComponentDesign = class(TInterfacedObject, ITestComponentDesign) 
    public 
    function DisableRuntimeThemes: Boolean; 
    end; 

procedure Register; 
begin 
    RegisterComponents('Test', [TTestComponent]); 
end; 

function GetProjectResource(const Project: IOTAProject): IOTAProjectResource; 
var 
    I: Integer; 
begin 
    Result := nil; 
    if not Assigned(Project) then 
    Exit; 

    for I := 0 to Project.ModuleFileCount - 1 do 
    if Supports(Project.ModuleFileEditors[I], IOTAProjectResource, Result) then 
     Break; 
end; 

function GetProjectResourceHandle(const ProjectResource: IOTAProjectResource; ResType, ResName: PChar): TOTAHandle; 
var 
    I: Integer; 
    ResEntry: IOTAResourceEntry; 
begin 
    Result := nil; 
    if not Assigned(ProjectResource) then 
    Exit; 

    for I := 0 to ProjectResource.GetEntryCount - 1 do 
    begin 
    ResEntry := ProjectResource.GetEntry(I); 
    if Assigned(ResEntry) and (ResEntry.GetResourceType = ResType) and (ResEntry.GetResourceName = ResName) then 
    begin 
     Result := ResEntry.GetEntryHandle; 
     Break; 
    end; 
    end; 
end; 

function DisableProjectRuntimeThemes(const Project: IOTAProject): Boolean; 
var 
    ProjectResource: IOTAProjectResource; 
    ResHandle: TOTAHandle; 
begin 
    Result := False; 
    ProjectResource := GetProjectResource(Project); 
    if not Assigned(ProjectResource) then 
    Exit; 

    ResHandle := GetProjectResourceHandle(ProjectResource, RT_MANIFEST, CREATEPROCESS_MANIFEST_RESOURCE_ID); 
    if Assigned(ResHandle) then 
    begin 
    ProjectResource.DeleteEntry(ResHandle); 
    Result := True; 
    end; 
end; 

function TTestComponentDesign.DisableRuntimeThemes: Boolean; 
var 
    Project: IOTAProject; 
begin 
    Project := GetActiveProject; 
    Result := Assigned(Project) and DisableProjectRuntimeThemes(Project); 
end; 

initialization 
    TestComponentDesign := TTestComponentDesign.Create; 

finalization 
    TestComponentDesign := nil; 

end. 
+0

Aceptado, porque esto hace lo que pido. Debo señalar que creo que David tiene razón, que estoy preguntando sobre hacer un hack (usando archivos de texto de manifiesto externos), cuando mi componente probablemente debería intentar usar Contextos de Activación, pero si Windows parece estar demasiado roto para funcionar con los contextos de activación de alguna manera, esta es la solución. Creo que esta pregunta y respuesta son valiosas, ya que son una muestra del uso de IOTAProjectResource, y este es simplemente un caso simple donde conseguirlo sería útil. –

6

Sospecho que mejor solución es dejar que los usuarios del componente hacen lo que quieran con manifiestos para sus aplicaciones. Hacer lo contrario colocaría una restricción seria en cualquier usuario de este componente.

En su lugar use la API activation context para activar los manifiestos que su componente necesita, como y cuando lo necesite.

Su idea actual de escribir archivos de manifiesto en el directorio ejecutable suena extremadamente frágil y puede fallar siempre que no se pueda escribir en ese directorio. Por otro lado, la API de contexto de activación hace exactamente lo que realmente necesita sin ninguno de los inconvenientes.

+0

Este es el mecanismo que utilizo para habilitar los temas de tiempo de ejecución en mi excel com add en –

+0

. ¿Sabe si Win7 UAC bloquearía el acceso a estas API de usuarios regulares o restringidos? –

+0

No hay problema con UAC. Así es como debe resolver su problema. –

Cuestiones relacionadas