Multivisor: Cómo ver 500 formatos de archivos usando 90 líneas de código

En mi ya larga experiencia usando xailer, siempre he tenido dos espinitas clavadas que se me habían resistido especialmente:

La integración de controles ActiveX en mis programas y la posibilidad de visualizar limpiamente archivos pdf dentro de un formulario sin tener que recurrir a trucos con el explorer que se empeña en que me aparezcan las barras de herramientas de acrobat cada vez que intento visualizar un documento.

Pues bien, hoy vamos a matar dos pájaros de un tiro y ver cómo hacer ambas cosas.

Hace un tiempo, gracias a un plugin para total commander descubrí la tecnología Outside in de Oracle que nos permite acceder, transformar y controlar el contenido de cerca de 500 formatos de ficheros.

Imaginaros mi sorpresa al ver que además disponía de un control activex para acceder a esa maravilla. Total, que no me pude resistir, y aquí está el resultado.

En el área de descargas de xailer, en la sección de ejemplos, tenéis el instalable del ejemplo que vamos a ver, así como todos los fuentes necesarios para poder crear vosotros mismos el ejecutable.

Os recomiendo que os lo instaléis antes de seguir leyendo, ya que así os registrará el fichero ocx en vuestro sistema y os permitirá seguir los ejemplos paso a paso.

Lo primero que vamos a hacer será crear un sencillo formulario en el que vamos a situar a la izquierda del todo un Listbox para mostrar los ficheros que queremos visualizar y un Bevel a la derecha, que será donde se mostrará el contenido del fichero seleccionado.
Justo encima del bevel pondremos dos controles más: un BtnBmp para poder imprimir lo que estamos viendo, y un Combobox que nos permitirá seleccionar la forma de visualizar nuestro documento

Algo así:

Una vez tengamos el formulario creado, nos vamos al menú componentes de xailer y seleccionamos importar activex

Veremos como nos aparece una ventana que se va llenando con todos los controles activex que están disponibles en nuestro sistema.

De todos ellos tenemos que seleccionar el que dice oixctrl class, que es el correspondiente al control activex de Oracle Outside In technology.

Como os decía, lo seleccionamos y pulsamos el botón crear clase.

Veremos como xailer se pone a trabajar y nos crea el solito el fichero prg necesario para poder interactuar con el control indicado.

Cuando termine, veremos en nuestro gestor de proyectos un nuevo prg llamado oixctrl.prg que contiene todas las propiedades, métodos y eventos necesarios para poder trabajar con el nuevo control.

Ya sólo nos queda poner un poco de nuestra parte y decirle al programa qué hacer con las nuevas características recien estrenadas.

Para empezar, vamos a crear dos datas nuevas a nuestro formulario
Data oView
Data cDir INIT '.samples'
oView: el objeto que contendrá el control ocx
cDir: el directorio donde están los ficheros de ejemplo que vamos a mostrar.

Es importante tener muy claro que de momento sólo le hemos dicho al programa que tenemos la intención de usar un nuevo elemento que se llamará oView, pero aún no le hemos dicho que va a contener.
Para ello usaremos el evento OnInitializate del formulario.
METHOD FormInitialize( oSender ) CLASS TForm1
  Local aImges,n
  WITH OBJECT ::oView := Toixctrl():New( ::oBevel1 )
          :nAlign := alCLIENT
          :Create()
          :ViewFile( .f., ::cDir+"oivwx.pdf" )
  END
  aImges := Directory( ::cDir )
  FOR n := 1 TO Len( aimges )
         ::oListbox1:addItem( aImges[n,1] )
   NEXT
RETURN Nil
Aunque no os lo creáis, las palabras mágicas que van a hacer que podamos mostrar hasta ficheros de autocad dentro de nuestros formularios ya se las hemos dicho y son :.
  WITH OBJECT ::oView := Toixctrl():New( ::oBevel1 )
Si nos fijamos en el fichero oixctrl.prg que nos ha creado Xailer vemos que aparece una línea que dice
CLASS Toixctrl FROM TOcx
En ella, Xailer crea una nueva clase llamada Toixctrl «con capacidades ocx», así que lo primero que hemos hecho ha sido decirle al programa que nuestro data oView va a ser
un objecto del tipo Toixctrl y que queremos que «cuelgue» no del formulario principal si no del bevel que hemos creado al empezar (::oBevel1)

Una vez creado, para que sea más bonito, vamos a indicarlo a Xailer que además de colgar de oBevel1, queremos que ocupe todo el espacio posible dentro del bevel (:nAlign := alCLIENT)

Ahora que ya tenemos definidad las características del control, tan sólo nos queda decirle que lo cree llamando al método :create()

Y listo!, a empezar a utilizarlo!!

En oixctrl.prg tenemos todos los métodos, propiedades y eventos que ha «heredado» nuestro nuevo control del ocx original. Eso sí, para saber qué hace cada una de ellas no nos quedará más remedio que recurrir a la documentaciónd del ocx en cuestión.

Vamos a ver las más elementales del ocx que estamos usando.

Para visualizar un fichero utilizaremos el método ViewFile( lFileOpenDlg, cFile)
– lFileOpenDlg es una variable lógica que si la establecemos a .t. nos mostrará una caja de diálogo estándar de apertura de fichero y nos mostrará el fichero seleccionado
– cFile es una variable de tipo texto con el nombre del fichero a visualizar.

