Club Delphi  
    FTP   CCD     Buscar   Trucos   Trabajo   Foros

Retroceder   Foros Club Delphi > Otros temas > Trucos
Registrarse FAQ Miembros Calendario Guía de estilo Buscar Temas de Hoy Marcar Foros Como Leídos

Los mejores trucos

Respuesta
 
Herramientas Buscar en Tema Desplegado
  #1  
Antiguo 23-05-2008
Avatar de xEsk
[xEsk] xEsk is offline
Miembro Premium
 
Registrado: feb 2006
Posts: 449
Poder: 12
xEsk Va por buen camino
TProgressBar cíclico nativo (marquee) (añadida solución 3)

Hola,

Algunas veces seguro que os habéis encontrado con la necesidad de mostrar un proceso que no sabéis cuanto tiempo os va a durar, y sería bonito poder indiciar que el programa esta trabajando, pero el Delphi después de tanto tiempo, aun no soporta la propiedad Marquee en su TProgressBar. Pues aquí os propongo como convertir un TProgressBar nativo del Delphi (Win32) en un TProgressBar con la propiedad marquee, sin tener que usar componentes de terceros, que además la mayoría no son nativos (para gente obsesionada en que los programas deben usar los temas de Windows (como yo) seguro que les gustará).

Preparativos

Incluir la unit CommCtrl al uses, para incluir las constantes: PBS_MARQUEE y PBM_SETMARQUEE.

Si no tenéis estas constantes definidas en vuestro Delphi, aquí os pongo su valor:
Código Delphi [-]
{ For Windows >= XP }
{$EXTERNALSYM PBS_MARQUEE}
PBS_MARQUEE             = $08;
{$EXTERNALSYM PBM_SETMARQUEE}
PBM_SETMARQUEE          = WM_USER+10;
NOTA: Debeis tener en cuenta, que esta propiedad solo esta disponible para sistemas operativos Windows XP y superiores.


Solución 1 - Asignar la propiedad marquee a cualquier TProgressBar

Al crear el formulario le asignamos la propiedad marquee al TProgressBar que hay que convertir:

Código Delphi [-]
SetWindowLong(ProgressBar.Handle, GWL_STYLE, GetWindowLong(ProgressBar.Handle, GWL_STYLE) or PBS_MARQUEE);

Cuando esta en movimiento, este parpadea un poco, pero es facil solucionarlo poniendo la propiedad DoubleBuffered a True.


Como activar/detener el ProgressBar:

Activar:
Código Delphi [-]
SendMessage(ProgressBar.Handle, PBM_SETMARQUEE, WPARAM(True), Velocidad);

Detener:
Código Delphi [-]
SendMessage(ProgressBar.Handle, PBM_SETMARQUEE, WPARAM(False), 0);

Parametros:

[1] El Handle del TProgressBar que vamos a modificar
[2] La propiedad que vamos a modificar del TProgressBar
[3] Lo que vamos a hacer, si activarlo o desactivarlo (true = activar, false = desactivar)
[4] La velocidad de movimiento de la barra de progreso.

Ejemplo final:

Un par de botones, un SpinEdit y el ProgressBar a modificar.

Código Delphi [-]
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ComCtrls, CommCtrl, StdCtrls, Spin;

type
  TForm1 = class(TForm)
    ProgressBar1: TProgressBar;
    Button1: TButton;
    Button2: TButton;
    SpinEdit1: TSpinEdit;
    procedure FormCreate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
  SetWindowLong(ProgressBar1.Handle, GWL_STYLE, GetWindowLong(ProgressBar1.Handle, GWL_STYLE) or PBS_MARQUEE);
  // sin parpadeos
  ProgressBar1.DoubleBuffered:=True;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  SendMessage(ProgressBar1.Handle, PBM_SETMARQUEE, WPARAM(True), SpinEdit1.Value);
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  SendMessage(ProgressBar1.Handle, PBM_SETMARQUEE, WPARAM(False), 0);
end;

end.

Solución 2 - Crear un componente derivado del TProgressBar para no tener que ir configurándolo todas las veces

Código fuente del nuevo componente:

Código Delphi [-]
  
