Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   OOP (https://www.clubdelphi.com/foros/forumdisplay.php?f=5)
-   -   ¿Saben de algún componente que realice ésta función? (https://www.clubdelphi.com/foros/showthread.php?t=77919)

TiammatMX 06-03-2012 18:39:12

¿Saben de algún componente que realice ésta función?
 
Buena tarde, jóvenes delphineros...

Aquí, yo y mis peticiones a cual más rara y complicada. ¿Conocen algún componente que en un panel me permita mostrar una previsualización de un archivo Adobe Acrobat? Y de ser posible, que también lo mandase a la impresora, estaría fabuloso.

O de algún código que me permita mostrar una especie de visualización previa del archivo PDF.

defcon1_es 06-03-2012 19:05:11

Hola, ¿has probado con el ActiveX de Adobe?

Regístralo en Delphi y te creará un componente en la paleta de "ActiveX".

manuc 06-03-2012 19:07:23

Hola,

Con previsualización ¿a qué te refieres axactamente? ¿un thumbnail?

Un saludo.

newtron 06-03-2012 19:49:46

¿No te sirve abrirlo con el visor predeterminado que tenga windows?

TiammatMX 06-03-2012 20:15:40

Cita:

Empezado por newtron (Mensaje 426984)
¿No te sirve abrirlo con el visor predeterminado que tenga windows?

De hecho, éste será el siguiente paso, es decir, al hacer una visualización previa del documento en un panelito, darle doble click, llamar a Adobe Acrobat e imprimirlo y demás.

Sí, manuc, a éso me refiero exactamente. Una visualización previa en un thumbnail dentro de un panel de una pantalla.

defcon1_es, la idea es tener un panelito que me muestre el documento, sin necesidad de registrar el ActiveX, que ya tengo en su lugar y funcionando.

radenf 07-03-2012 00:34:11

Estimado tiammat:

Yo utilizo el PdfViewer de Synactics.
Synactics ya no lo desarrolla pero puedes encontrarlo buscando en google.
Hace exactamente lo que tú quieres, pero requiere tener instalado Adobe reader en el pc que lo utilices.

Salu2 y ojalá te sirva

manuc 07-03-2012 10:19:34

Ok, pues te dejo esta función que hace justo lo que quieres.

Con esta función puedes generar el thumbnail, a apartir de la ruta hasta el fichero. Hay varias formas de hacer esto, pero esta es la que mejor me ha funcionado.

Código Delphi [-]
function GetThumbnail(lpPathName, lpFileName: PWideChar; Width, Height: Integer): TBitmap;
var
 Desktop, Folder: IShellFolder;
 ItemIDList: PItemIDList;
 Flags, Priority: Cardinal;
 ExtractImage: IExtractImage;
 Res: HRESULT;
 hBitmap: Windows.HBITMAP;
 Buffer: array[0..MAX_PATH-1] of WideChar;
 Size: TSize;
begin
  Result := nil;
  SHGetDesktopFolder(Desktop);
  if LongBool(Desktop.ParseDisplayName(0, nil, lpPathName, PDWORD(0)^, ItemIDList, PDWORD(0)^)) then Exit;
  Desktop.BindToObject(ItemIDList, nil, IShellFolder, Folder);
  CoTaskMemFree(ItemIDList);
  if LongBool(Folder.ParseDisplayName(0, nil, lpFileName, PDWORD(0)^, ItemIDList, PDWORD(0)^)) then Exit;
  Folder.GetUIObjectOf(0, 1, ItemIDList, IExtractImage, nil, ExtractImage);
  CoTaskMemFree(ItemIDList);
  if not Assigned(ExtractImage) then Exit; // TODO
  Size.cx := Width; Size.cy := Height; Priority := 0;
  Flags := $28{IEIFLAG_SCREEN+IEIFLAG_OFFLINE};
  Res := ExtractImage.GetLocation(Buffer, SizeOf(Buffer), Priority, Size, 24{pf32bit}, Flags);
  if (Res = NOERROR) or (Res = E_PENDING{IEIFLAG_ASYNC}) then
  begin
    if not LongBool(ExtractImage.Extract(hBitmap)) then
    begin
     Result := TBitmap.Create;
     Result.Handle := hBitmap;
    end;
  end;
end;

¿cómo utilizarla? Por ejemplo:
Código Delphi [-]
Var
  bmp:TBitmap;
  vFichero:WideString;
  vRuta:WideString;
begin
  vRuta    := ExtractFilePath(path_fichero_pdf);
  vFichero := ExtractFilename(path_fichero_pdf);

  bmp := GetThumbnail(PWideChar(vRuta), PWideChar(vFichero), 122, 200);
  Image1.Picture.Assign(bmp);
  freeandnil(bmp)

Espero que te ayude.
Cualquier cosa, consulta sin problemas.

Un saludo.

TiammatMX 12-03-2012 16:22:32

Cita:

Empezado por manuc (Mensaje 427024)
...Espero que te ayude.
Cualquier cosa, consulta sin problemas...

Gracias manuc, está excelente tu función, y de hecho sí tengo una consulta.

Pretendo que el PDF que voy a mostrar resida en un campo binary de MS SQL server y se muestre en un TPanel justo con una funcionalidad parecida a la que amablemente me proporcionaste. ¿Qué adecuaciones debería hacerle? O tal vez, grabar momentáneamente el archivo en disco para ser mostrado.

Muy agradecido por tu excelente respuesta.

manuc 12-03-2012 16:50:09

Hola tiammat,

Me alegro que te ayude.

Si te refieres a modificar la función para que genere el thumbnail directamente del campo en base de datos ... creo que no sería posible o yo no sabría hacerlo.

Si existe un proceso en tu Software para enviar el fichero a base de datos, yo aprovecharía este proceso para generar el thumbnail y guardarlo en un campo en base de datos.

Depende un poco del tamaño de los ficheros PDF. Si cada vez que quieres generar el thumbnail "extraes" el fichero de base de datos, puede ser que generes un tráfico no necesario, dado que es probable que muchos casos el usuario no llegue a utilizar el PDF.

Pero esto ya depende del criterio de cada uno.

Un saludo!

TiammatMX 15-03-2012 19:48:35

Cita:

Empezado por manuc (Mensaje 427425)
Hola tiammat,

Me alegro que te ayude...

Una pregunta, manuc, ¿me hace falta algo, alguna unit o función para utilizar el código éste? Por que me marca errores:

Cita:

[Error][Error] ufrmContenedor.pas(808): Undeclared identifier: 'IExtractImage'
[Error] ufrmContenedor.pas(820): Undeclared identifier: 'CoTaskMemFree'
[Error] ufrmContenedor.pas(828): Incompatible types
[Error] ufrmContenedor.pas(833): Missing operator or semicolon
[Error] ufrmContenedor.pas(837): ')' expected but identifier 'Extract' found
[Error] ufrmContenedor.pas(857): Incompatible types: 'WideString' and 'PWideChar'
[Error] ufrmContenedor.pas(857): Incompatible types: 'WideString' and 'PWideChar'
[Fatal Error] TSDocumentos.dpr(6): Could not compile used unit 'ufrmContenedor.pas'
y como lo tengo implementado es así...

Código Delphi [-]
procedure TfrmContenedor.VisualizaMiniatura(sIDDocumento,sConsPac: string);

  procedure BajaPDF(sNombreArchivo : string);
  var
    qryTemporal : TADOQuery;
    msFlujo : TMemoryStream;
  begin
    qryTemporal := TADOQuery.Create(Self);
    with qryTemporal do
    begin
      Connection := qryDocumentos.Connection;
      SQL.Clear;
      SQL.Add('Select HY11_DocumentoElectronico from HY11_DocumentosPacElec where (E2_CTRL_PAC = '+lblExpediente.Caption+') AND ('+chklstDocumentos.Items.Strings[chklstDocumentos.ItemIndex])+');');
      Open;
      if RecordCount > 0 then
      begin
        msFlujo := TMemoryStream.Create;
        try
          TBlobField(qryTemporal.FieldByName('HY11_DocumentoElectronico')).SaveToStream(msFlujo);
          msFlujo.Position := 0;
          msFlujo.SaveToFile(sNombreArchivo);
        finally
          msFlujo.Free;
          msFlujo.Destroy;
        end;
      end;
      Close;
      Destroy;
    end;
  end;

  function CreaThumbnail(sRuta, sArchivo : PWideChar; Width, Height: Integer) : TBitmap;
  var
    Desktop, Folder: IShellFolder;
    ItemIDList: PItemIDList;
    Flags, Priority: Cardinal;
    ExtractImage: IExtractImage;
    Res: HRESULT;
    hBitmap: Windows.HBITMAP;
    Buffer: array[0..MAX_PATH-1] of WideChar;
    Size: TSize;
  begin
    Result := nil;
    SHGetDesktopFolder(Desktop);
    if LongBool(Desktop.ParseDisplayName(0, nil, sRuta, PDWORD(0)^, ItemIDList, PDWORD(0)^)) then
      Exit;

    Desktop.BindToObject(ItemIDList, nil, IShellFolder, Folder);
    CoTaskMemFree(ItemIDList);

    if LongBool(Folder.ParseDisplayName(0, nil, sArchivo, PDWORD(0)^, ItemIDList, PDWORD(0)^)) then
      Exit;

    Folder.GetUIObjectOf(0, 1, ItemIDList, IExtractImage, nil, ExtractImage);
    CoTaskMemFree(ItemIDList);

    if not Assigned(ExtractImage) then
      Exit;

    Size.cx := Width; Size.cy := Height; Priority := 0;
    Flags := $28{IEIFLAG_SCREEN+IEIFLAG_OFFLINE};
    Res := ExtractImage.GetLocation(Buffer, SizeOf(Buffer), Priority, Size, 24{pf32bit}, Flags);
    
    if (Res = NOERROR) or (Res = E_PENDING{IEIFLAG_ASYNC}) then
    begin
      if not LongBool(ExtractImage.Extract(hBitmap)) then
      begin
       Result := TBitmap.Create;
       Result.Handle := hBitmap;
      end;
    end;

  end;

var
  sFolder, sNombreArchivo : widestring;
  bmImagen : TBitmap;
begin
  sFolder := ObtenerFolder+'\';
  sNombreArchivo := 'TMP'+Trim(lblExpediente.Caption)+Trim(Texto2ID(chklstDocumentos.Items.Strings[chklstDocumentos.ItemIndex]))+'.pdf';
  ShowMessage(Format('La carpeta Mis Documentos para el usuario actual es: "%s"'+CRLF+'y el nombre de archivo temporal será: "%s"',[sFolder,sNombreArchivo]));

  if NOT FileExists(sFolder+sNombreArchivo) then
    BajaPDF(sFolder+sNombreArchivo);

  bmImagen := CreaThumbnail(sFolder,sNombreArchivo,imgMiniatura.Width,imgMiniatura.Height);
  imgMiniatura.Picture.Assign(bmImagen);
  FreeAndNil(bmImagen);
end;


¿Habrá algo que falte? Oriéntame, por favor.

manuc 15-03-2012 21:16:33

ohh!!

Perdona, fallo mío.

Me faltaba este trozo de código :-) :

