Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   OOP (https://www.clubdelphi.com/foros/forumdisplay.php?f=5)
-   -   Responder a un click en un objeto (tImage) mostrado en un tStatusBar (https://www.clubdelphi.com/foros/showthread.php?t=32777)

sitrico 15-06-2006 23:36:12

Responder a un click en un objeto (tImage) mostrado en un tStatusBar
 
Tengo el siguiente código (de prueba) que me permite usar un tProgresBar y Mostrar Varios tImage dentro de un tStatusBar:


Código Delphi [-]
unit StatusBarMain;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ComCtrls, ImgList, ExtCtrls, JvImageList, Buttons;

type
  TForm1 = class(TForm)
    StatusBar1: TStatusBar;
    CheckBox1: TCheckBox;
    CheckBox2: TCheckBox;
    CheckBox3: TCheckBox;
    CheckBox4: TCheckBox;
    CheckBox5: TCheckBox;
    ImageList1: TImageList;
    CheckBox6: TCheckBox;
    CheckBox7: TCheckBox;
    CheckBox8: TCheckBox;
    Edit1: TEdit;
    Button1: TButton;
    ProgressBar1: TProgressBar;
    procedure StatusBar1DrawPanel(StatusBar: TStatusBar;
      Panel: TStatusPanel; const Rect: TRect);
    procedure CheckBox1Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure SpeedButtonClick(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

uses Types;

{$R *.dfm}

procedure TForm1.StatusBar1DrawPanel(StatusBar: TStatusBar;
  Panel: TStatusPanel; const Rect: TRect);
Const
mrg = 25;
Var
r : tRect;
i,j, px : Integer;

// Aqui hago el trabajo de mostrar la imagen

Procedure MostrarImagen(ItemIndex:Integer);
Var
img : TImage;
Begin
img := TImage.Create(StatusBar);
Try
   img.Tag := ItemIndex;
   img.AutoSize := False;
   img.Stretch := True;
   img.Height := 15;
   img.Width := 15;
   img.Transparent := true;
// falta esta funcion que no trabaja:
// img.onclick := MiOnClick;
   ImageList1.GetBitmap(ItemIndex,img.Picture.Bitmap);
   StatusBar.Canvas.Draw(px,r.Top,img.Picture.Bitmap);
Finally
   Inc(px,mrg);
   End;
End;

begin
//Limpiar las imagenes
For i := 0 to ComponentCount-1 do
   If (Components[i] is TImage) then
      If tImage(Components[i]) <> nil Then
         tImage(Components[i]).Free;
// esta rutina ignorenla sólo es una prueba y fue la forma simple de 
// contar el nro de imagenes a mostrar (una por cada checked)
j := 0;
For i := 0 to ComponentCount-1 do
   if Components[i] is TCheckBox then
      If TCheckBox(Components[i]).Checked Then
         inc(j);
// el progressBar
If Panel.Index = 3 then
   Begin
   With ProgressBar1 do
      Begin
      Top := Rect.Top;
      Left := Rect.Left;
      Width := Rect.Right - Rect.Left;
      Height := Rect.Bottom - Rect.Top;
      End;
   End;
// las imagenes
If Panel.Index = 4 then
   Begin
   r := Rect;
   px := r.left + (((r.Right - r.left)- (j * mrg)) div 2);
   For i := 0 to ComponentCount-1 do
      if Components[i] is TCheckBox then
          If TCheckBox(Components[i]).Checked Then
             MostrarImagen(TCheckBox(Components[i]).Tag);
   End;
end;

// Para mover el status bar
procedure TForm1.CheckBox1Click(Sender: TObject);
begin
StatusBar1.Refresh;
end;

// Esto es obligatorio mara meter el progressbar dentro del statusBar 
// tomado de un foro)
procedure TForm1.FormCreate(Sender: TObject);
Var
ProgressBarStyle : Integer;
begin
ProgressBar1.Parent := StatusBar1;
ProgressBarStyle := GetWindowLong(ProgressBar1.Handle,GWL_EXSTYLE);
ProgressBarStyle := ProgressBarStyle - WS_EX_STATICEDGE;
SetWindowLong(ProgressBar1.Handle,GWL_EXSTYLE,ProgressBarStyle);
end;

// para mover el ProgressBar
procedure TForm1.Button1Click(Sender: TObject);
begin
ProgressBar1.StepIt;
If ProgressBar1.Position = ProgressBar1.Max Then
   ProgressBar1.Position := 0;
end;

end.

Como pueden ver lo que hago es mostrar una ó más imágenes dentro de un panel de un tStatusBar (segun se seleccionen los tCheckBox) claro que no es la idea de mi aplicación pero es una prueba de lo que quiero hacer:

Segun ciertos parametros, aparecerán en el panel de la StatusBar varios iconos (tImage) con información adicional para el usuario. lo que quiero hacer es que si el usuario hace click sobre uno de esos iconos se ejecute el codigo correspondiente. Esto último no es problema (tengo acciones y las lanzo segun el tag del objeto).

Lo que sí es un problema es que los tImage no responden al click del ratón. :(

Disculpen lo largo :)

PD Uso Delphi 7 con componentes normales, se que hay por hay algunos tstatusBar especializados pero preferiría usar los normales (no dan tantos problemas :confused: )

Bicho 16-06-2006 09:04:52

Cita:

Empezado por sitrico
Lo que sí es un problema es que los tImage no responden al click del ratón

Pero la statusbar si, que es realmente quien tiene asignada las imágenes y es a ella sobre la que haces click, no sobre las imágenes.

Puedes usar el evento OnClick o mejor aún, el OnMouseDown, que te da las coordenadas X, Y de la posición exacta del ratón sobre la barra donde has hecho click, sólo tienes que comparar esas coordenadas con el rango que ocupa cada una de las imágenes que tienes en la barra de estado. Además para hacerlo más sencillo puedes usar distintos panels en la barra, cada uno para una imagen.

Te pongo un ejemplo muy sencillo, en mis programas tengo una barra de estado con una imagen que imita una conexión abierta o cerrada (son dos imagenes y según una variable se cambian), pues bien al hacer clic sobre la posición donde esta la imagen en la barra de estado, el programa ejecuta el evento de conexión, se conecta y me cambia la imagen. Para saber si he pulsado sobre la imagen le pregunto lo siguiente:

Código Delphi [-]
procedure TForm1.StatusBar1MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
     if x <= StatusBar1.panels[1].Width then begin
        if conectado then Desconecta
        else conecta;
     end;
end;

La imagen está en el primer panel de la barra y busco si he hecho click entre el principio de la barra (donde empieza el panel: X=0) y el ancho del panel (donde acaba la imagen: Panels[1].width), luego ya según el estado de la variable conecta o desconecta.

Espero te sirva de ayuda.

Saludos

sitrico 16-06-2006 17:30:52

Bicho:
De buenas a primeras parece que por ahi van los tiros (OnMouseDown) Gracias.


Pero te comento lo siguiente:

En tu código falta verificar el boton pulsado :)

Código Delphi [-]
If Button = mbLeft Then
esa es la parte fácil

La cosa se me complica :mad:

Tu comparas el valor sólo el valor:

Código Delphi [-]
x <= StatusBar1.panels[1].Width

Este código -así- aplica a los 2 primeros páneles (0 y 1) pero el ejemplo vale.

Yo uso el panel 4 (el quinto) para dibujar los iconos, tendría que calcular primero la pocición "left" del panel (¿suma de los width de los anteriores?) pero luego tendría que calcular:

1. cuantos iconos hay
2. posiciones de cada uno ( al leer las coordenadas left y top de las imagenes son 0,0 :confused: )
3. comparar la coordenada X del click con cada uno de los rangos
4 (lo dificil) tengo N imagenes, el click fue en la nro I ¿ cual es la nro I y a que evento debe llamar ? .....:eek:

Por cuestiones de presentación no puedo separar las imagenes en paneles individuales (sería lo más facil, tanto que lo voy a considerar seriamente)

¿No habrá alguna manera de pasar el mensaje (click) a las imagenes para que puedan responder directamente?

Por ahora voy a hacer algunas pruebas a ver que consigo.

Gracias nuevamente.

Y todavía dicen que en delphi se hacen los programas "sin escribir una linea de código" :rolleyes:

Edito para agregar resultados de las pruebas:

Código Delphi [-]
procedure TForm1.StatusBar1MouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
Var
i,j, px : Integer;
begin
If Button = mbLeft Then
   Begin
   Edit1.Text := 'x='+IntToStr(x)+', y='+IntToStr(y);
   Edit2.Text := '';
   Memo1.lines.Clear;
   If (x >= rPanel4.Left)  And (x <= rPanel4.Right) Then //
      Begin
      // Determinar la posición de la primera imagen
      j := NumeroImagenes;
      px := rPanel4.left + (((rPanel4.Right - rPanel4.left)- (j * mrg)) div 2);
      For i := 0 to j do
         Begin
         If (x >= px-1) and (x <= px+17) Then // un poco de margen
            Edit2.Text := intToStr(i); // el valor i contiene el nº del icono pulsado
         // saltar a la posicion de la siguiente imagen
         Inc(px,mrg);
         End;
      End;
   End;
end;

Este codigo soluciona los problemas (1, 2 , y 3) sólo aclarar que rPanel4 es una variable privada de tipo tRect que almacena el valor de Rect en el evento:

Código Delphi [-]
procedure TForm1.StatusBar1DrawPanel(StatusBar: TStatusBar;
  Panel: TStatusPanel; const Rect: TRect);
Begin
If Panel.Index = 4 then
   Begin
   rPanel4 := Rect;

Solo falta saber cual es el boton: i...

root 16-06-2006 17:51:49

Hola
 
Soy estudiante de informatica y estoy en un proyecto pero me hace falta encontrar una funcion que me permita adicionar un usuario a los permisos de seguridad de una carpeta y darle acceso total a ese usuario, tengo una pero lo que hace es insertar el usuario que yo le diga y quitar todos los que tiene ademas de no darle permiso ninguno.
Por favor si sabes como hacerlo o de alguien que me pueda ayudar te lo agradecere mucho.
Saludos

sitrico 16-06-2006 21:34:39

root, de verdad no tengo ni idea, pero trata de iniciar nuevamente el hilo (pregunta) desde el foro Principal -> Varios que seguro alguien puede indicarte (muy probablemente requerirás llamar al API de WINDOWS)


La franja horaria es GMT +2. Ahora son las 19:05:39.

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