TProgressBarMarquee = class(TProgressBar)
  private
    FSpeed: Integer;
    FMarqueeEnabled: Boolean;
    procedure SetFarqueeEnabled(const Value: Boolean);
  protected
    procedure CreateParams(var Params: TCreateParams); override;
  public
    constructor Create(AOwner: TComponent); override;
    property MarqueeSpeed: Integer read FSpeed write FSpeed default 40;
    property MarqueeEnabled: Boolean read FMarqueeEnabled write SetFarqueeEnabled;
  end;

{ TProgressBarMarquee }

constructor TProgressBarMarquee.Create(AOwner: TComponent);
begin
  inherited;
  FSpeed:=40;
end;

procedure TProgressBarMarquee.CreateParams(var Params: TCreateParams);
begin
  inherited;
  Params.Style:=Params.Style or PBS_MARQUEE;
end;

procedure TProgressBarMarquee.SetFarqueeEnabled(const Value: Boolean);
begin
  FMarqueeEnabled:=Value;
  // enviar mensjae al TProgressBar con los nuevos valores
  SendMessage(Handle, PBM_SETMARQUEE, WPARAM(FMarqueeEnabled), FSpeed);
end;

La segunda versión podría modificarse para soportar también el modo normal del TProgressBar, pero esto ya se lo dejo para quien quiera entretenerse xD Igual que ahora mismo tiene todo los métodos del TProgressBar estándar y no son necesarios.



Solución 3 - Nueva! - Ampliar las funciones del TProgressBar usando Class Helpers

Esta tercera opción, no es válida para todas las versiones de Delphi, en concreto funciona a partir del Delphi 8 (Delphi 8, BDS 2005, BDS 2006 y D2007). Así pues, esta solución utiliza la extensión del lenguaje de Object Pascal llamada Class Helpers para modificar el TProgressBar estándar.

Veamos como implementarla:

Código Delphi [-]
  TProgressBarMarquee = class Helper for TProgressBar
  public
    procedure StartMarquee(Speed: Integer);
    procedure StopMarquee;
    procedure DisableMarquee;
  end;

{ TProgressBarMarquee }

procedure TProgressBarMarquee.StartMarquee(Speed: Integer);
begin
  SetWindowLong(Handle, GWL_STYLE, GetWindowLong(Handle, GWL_STYLE) or PBS_MARQUEE);
  SendMessage(Handle, PBM_SETMARQUEE, WPARAM(True), Speed);
end;

procedure TProgressBarMarquee.StopMarquee;
begin
  SendMessage(Handle, PBM_SETMARQUEE, WPARAM(False), 0);
end;

procedure TProgressBarMarquee.DisableMarquee;
begin
  SetWindowLong(Handle, GWL_STYLE, GetWindowLong(Handle, GWL_STYLE) - PBS_MARQUEE);
end;

La pregunta es, que ganamos respecto a crear un componente derivado del TProgressBar (solución 2) a usar un "helper" para el TProgressBar, pues que la tercera solución lo que hace realmente es "ampliar" el componente TProgressBar, así pues todos los TProgressBar estándar, cuentan ahora con estos 3 nuevos métodos.

Personalmente, esta tercera opción es mi favorita :)

Saludos,
xEsk.
Responder Con Cita
  #2  
Antiguo 23-05-2008
Avatar de neuronic
neuronic neuronic is offline
Miembro
 
Registrado: jul 2007
Ubicación: Catalunya
Posts: 30
Poder: 0
neuronic Va por buen camino
uooo excelente hoy estaba buscando una cosa parecida, genial
Responder Con Cita
  #3  
Antiguo 25-05-2008
Avatar de dec
dec dec is offline
Moderador
 
Registrado: dic 2004
Ubicación: Alcobendas, Madrid, España
Posts: 12.559
Poder: 27
dec Va camino a la famadec Va camino a la fama
Muy buen tutorial y muy útil xEsk. ¡Gracias! ;-)
Responder Con Cita
  #4  
Antiguo 26-05-2008
JXJ JXJ is offline
Miembro
 
Registrado: abr 2005
Posts: 2.473
Poder: 15
JXJ Va por buen camino
¿¿que es eso de marquee??
Responder Con Cita
  #5  
Antiguo 04-06-2008
Avatar de xEsk
[xEsk] xEsk is offline
Miembro Premium
 
Registrado: feb 2006
Posts: 449
Poder: 12
xEsk Va por buen camino
[b]JXJ[b] [i]¿¿que es eso de marquee??[i]