En nuestro ejemplo vamos a establecer
:ViewFile( .f., ::cDir+"oivwx.pdf" )
para que nada más crear el control nos muestre en la ventana el manual de instrucciones del mismo.

Bien, pero… ¿dónde se va mostrar?. Pues dentro de oBevel1!, ocupando todo el espacio posible.

Todo lo demás es púramente decorativo,
Leemos todos los ficheros del directorio samples y se los asignamos al listbox
aImges := Directory( ::cDir )
FOR n := 1 TO Len( aimges )
  ::oListbox1:addItem( aImges[n,1] )
NEXT
Cada vez que cambiamos de línea en el listbox hacemos una nueva llamada a ViewFile con el valor del nuevo fichero a visualizar
METHOD Listbox1Change( oSender, nIndex ) CLASS TForm1
  ::oCombobox1:nIndex=1
  ::Combobox1Change( ::oCombobox1, 1 )
  ::oView:ViewFile( .f., ::cDir+oSender:aItems[nIndex] )
RETURN Nil
En el combobox definiremos cómo se va a visualizar el fichero: a tamaño natural, ajustado en ventana, etc..
Para ello utilizamos las propiedades BMPFitMode, VECFitMode y WPFitMode que nos definen el tipo de visualización para ficheros de imagen, vectoriales y texto
METHOD Combobox1Change( oSender, nIndex, nOldIndex ) CLASS TForm1
 IF nIndex > 4
     ::oView:BMPFitMode := nIndex
     IF nIndex > 3
         ::oView:WPFitMode := nIndex
     ENDIF
 ENDIF
 ::oView:VECFitMode := nIndex
RETURN Nil
y por último, en el botón utilizamos el método PrintOI(0,128,0,0)
METHOD BtnBmp1Click( oSender ) CLASS TForm1
  ::oView:PrintOI(0,128,0,0)
RETURN Nil

De este método sólo nos interesa el primer parámetro, que si es 1 nos muestra la caja de configuración de impresora antes de imprimir.
El resto de los parámetros, mejor dejarlos como están.

Listo, ya sólo tenemos que darle al play y disfrutar de nuestro ejemplo funcionando.

Para terminar, recordaros que para que nuestro ejemplo funcione en otros ordenadores, no basta con copiar el fichero ejecutable, sino que es necesario copiar y registrar el ocx y todos los ficheros accesorios.

Dentro del fichero zip con los fuentes del ejemplo os dejo el script de instalación de Inno setup, pero esa es otra historia y os la contaré otro día.

8 comentarios en “Multivisor: Cómo ver 500 formatos de archivos usando 90 líneas de código

  1. xevi

    Fredy,

    Estupendo tu aporte, y además la explicación està magníficamente detallada.

    ¿de donde se descarga este ocx?
    Quedaria saber si su uso es libre…

    Gracias

    Un Saludo,
    Xevi

    Responder
  2. José Lalín

    Fredy,

    no estoy seguro. Acabo de mirar la MSDN y quizás esto pueda servir:

    IsOcxRegistered( «oicxctrl.oixctrl.1» )

    HB_FUNC( ISOCXREGISTERED )
    {
    CLSID clsid;
    HRESULT hr = CLSIDFromProgID( (LPCOLESTR) hb_parc( 1 ), &clsid);
    hb_retl( SUCCEEDED( hr ) );
    }

    La he escrito mirando la documentación y seguramente necesite convertir hb_parc( 1 ) con AnsiToWide().

    Responder
  3. Fredy

    José,

    Como siempre, magistral!

    Podemos mejorar el código poniendo, al principo del FormInitialize:

    IF !( IsOcxRegistered(«oixctrl.oixctrl.1») )
    MsgStop(«Imposible continuar»+ CRLF + ;
    «Por favor,reinstale el programa»,»Atención»)
    QUIT
    ENDIF

    y al final del código:

    //——————————
    #pragma BEGINDUMP
    #include «windows.h»
    #include «xailer.h»

    HB_FUNC( ISOCXREGISTERED )
    {
    CLSID clsid;
    HRESULT hr = CLSIDFromProgID( (LPCOLESTR) AnsiToWide(hb_parc( 1 )), &clsid);
    hb_retl( SUCCEEDED( hr ) );
    }
    #pragma ENDDUMP
    //——————————

    Este control es un poco más complicado para registrarlo automáticamente, porque hay que insertar unas entradas en el registro de windows y copiar un montón de filtros y dll además del ocx, pero si alguien se anima a hacerlo, puedo publicarlo en el blog cuando quiera 🙂

    Responder
  4. José Lalín

    Fredy,

    tienes una pérdida de recursos que hay que corregir: es necesario liberar el puntero devuelto por AnsiToWide() y, de paso, comprobar que se pasa el parámetro para evitar GPFs.

    HB_FUNC( ISOCXREGISTERED )
    {
       if( ISCHAR( 1 ) )
       {
          CLSID clsid;
          LPWSTR lpName = AnsiToWide(hb_parc( 1 ));
          HRESULT hr = CLSIDFromProgID( (LPCOLESTR) lpName, &clsid);
          hb_xfree( lpName );
          hb_retl( SUCCEEDED( hr ) );
       }
       else
          hb_retl( FALSE );
    }
    
    								
    Responder

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *