Inicio > Aplicación, Código, Delphi, DLL, imágenes, Preview Handler > IV – Instalador para PreviewHandler de imágenes/texto (Inno Setup)

IV – Instalador para PreviewHandler de imágenes/texto (Inno Setup)

Share Button

Continuando con las entradas anteriores, en esta última vamos a crear una extensión para visualizar los tipos de imágenes más habituales y usados en Windows. Además vamos a «redistribuir»  un poco nuestro esqueleto inicial para reorganizar las clases (tal y como comentamos en entradas anteriores); Y finalmente vamos a crear un instalador para poder ofrecer esta extensión de una forma más profesional.

Os adjunto los links de todas las entradas de esta serie, como he hecho en las anteriores:

  1. Crear una Previsualización de ficheros en Windows
  2. «Registros» de una DLL de previsualización
  3. Generando previsualización funcional (PreviewHandler)
  4. Instalador para PreviewHandler de imágenes/texto (Inno Setup)

.

INTRODUCCION

Con todo los visto hasta ahora en las entradas anteriores, vamos a crear una DLL para imágenes de diferentes formatos, modificando un poco el esqueleto del proyecto que teníamos hasta ahora.

Vamos a tratar las extensiones más comunes con las que trabajamos:  bmp, jpg, jpeg, png, gif, ico, wmf, emf, tif, tiff

Además vamos a generar un instalador con Inno Setup que instale (y desinstale cuando sea necesario) nuestra DLL de previsualización. Inno Setup, para los que no lo conozcáis, es un generador de instalaciones para Windows muy potente y totalmente gratuito. En otras ocasiones ya he hablado de él, y a día de hoy es un estándar en generar programas de instalación.

Además de ser sencillo de utilizar, hay multitud de scripts predefinidos y de ejemplo por la web, que podéis utilizar, modificar y adaptar a vuestras necesidades. Para lo que necesitamos nosotros veréis que es sumamente sencillo y fácil.

.

MODIFICACIONES A NUESTRO ESQUELETO

Lo primero que vamos a hacer con nuestra DLL, es reestructurar nuestra clases para organizarlas de una manera más lógica (utilizando herencia).
Vamos a dejar tanto la clase TBaseShellExt como el formulario TFormPreviewBase, como clases abstractas a partir de las cuales vamos a derivar otras para generar clases funcionales.
De esta forma, la herencia para el Handler y para el formulario de visualización quedan como se ve en la imagen de la derecha.

La interfaz del handler ahora queda de esta forma (con la herencia vista anteriormente):

  TBaseShellExt = class abstract(TComObject, IPreviewHandler)
  private
	// Permite cargar datos desde el origen especificado en una llamada de método Initialize 
        // anterior y para comenzar la representación en la ventana del controlador de vista previa
	function DoPreview: HRESULT; stdcall;
	// Permite devolver el HWND desde una llamada a la función GetFocus.
	function QueryFocus(var phwnd: HWND): HRESULT; stdcall;
	// Permite establecer el foco en sí mismo.
	function SetFocus: HRESULT; stdcall;
	// Permite cambiar el área dentro del hwnd primario en el que se dibuja.
	function SetRect(var prc: TRect): HRESULT; stdcall;
	// Establece la ventana primaria de la ventana del previsualizador, así como el área 
        // dentro del elemento primario que se va a usar para la ventana del previsualizador.
	function SetWindow(hwnd: HWND; var prc: TRect): HRESULT; stdcall;
	// Permite controlar una pulsación de tecla pasada desde la bomba de mensajes del proceso 
        // en el que se ejecuta el controlador de vista previa
	function TranslateAccelerator(var pmsg: tagMSG): HRESULT; stdcall;
	// Permite dejar de representar una vista previa y liberar todos los recursos asignados 
        // en función del elemento pasado durante la inicialización
	function Unload: HRESULT; stdcall;
  private
	FParent: HWND;     // Handle de la ventana de previsualizacion
	FBounds: TRect;    // Define el area de la previsualizacion
  protected
	FormPreview: TFormPreviewBase;     // formuario de previsualizacion
	// Procedimiento que realmente realiza la previsualizacion
	procedure InternalDoPreview; virtual;
	procedure AfterDoPreview; virtual;
	// testear la ventana de previsualizacion
	procedure TestPreviewWindows;
	// Devuelve la clase contructora del formulario de visualización (a redefinir en los derivados)
	class function FormPreviewClass:TFormPreviewClass; virtual; abstract;
  public
	destructor Destroy; override;
  end;
 
  TFileShellExt = class(TBaseShellExt, IInitializeWithFile)    // clase con inicializacion por fichero
  strict private
	function IInitializeWithFile.Initialize = IInitializeWithFile_Init;
  private
	FFilePath: string;
	// Inicialización para ficheros
	function IInitializeWithFile_Init(pszFilePath: LPCWSTR; grfMode: DWORD): HRESULT; stdcall;
  protected
	// Procedimiento que realmente realiza la previsualizacion
	procedure InternalDoPreview; override;	
  public
	property FilePath:string read FFilePath write FFilePath;
  end;
 
  TStreamShellExt = class(TBaseShellExt, IInitializeWithStream)  // clase con inicilizacion por stream
  strict private
	function IInitializeWithStream.Initialize = IInitializeWithStream_Init;
  private
	FStream:IStream;
	// Inicilización para stream
	function IInitializeWithStream_Init(const pstream: IStream; grfMode: DWORD): HRESULT; stdcall;
  protected
	// Procedimiento que realmente realiza la previsualizacion
	procedure InternalDoPreview; override;
  end;
 
  TImageShellExt = class(TFileShellExt)
  protected
	// Procedimiento que realmente realiza la previsualizacion para imagenes
	procedure InternalDoPreview; override;
	class function FormPreviewClass:TFormPreviewClass; override;
  end;

 