Es como se refieren a los ProgressBar cícilicos.
Responder Con Cita
  #6  
Antiguo 06-06-2008
teo.jurado teo.jurado is offline
Registrado
 
Registrado: may 2008
Posts: 1
Poder: 0
teo.jurado Va por buen camino
Una pregunta.... esto mismo se podria hacer con Canvas?

Me explico. Tengo que hacer una pantalla de presentacion de informacion en tiempo real, de una maquinaria que tenemos en el almacen, y quisiera hacer un tubo con flujos....

En C# Es bastante facil de hacer, pero estoy haciendo el 'porting' a Delphi, y se me resiste....

En C#, utilizo Graficos, el Pen y Brush, haciendo un offset de las lineas con un Timer, pero parece ser que esto en Delphi, como que no funciona igual....
Responder Con Cita
  #7  
Antiguo 09-06-2008
jceluce jceluce is offline
Miembro
 
Registrado: may 2003
Ubicación: Mar del Plata - Argentina
Posts: 29
Poder: 0
jceluce Va por buen camino
Hola, lo probé con D6 y no funciona.
Como no tengo las constante las definí en el proyecto.
Es por la versión o falta algo?
Responder Con Cita
  #8  
Antiguo 09-06-2008
Avatar de xEsk
[xEsk] xEsk is offline
Miembro Premium
 
Registrado: feb 2006
Posts: 449
Poder: 12
xEsk Va por buen camino
[/b][/u][/i]jceluce que solucion estas probando?
Responder Con Cita
  #9  
Antiguo 21-07-2008
Avatar de MaMu
MaMu MaMu is offline
Miembro
 
Registrado: abr 2006
Ubicación: Argentina
Posts: 863
Poder: 12
MaMu Va por buen camino
Este ejemplo en D7 no funciona.
Responder Con Cita
  #10  
Antiguo 04-12-2008
Avatar de sitrico
[sitrico] sitrico is offline
Miembro Premium
 
Registrado: may 2003
Ubicación: Caracas, Venezuela
Posts: 295
Poder: 15
sitrico Va por buen camino
probé con D7 la solucion 1 y lamentablemente no funciona
Responder Con Cita
  #11  
Antiguo 04-12-2008
Avatar de sitrico
[sitrico] sitrico is offline
Miembro Premium
 
Registrado: may 2003
Ubicación: Caracas, Venezuela
Posts: 295
Poder: 15
sitrico Va por buen camino
Sí funciona en D7 pero hay que agregar un componente XPMafifiest :-)
Responder Con Cita
  #12  
Antiguo 04-12-2008
Avatar de sitrico
[sitrico] sitrico is offline
Miembro Premium
 
Registrado: may 2003
Ubicación: Caracas, Venezuela
Posts: 295
Poder: 15
sitrico Va por buen camino
Posteo el resultado completo

Código Delphi [-]
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ComCtrls, XPMan;

type
  TForm1 = class(TForm)
    ProgressBar1: TProgressBar;
    Button1: TButton;
    Button2: TButton;
    XPManifest1: TXPManifest;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

const
  PBS_MARQUEE = $08;
  PBS_SETMARQUEE = (WM_USER + 10);

procedure TForm1.Button1Click(Sender: TObject);
begin
SendMessage(ProgressBar1.Handle, PBS_SETMARQUEE, 1, 200);
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
SendMessage(ProgressBar1.Handle, PBS_SETMARQUEE, 0, 200);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  SetWindowLong(ProgressBar1.Handle, GWL_STYLE, GetWindowLong(ProgressBar1.Handle, GWL_STYLE) or PBS_MARQUEE);
  // sin parpadeos
  ProgressBar1.DoubleBuffered:=True;

end;
Responder Con Cita
Respuesta


Herramientas Buscar en Tema
Buscar en Tema:

Búsqueda Avanzada
Desplegado

Normas de Publicación
no Puedes crear nuevos temas
no Puedes responder a temas
no Puedes adjuntar archivos
no Puedes editar tus mensajes

El código vB está habilitado
Las caritas están habilitado
Código [IMG] está habilitado
Código HTML está deshabilitado
Saltar a Foro


La franja horaria es GMT +2. Ahora son las 05:41:46.


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