Club Builder - Foros de discusión Club Builder
Foro de C++Builder en español
 
 FAQFAQ   BuscarBuscar   MiembrosMiembros   Grupos de UsuariosGrupos de Usuarios   RegistrarseRegistrarse 
 PerfilPerfil   Entra para ver tus mensajes privadosEntra para ver tus mensajes privados   EntrarEntrar 

imprimir listview

 
Publicar nuevo tema   Responder al tema    Foros de discusión -> Consultas
Ver tema anterior :: Ver tema siguiente  
Autor Mensaje
Mensaje    Asunto: imprimir listview Responder citando

Ya se que se ha preguntado varias veces, pero ninguna tiene la solución definitiva.
Mirando por internet, he encontrado esta página y sobre todo la clase printobj (http://www.marteens.com/ejemplos.htm) pero está en delphi. Parece interesante, pero no llego a acabar de traducir el código, sobre todo
Código:
   FStarts: array of Integer;
   FWidths: array of Integer;

   SetLength(FStarts, FListView.Columns.Count);
   SetLength(FWidths, FListView.Columns.Count);
   for I := Low(FStarts) to High(FStarts) do


Lo interesante está en que le mandas el listview a imprimir y no importa las columnas que tenga
Espero vuestra ayuda para poder hacer algo parecido en C++, ya que no estoy muy fuerte en programar clases
la llamada la hago así, segun pone la explicación de la página
Código:
if(!PrintDialog1->Execute()) return;
TPrintObj *prn = new TPrintObj();
prn->Create(Printer(),ListView1);
prn->ListPrint("","");
prn->Destroy();


Saludos, Bosoft

PD: si queréis la traducción que he hecho, os la pego. Y el programa tiene un fallo si lo compilo en mi proyecto y no puedo detectarlo, porque builder 2007 no me hace el seguimiento dentro del .pas
Volver arriba
Ver perfil de usuario Enviar mensaje privado
Mensaje    Asunto: Responder citando

No he mirado el código original, cuando tenga tiempo lo haré. Te adelanto que en delphi los arrays pueden ser estáticos o dinámicos. En el código que expones se refiere a arrays dinámicos, de forma que

Código:
FStarts: array of Integer;
//es equiparable a:
int *FStarts;

y
Código:
SetLength(FStarts, FListView.Columns.Count);
// asigna el tamaño del array dinámico y podría traducirse como
FStarts = new int[FListView.Columns.Count];


En delphi no se destruyen explicitamente estos arrays, desaparecen o liberan automáticamente al salir del ambito. En C++ debes destruirlos con
Código:
delete [] FStarts;


Por ultimo el bucle que pones en la sentencia for, se refiere a un bucle que comienza en el primer elemento del array y termina en el último. Podrías poner algo como:

Código:
for(int i=0; i<FListView.Columns.Count; i++){
.................
}



Saludos.
Volver arriba
Ver perfil de usuario Enviar mensaje privado
Mensaje    Asunto: Responder citando

He mirado el código. Te propongo esta traducción:


PrintObject.h

Código:
//---------------------------------------------------------------------------

#ifndef PrintObjectH
#define PrintObjectH
//---------------------------------------------------------------------------

#include <printers.hpp>
#include <ComCtrls.hpp>

class TPrintObj
{
  protected:
    TPrinter  *FPrinter;
    String    FTitle;
    String    FPageFormat;
    TListView *FListView;
    int       FCurY;
    int       FMaxX;
    int       FMaxY;
    int       FHeight;
    int       *FStarts;
    int       *FWidths;

    void NewLine();
    void PrintHeader();
    void PrintLine(TListItem *AItem);
    void PrintRect(const String S, int Column);
  public:
    TPrintObj(TPrinter *APrinter, TListView *AListView);
    ~TPrintObj();

    void Print(const String ATitle = "", const String APageFormat = "");
};

#endif


PrintObject.cpp:

Código:
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "PrintObject.h"

//---------------------------------------------------------------------------

#pragma package(smart_init)
TPrintObj::TPrintObj(TPrinter *APrinter, TListView *AListView)
{
  FPrinter = APrinter;
  FListView = AListView;
  FStarts = 0;
  FWidths = 0;
}

TPrintObj::~TPrintObj()
{
   if(FStarts) delete [] FStarts;
   if(FWidths) delete [] FWidths;
}

void TPrintObj::NewLine()
{
  FCurY += FHeight;
  if (FCurY > FMaxY - 2 * FHeight){
    FCurY = 0;
    FPrinter->NewPage();
  }
}

void TPrintObj::Print(const String ATitle, const String APageFormat)
{
  int I, FConvX1, FConvX2;

  FPrinter->BeginDoc();
  __try{
    FPrinter->Canvas->Font->Assign(FListView->Font);
    FTitle = ATitle;
    FPageFormat = APageFormat;
    FCurY = 0;
    FMaxX = FPrinter->PageWidth;
    FMaxY = FPrinter->PageHeight;
    FConvX1 = FPrinter->Canvas->TextWidth("M");
    FConvX2 = FListView->Canvas->TextWidth("M");
    if(FStarts) delete [] FStarts;
    FStarts = new int[FListView->Columns->Count];
    if(FWidths) delete [] FWidths;
    FWidths = new int[FListView->Columns->Count];
    for (int I = 0; I < FListView->Columns->Count; I++){
      if(I == 0)
        FStarts[I] = FConvX1;
      else
        FStarts[I] = FStarts[I - 1] + FWidths[I - 1];
      FWidths[I] = FListView->Columns->Items[I]->Width * FConvX1/FConvX2;
    }
    for (int I = 0; I < FListView->Items->Count; I++){
      if(FCurY == 0)
        PrintHeader();
      PrintLine(FListView->Items->Item[I]);
    }
  }__finally{
    FPrinter->EndDoc();
  }
}

void TPrintObj::PrintHeader()
{
  TRect R;
  if (FTitle != "" || FPageFormat != ""){
    FPrinter->Canvas->Font->Size = FPrinter->Canvas->Font->Size + 2;
    __try{
      FHeight = FPrinter->Canvas->TextHeight(FTitle + FPageFormat + "1234567890");
      R = Rect(FStarts[0], FCurY, FMaxX, FCurY + FHeight);
      if(FTitle != "")
        DrawText(FPrinter->Canvas->Handle, FTitle.c_str(), -1, &R, DT_LEFT | DT_TOP | DT_SINGLELINE);
      if (FPageFormat != "")
        DrawText(FPrinter->Canvas->Handle, Format(FPageFormat, ARRAYOFCONST((FPrinter->PageNumber))).c_str(),
                 -1, &R, DT_RIGHT | DT_TOP | DT_SINGLELINE);
      NewLine();
    }__finally{
      FPrinter->Canvas->Font->Size = FPrinter->Canvas->Font->Size - 2;
    }
    NewLine();
  }
  FHeight = 0;
  FPrinter->Canvas->Font->Style = TFontStyles()<< fsBold;
  try{
    for(int I = 0; I< FListView->Columns->Count; I++)
      PrintRect(" " + FListView->Columns->Items[I]->Caption + " ", I);
    NewLine();
  }__finally{
    FPrinter->Canvas->Font->Style = TFontStyles();
  }
}

void TPrintObj::PrintLine(TListItem *AItem)
{
  String AStr;

  FHeight = 0;
  for(int I= 0; I <= AItem->SubItems->Count; I++){
    if(I == 0)
      AStr = AItem->Caption;
    else
      AStr = AItem->SubItems->Strings[I - 1];
    PrintRect(" " + AStr + " ", I);
  }
  NewLine();
}

void TPrintObj::PrintRect(const String S, int Column)
{
  static int AlignFlags[] = {DT_LEFT, DT_RIGHT, DT_CENTER};

  int CurHeight;
  int TwoEms;
  TRect R;

  CurHeight = FPrinter->Canvas->TextHeight(S);
  TwoEms = FPrinter->Canvas->TextWidth("M");
  if(CurHeight > FHeight)
    FHeight = CurHeight + 2;
  R = TRect(FStarts[Column], FCurY,
            FStarts[Column] + FWidths[Column], FCurY + CurHeight);
  if(R.Left > FMaxX || R.Right - R.Left < TwoEms)
    return; //Exit;
  if(R.Right > FMaxX)
    R.Right = FMaxX;
  DrawText(FPrinter->Canvas->Handle, S.c_str(), -1, &R,
           AlignFlags[FListView->Columns->Items[Column]->Alignment] | DT_TOP | DT_SINGLELINE);
}


Probado con Builder 5.

Saludos.


Ultima edición por escafandra el Mar 19 Ene, 2010 11:34 am, editado 2 veces
Volver arriba
Ver perfil de usuario Enviar mensaje privado
Mensaje    Asunto: Responder citando

Muchas gracias escafandra. Esta tarde lo pruebo.
Me he decidido por esta función ya que "en teoría" lo hace todo automáticamente

Gracias de nuevo

Saludos, Bosoft
Volver arriba
Ver perfil de usuario Enviar mensaje privado
Mensaje    Asunto: Responder citando

Hola escafandra:
después de unas cuantas horitas "pegándome" con la clase, no he podido hacerla funcionar.
Yo uso 2007 y no me entra el debug en la clase (que para eso quería la traducción)
Así pues he copiado la función print en mi cpp y lo he intentado desde allí
El primer error detectado es
Código:
FPrinter->BeginDoc();
// cambiado por
Printer()->BeginDoc();

Y al menos esta linea la trata bien, pero saltaba en la siguiente
Código:
FPrinter->Canvas->Font = FListView->Font;

lo que me dio a entender que no "pillaba" el puntero Fprinter correctamente. Lo cambié por Printer(), pero sigue saltando el mismo error. Pero si elimino esa linea, me salta en la siguiente
Código:
FTitle = ATitle;

Me romperé un poco mas el coco haciendo una función en vez de una clase y cuando lo tenga correcto lo pasaré

Gracias
Saludos, Bosoft
Volver arriba
Ver perfil de usuario Enviar mensaje privado
Mensaje    Asunto: Responder citando

Cambia
Código:
FPrinter->Canvas->Font = FListView->Font;

por

Código:
FPrinter->Canvas->Font->Assign(FListView->Font);


El puntero FPrinter, asignado en el constructor no tiene porqué dar problemas.

No tengo la versión 2007 pero puedo probarlo en Builder 6


Saludos.
Volver arriba
Ver perfil de usuario Enviar mensaje privado
Mensaje    Asunto: Responder citando

¿Y te funciona?
Yo no he sido capaz de hacerlo funcionar, aunque compila sin errores
Probare a hacer las funciones en vez de clase para poder probar

Gracias de nuevo

Saludos, Bosoft
Volver arriba
Ver perfil de usuario Enviar mensaje privado
Mensaje    Asunto: Responder citando

Si, me funciona. Lo he probado en Builder 5 con un pequeño programita que consta de un ListView y un botón de impresión:

Código:
void __fastcall TForm1::Button1Click(TObject *Sender)
{
   TPrintObj PO(Printer(), ListView1);
   PO.Print();
}


He probado sobre una impresora virtual PDFCreator 0.9.9 para no malgastar papel.

No he probado con otras versiones del Builder.

Saludos.
Volver arriba
Ver perfil de usuario Enviar mensaje privado
Mensaje    Asunto: Responder citando

Pues no hay manera, me sigue cascando en
Código:
FPrinter->Canvas->Font->Assign(FListView->Font);

y si quito esa linea casca en
Código:
FTitle = ATitle;

Debe ser de la versión 2007

Seguiré haciendo pruebas

Gracias por tu gran ayuda

Saludos, Bosoft
Volver arriba
Ver perfil de usuario Enviar mensaje privado
Mensaje    Asunto: Responder citando

Por fin, ya funciona
He quitado todas las referencias a FPrinter, las he cambiado por Printer() y ahora no casca
La llamada al creador ha quedado así
Código:
TPrintObj(TListView *AListView);


Ahora me centraré en mejorar el código y añadirle mas ..... "cositas"

Por cierto ¿a ti te salen todos los items centrados? es como si no pillara bien el taLeftJustify de las columnas y las saca todas centradas

Muchísimas gracias por tu gran ayuda

Saludos, Bosoft
Volver arriba
Ver perfil de usuario Enviar mensaje privado
Mensaje    Asunto: Responder citando

bosoft escribió:
Por fin, ya funciona
Perfecto.

bosoft escribió:

Por cierto ¿a ti te salen todos los items centrados? es como si no pillara bien el taLeftJustify de las columnas y las saca todas centradas


Tienes razón. Cometí un error en el código. Donde dice:
Código:
DrawText(FPrinter->Canvas->Handle, S.c_str(), -1, &R,
           AlignFlags[FListView->Columns->Items[Column]->Alignment] || DT_TOP || DT_SINGLELINE);

Debe decir:
Código:
  DrawText(FPrinter->Canvas->Handle, S.c_str(), -1, &R,
           AlignFlags[FListView->Columns->Items[Column]->Alignment] | DT_TOP | DT_SINGLELINE);


Está arreglado en el mensaje donde publico la clase.

Saludos.
Volver arriba
Ver perfil de usuario Enviar mensaje privado
Mostrar mensajes de anteriores:   
Cambiar a:  
No puedes publicar temas nuevos en este foro
No puedes responder a temas en este foro
No puedes editar tus mensajes en este foro
No puedes borrar tus mensajes en este foro
No puedes votar en las encuestas de este foro


Hosting WordPress Indedmedia desde 3,99 €
© 2002–2026 Club Builder · Funciona con phpBB.