Al final de la entrada os pongo todo el proyecto para descargar.

.

VISUALIZACION DE IMAGENES

Si nos centramos ahora en el formulario de visualización, vamos a utilizar en este caso la inicialización por fichero (a partir del path), ya que si necesitamos conocer el tipo del fichero, será más sencillo hacerlo a partir de su extensión (y dado que diferentes tipos de imagen pueden requerir diferente código para cargarse).

En Delphi es bastante sencillo el código, en realidad basta con unas pocas líneas:

procedure TFormPreviewImage.DoPreviewEXT(const AFileName: TFileName);
begin
  inherited;
  Extension := AnsiReplaceText(AnsiString(ExtractFileExt(AFileName)), '.', string.Empty);
  // cargar la imagen de disco
  img.Picture.LoadFromFile(AFileName);
end;
// Refrescar la información de la imagen en pantalla
procedure TFormPreviewImage.RefreshInfo;
begin
  inherited;
  pnlTamaño.Caption := img.Picture.Width.ToString + 'x' + img.Picture.Height.ToString;
  pnlTamaño.Invalidate;
end;

Además extraemos la extensión y las dimensiones de la imagen para mostrarlas en la pantalla.

Una posible ampliación puede ser la de cargar imágenes que por defecto no carga la VCL, como pueden ser SVG, WBMP, Webp,… A ver si alguien se anima y ampliamos la DLL.

.

INSTALADOR CON «INNO SETUP»

Por último vamos a crear una instalación para nuestra librería. Para ello vamos a utilizar Inno Setup.
Para los que no lo hayáis utilizado, Inno es un generador de instalaciones gratuito y muy potente, que nos ofrece todo los necesario para generar un instalador.

Se basa en un Script de texto, y aunque hay utilidades de terceros muy interesantes como «Inno Script Studio» , también gratuito, que nos permite de forma visual configurar la infinidad de opciones del instalador, veréis que para algo básico como lo que necesitamos nosotros no son necesarias.

Un script básico que ya funciona para generar el instalador de nuestra DLL es el siguiente:

; Script generated by the Inno Script Studio Wizard.
; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!

; SECCION-1 ---------------------------------------------------------------
#define MyAppName "Controlador de vista previa para ficheros de Imagen"
#define MyAppVersion "1.5"
#define MyAppPublisher "Germán Estévez -Neftalí-"
#define MyAppURL "https://neftali.clubdelphi.com"

; SECCION-2 ---------------------------------------------------------------
[Setup]
; NOTE: The value of AppId uniquely identifies this application.
; Do not use the same AppId value in installers for other applications.
; (To generate a new GUID, click Tools | Generate GUID inside the IDE.)
AppId={{87E9F1B0-A979-4DB1-B63B-AB50AA5FE290}
AppName={#MyAppName}
AppVersion={#MyAppVersion}
;AppVerName={#MyAppName} {#MyAppVersion}
AppPublisher={#MyAppPublisher}
AppPublisherURL={#MyAppURL}
AppSupportURL={#MyAppURL}
AppUpdatesURL={#MyAppURL}
DefaultDirName={pf}\ShellPreviewExtFiles
DisableDirPage=yes
DefaultGroupName=ShellPreviewExtFiles
DisableProgramGroupPage=yes
LicenseFile=..\Install\License.txt
OutputBaseFilename=Instalar
Compression=lzma
SolidCompression=yes

; SECCICON-3 ---------------------------------------------------------------
[Languages]
Name: "spanish"; MessagesFile: "compiler:Languages\Spanish.isl"
Name: "catalan"; MessagesFile: "compiler:Languages\Catalan.isl"
Name: "english"; MessagesFile: "compiler:Default.isl"

; SECCION-4 ---------------------------------------------------------------
[Files]
Source: "..\ShellPreviewImagesFiles.dll"; DestDir: "{app}"; Flags: ignoreversion 32bit regserver; Languages: catalan english spanish
; Fichero de licencia
Source: ".\License.txt"; DestDir: "{app}"; Flags: ignoreversion;
Source: ".\Readme.txt"; DestDir: "{app}"; Flags: ignoreversion;

Os he marcado con comentarios (;————-…) las diferentes secciones del script, para poder identificarlas, aunque los nombres son bastante descriptivos.

  • SECCION-1: Constantes básicas para el instalador, que se usan más adelante en el script.
  • SECCION-2: Variables necesarias para el asistente de instalación (nombre, descripción, versión, directorio de instalación,…)
  • SECCION-3: Lenguajes en los que deseamos mostrar el instalador; El primero será el de la pantalla inicial que permitirá al usuario cambiarlo.
  • SECCION-4: Lista de ficheros a instalar con sus diferentes opciones. Importante en nuestro caso indicar el flag regserver, para nuestra DLL. Eso hará que el instalador de forma automática la registre (regsvr32) y la desregistre cuando hagamos la desinstalación.

Tal vez lo veáis muy complejo, pero no os preocupéis no debéis escribir este script «a mano». Este script ya lo genera «Inno Script Studio» que mediante un asistente nos va solicitando los datos básicos. Lo podéis ver en las imágenes siguientes.
NOTA: Tengo el asistente en inglés (en las imágenes), pero podéis ponerlo en varios idiomas.

Os adjunto al final de la entrada los diferentes ZIPs para que podáis probar.

  • Código fuente del proyecto (incluye fuentes, script inno, imágenes de ejemplo,…)
  • Fichero [instalar.exe] ya compilado, listo para instalar.

Si lo instaláis (ya sea compilando la DLL y generando el proyecto de Inno, o utilizando el instalador) veréis que se genera una carpeta con todo lo necesario en:

c:\Program Files (x86)\ShellPreviewExtFiles\

Os adjunto ficheros para descarga:

Aquí tenéis el enlace a Github donde he subido todos los ficheros de las diferentes entradas, organizados por las diferentes versiones por si en algún momento no están accesibles aquí

Os dejo también un video corto donde podáis ver cómo funciona esta última versión programada y ver en funcionamiento el instalador de Inno Setup.

 

Y hasta aquí lo que tengo previsto de esta serie, aunque no descarto ampliarla con algunas cosas más que me rondan por la cabeza.

.

LINKS DE INTERÉS…

Algunos links ya los he puesto en las entradas anteriores, pero no las referencias a otras webs o blogs donde podéis encontrar información al respecto a modo de bibliografía. Sí he puesto enlaces a la documentación de la MSDN, pero me he dejado algunos. A provecho esta sección para recopilarlos:

  • En el blog de Rodrigo Ruz podéis encontrar código al respecto de los «Preview handlers» y una fantástica extensión para visualizar ficheros de código fuente. Diferentes lenguajes de programación. En GitHub tenéis código fuente si queréis revisar y aprender.
  • En el blog de «The Art of delphi programming» de Uwe Raabe, podéis encontrar una entrada sobre Previews para Windows 7, con código fuente disponible muy interesante.
  • En este blog de Brad Smith también podéis encontrar sobre el tema.
  • El resto de información está en la MSDN y podéis encontrarla a partir de este link.

 

Como siempre espero vuestros comentarios, preguntas, sugerencias, críticas,…

 

5/5 - (1 voto)
Subscribe
Notify of
guest

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.

0 Comments
Inline Feedbacks
Ver todos los comentarios
0
Would love your thoughts, please comment.x
()
x