Código Delphi [-]
type
 IExtractImage = interface ['{BB2E617C-0920-11d1-9A0B-00C04FC2D6C1}'] // http://msdn2.microsoft.com/en-us/lib...48(VS.85).aspx
  function GetLocation(pszPathBuffer: LPWSTR; cchMax: DWORD; var pdwPriority: DWORD; const prgSize: SIZE; dwRecClrDepth: DWORD; var pdwFlags: DWORD): HRESULT; stdcall;
  function Extract(var phBmpImage: HBITMAP): HRESULT; stdcall;
 end;

Te he preparado una demo, que puedes descargarla aquí: www.applinet.es/descargas/thumbnail_demo.zip

¿Puedes probarlo con añadiendo este código?
Cuéntame como te fue.

Un saludo.

Manuel.

TiammatMX 15-03-2012 22:17:54

Cita:

Empezado por manuc (Mensaje 427771)
ohh!! ...

¡¡¡¡AAAAAHHHHHHHHH!!!! Gracias a tu participación (The Beatles tenía mucha razón con éso de "with a little help from my friends") la aplicación ha quedado espectacular.

Solamente que en la primera corrida (el TImage "virgen", la memoria sin ningún dato) me arroja una excepción, pero quiero creer que es por que aún no tiene nada...

Muchas gracias, Manuel. No sabes cuánto de lo agradezco.

manuc 16-03-2012 08:41:34

jaja, me alegro que vaya bien!

Nada, hoy por ti, mañana por mí ;)

Un saludo.

TiammatMX 16-03-2012 17:56:04

Cita:

Empezado por manuc (Mensaje 427803)
jaja, me alegro que vaya bien!...

Viendo ésto, "bien" es poco... :D

roman 16-03-2012 18:29:41

Hola,

¿Se requiere tener instalado el Adobe Acrobat? Porque probé el ejemplo de manuc y no me muestra nada. Yo uso Foxit en lugar de Adobe.

// Saludos

TiammatMX 16-03-2012 20:00:01

Cita:

Empezado por roman (Mensaje 427835)
Hola...

¡Hola, Román! Primera vez que te apareces en mis preguntas..., un honor.

Cita:

Empezado por roman (Mensaje 427835)
...¿Se requiere tener instalado el Adobe Acrobat? Porque probé el ejemplo de manuc y no me muestra nada. Yo uso Foxit en lugar de Adobe...

Según entendí el código, se extrae del thumbnail del sistema operativo la imagen creada a partir del archivo (manuc, razón por la cual no era posible mostrar dentro de la aplicación el thumbnail directo desde la base de datos. Otro punto a favor tuyo.) y sinceramente, es la primerísima ocasión que escucho mencionar FoxIt, por lo que carezco de referencia sobre su funcionamiento.

Pero si genera una imagen de vista previa para el sistema operativo, no veo por qué no puedas acceder a ella, a menos que realmente se requiera Adobe Acrobat por alguna razón que no puedo deducir en éste momento del código...

Saludines.

roman 16-03-2012 21:05:57

Yo lo que creo es que el Acrobat Reader implementa la interfaz IExtractImage que es la que se lee con el código de manuc. Y eso significa que debes tener instalado el Acrobat Reader. En otros términos, debes estar preparado para advertir a tus usuarios que sin el Acrobat no podrán ver las miniaturas.

// Saludos

TiammatMX 16-03-2012 23:38:59

Cita:

Empezado por roman (Mensaje 427845)
Yo lo que creo es que el Acrobat Reader implementa la interfaz IExtractImage que es la que se lee con el código de manuc. Y eso significa que debes tener instalado el Acrobat Reader. En otros términos, debes estar preparado para advertir a tus usuarios que sin el Acrobat no podrán ver las miniaturas.

// Saludos

Sí, Román..., estoy más que consciente de ello..., pero como es "software estandarizado" en las oficinas del cliente, no me preocupa mucho...

(por el momento... :( )

manuc 21-03-2012 19:04:48

tiammat, te quedó bien el formulario, con la vista previa.

Me alegro.

Un saludo.


La franja horaria es GMT +2. Ahora son las 03:32:00.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi