Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Varios (https://www.clubdelphi.com/foros/forumdisplay.php?f=11)
-   -   Scroll en componente TScrollBox (https://www.clubdelphi.com/foros/showthread.php?t=84426)

cmfab 17-10-2013 16:32:35

Scroll en componente TScrollBox
 
Hola a todos en este gran foro, resulta que tengo un componente contenedor TScrollBox, en el cual creo infinidad de controles tipo Tbutton, el asunto es que necesito que funcione el scroll al arrastrarlo sin soltarlo, osea que vaya bajando o subiendo por lal lista de botones, actualmente esto me funciona solo con el click en los extremos de la barra de desplazamiento vertical, o arrastrando el scroll y soltandolo, pero necesito que al arrastrar el scroll vertical la lista se vaya desplazando automáticamente igual que lo hace un listbox por ejemplo, espero me haya explicado correctamente y gracias de antemano.

ecfisa 18-10-2013 18:11:44

Hola cmfab.

Podes lograrlo mediante la propiedad Tracking, por ejemplo:
Código Delphi [-]
procedure TForm1.CheckBox1Click(Sender: TObject);
begin
  with ScrollBox1 do
  begin
    HorzScrollBar.Tracking := CheckBox1.Checked;
    VertScrollBar.Tracking := CheckBox1.Checked;
  end;
end;
(También podes configurar esta propiedad desde el Object Inspector)

Saludos :)

cmfab 18-10-2013 19:24:14

Listo, muchísimas gracias por la aclaración

FideRosado 19-10-2013 07:14:09

sobre el scroll con la rueda del raton
 
se puede usar en el mismo contenedor la rueda del raton ,, yo he intentado pero no me sale..

ecfisa 19-10-2013 10:38:47

Hola FideRosado.

Revisa este enlace: Ratón arriba, ratón abajo, ratón arriba...

Saludos :)

FideRosado 20-10-2013 00:25:27

Cita:

Empezado por ecfisa (Mensaje 468618)
Hola FideRosado.

Revisa este enlace: Ratón arriba, ratón abajo, ratón arriba...

Saludos :)


ese ejemplo lo puse pero no me sale.. se me keda en donde mismo..

segun el esquema que esta arriva, en texto , es la jerarquia del scrollbox, como esta en el ejemplo que me mandastes , trata de hacerlo que funcione el scroll ahy .. y despues me lo posteas para saber como fue porke ya los intente todos..

ecfisa 20-10-2013 00:38:53

Hola FideRosado.

Si el control que posee el foco es el TScrollBox el código del enlace funciona correctamente. Claro está que siempre que el scroll sea posible.

Por ejemplo, dos casos en los que no funcionaría:
  • Que todos los controles puedan ser mostrados en el ScrollBox (nada para hacer scroll).
  • Que los controles a ser mostrados estén dentro de otro alineado al cliente. Por ejemplo, un TScrollBox que contiene un TPanel alineado al cliente con muchos TButton dentro.

Saludos :)

FideRosado 20-10-2013 16:50:06

ecfisa
 
pero no me sale no se porke ,,

FideRosado 20-10-2013 16:52:04

Cita:

Empezado por FideRosado (Mensaje 468676)
pero no me sale no se porke ,,

trata de hacerlo aver si te sale , con el ejemplo ke me mandastes ..

será que cuando creas los tpanel dentro del scrollbox. el mismo pierde el foco porke lo que este dentro es tpnel..como hacer que el siempre tenga el foco

FideRosado 20-10-2013 21:13:08

Cita:

Empezado por FideRosado (Mensaje 468677)
trata de hacerlo aver si te sale , con el ejemplo ke me mandastes ..

será que cuando creas los tpanel dentro del scrollbox. el mismo pierde el foco porke lo que este dentro es tpnel..como hacer que el siempre tenga el foco


creo que seria bueno pensar en capturar el control a travez del parent , es decir si las dependencias estab dentro del llamado scrollbox1 pues a ese hay que mandarle siempre el nuevo valor de scroll box..

ecfisa 20-10-2013 22:33:12

Cita:

Empezado por FideRosado (Mensaje 468677)
trata de hacerlo aver si te sale , con el ejemplo ke me mandastes ..

será que cuando creas los tpanel dentro del scrollbox. el mismo pierde el foco porke lo que este dentro es tpnel..como hacer que el siempre tenga el foco

Hola.

No funciona por que cae en la misma categoría del segunco caso del mensaje #7 (controles con Align). Basta con que cambies esto en la creación de los paneles para que funcione:
Código Delphi [-]
procedure TForm1.btnCreatePnlClick(Sender: TObject);
begin
  Pnl         := TPanel.Create(nil);
  Pnl.Name    := 'PnlUser' + IntToStr(numberpanel);

  //Pnl.Align   := alTop;  (desactivar esta línea)

  Pnl.Top     := numberpanel * 50; // agregar esta
  ...

Saludos :)

FideRosado 21-10-2013 02:30:50

Cita:

Empezado por ecfisa (Mensaje 468691)
Hola.

No funciona por que cae en la misma categoría del segunco caso del mensaje #7 (controles con Align). Basta con que cambies esto en la creación de los paneles para que funcione:
Código Delphi [-]procedure TForm1.btnCreatePnlClick(Sender: TObject); begin Pnl := TPanel.Create(nil); Pnl.Name := 'PnlUser' + IntToStr(numberpanel); //Pnl.Align := alTop; (desactivar esta línea) Pnl.Top := numberpanel * 50; // agregar esta ...


Saludos :)



en todo caso puede darme problemas, recuerda que esa es la forma en la que el panel se acomoda dentro del scroll..y ademas , el scroll recibe los paneles bien . pork no se le puede capturar el scroll que tiene el control scroll box en ese momento y cambiarlo por otro..

ecfisa 21-10-2013 11:36:34

1 Archivos Adjunto(s)
Cita:

Empezado por FideRosado (Mensaje 468701)
...
pork no se le puede capturar el scroll que tiene el control scroll box en ese momento...

Hola.

Sencillamente por que el área cliente del TScrollBox se encuentra solapado por los paneles que la ocupan. Es por esa razón que la función FindVCLWindow devuelve un TPanel (aquél sobre el que se halla el cursor).

Sin embargo, si creas mas paneles de los que pueda mostrar el ScrollBox y posicionas el cursor del mouse sobre el ScrollBar vertical (del ScrollBox), verás que la rueda funciona correctamente tal como en este demo que te adjunto.

Saludos :)

FideRosado 21-10-2013 17:21:33

aca esta la solucion, hacer scroll, teniendo lo que sea encima o dentro del scrollbox
 
1 Archivos Adjunto(s)
aca les dejo el ejemplo de la aplicacion..se que no esta terminada como tiene que ser , pero es un avance en este tema..
Código Delphi [-]
unit Unit1;

interface

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

type
  TForm1 = class(TForm)
    btnCreatePnl: TButton;
    btnDelPnl: TButton;
    Button1: TButton;
    Button2: TButton;
    Edit1: TEdit;
    ScrollBox1: TScrollBox;
    procedure btnCreatePnlClick(Sender: TObject);
    procedure btnDelPnlClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    procedure MouseWheel(var Msg: tagMSG; var Handled: Boolean);
    procedure CheckBoxClick(Sender: TObject);
  public

  end;

var
  Form1: TForm1;

implementation {$R *.dfm}

var
  Pnl : TPanel;
  numberpanel: Integer = 1;

procedure TForm1.FormCreate(Sender: TObject);
begin
  Application.OnMessage:= MouseWheel;
end;

procedure TForm1.MouseWheel(var Msg: tagMSG; var Handled: Boolean);
var
  FControl: TWinControl;
   i: SmallInt;
begin
    FControl:= FindVCLWindow(Mouse.CursorPos);
    i:= HiWord(Msg.wParam);
  if Assigned(FControl) and (Msg.message = WM_MOUSEWHEEL) then begin
  try
    if (FControl.Parent is TScrollBox) then begin
      if i > 0 then begin
        with TScrollingWinControl(ScrollBox1).VertScrollBar do begin
          if ScrollBox1.VertScrollBar.Range > 0 then begin
            Position:= Position - Increment ;
            Edit1.Text:=IntToStr(Position);
          end;
        end;
      end else begin
        with TScrollingWinControl(ScrollBox1).VertScrollBar do begin
          if ScrollBox1.VertScrollBar.Range > 0 then begin
            Position:= Position + Increment;
            Edit1.Text:=IntToStr(Position);
          end;
        end;
      end;
    end;
  except
      next;
  end;
  end;
end;

procedure TForm1.CheckBoxClick(Sender: TObject);
begin
  if TCheckBox(Sender).Checked then
    TPanel(TCheckBox(Sender).Parent).Color := clRed
  else
    TPanel(TCheckBox(Sender).Parent).Color := clBtnFace
end;



procedure TForm1.btnCreatePnlClick(Sender: TObject);

begin
  Pnl         := TPanel.Create(nil);
  Pnl.Name    := 'PnlUser' + IntToStr(numberpanel);
  Pnl.Caption := '';
  Pnl.Align   := alTop;
  Pnl.Height  := 60;
  Pnl.Parent  := ScrollBox1;
  Pnl.ParentBackground := False;
  
  with TCheckBox.Create(nil) do
  begin
    OnClick := CheckBoxClick;
    Name    := 'CheckMail'+ IntToStr(numberpanel);
    Caption := '';
    left    := 16;
    top     := 21;
    Width   := 17;
    Parent  := Pnl;
  end;
end;

procedure TForm1.btnDelPnlClick(Sender: TObject);
var
  i,j: Integer;
begin
  for i:= ScrollBox1.ControlCount - 1 downto 0 do
    if ScrollBox1.Controls[i] is TPanel then
      for j:= 0 to TPanel(ScrollBox1.Controls[i]).ControlCount-1 do
        if (TPanel(ScrollBox1.Controls[i]).Controls[j] is TCheckBox) and
           (TCheckBox(TPanel(ScrollBox1.Controls[i]).Controls[j]).Checked) then
          ScrollBox1.Controls[i].Free;
end;



procedure TForm1.Button1Click(Sender: TObject);
begin

     with TScrollingWinControl(ScrollBox1).VertScrollBar do begin
          if ScrollBox1.VertScrollBar.Range > 0 then begin
            Position:= Position - Increment ;
            Edit1.Text:=IntToStr(Position);
          end;
     end;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
    with TScrollingWinControl(ScrollBox1).VertScrollBar do begin
          if ScrollBox1.VertScrollBar.Range > 0 then begin
            Position:= Position + Increment ;
            Edit1.Text:=IntToStr(Position);
          end;
     end;
end;

end.

aca les dejo la url del ejemplo en delphi

ecfisa 21-10-2013 18:26:26

Hola.

A, pero eso es distinto a lo que había entendido que solicitabas en el título del mensaje (#4) "sobre el scroll con la rueda del raton"... De ese modo no funciona sobre el scrollbar.

De todos modos la modificación que hiciste se puede optimizar bastante:
Código Delphi [-]
procedure TForm1.MouseWheel(var Msg: tagMSG; var Handled: Boolean);
var
  FControl: TWinControl;
  i       : SmallInt;
begin
  FControl := FindVCLWindow(Mouse.CursorPos);
  i := HiWord(Msg.wParam);
  if Assigned(FControl) and (Msg.message = WM_MOUSEWHEEL) then
  begin
    if (FControl.Parent is TScrollBox) then
    begin
      with TScrollingWinControl(ScrollBox1).VertScrollBar do
      begin
        if i > 0 then
          Position:= Position - Increment
        else
          Position:= Position + Increment;
      end;
    end;
    Next;
  end;
end;

Pero es bueno aclarar que tanto el código del mensaje (#14) como este, debido al uso del procedimiento Next pueden presentar un comportamiento poco deseable.

Por ejemplo, si en un mismo form conviven un TListBox y el TScrollBox del que hemos venido hablando pude apreciar dos de ellos:
  1. Si y se focaliza el ListBox y luego se realiza MouseWheel, la acción desencadena el scroll en ambos controles.
  2. Si el ScrollBox no tiene paneles, el scroll se realizará sobre el ListBox, aún estando situados sobre el ScrollBox.

Saludos. :)

FideRosado 21-10-2013 19:05:08

actualizacion del contenido scrollbox
 
tienes razon .. en eso me di cuenta ,, aca les pongo un a actualizacion del codigo, diciendole a los componentes que si el padre es scrollbox lo haga .. aun se puede mejorar , ve probandolo aver si llegas a mejorarlo..
pero bueno a mi me funcioina perfectamente..

Código Delphi [-]
procedure TForm1.MouseWheel(var Msg: tagMSG; var Handled: Boolean);
var
  FControl: TWinControl;
   i: SmallInt;
   o: integer;
   Scom: TComponent;
begin
    FControl:= FindVCLWindow(Mouse.CursorPos);
    i:= HiWord(Msg.wParam);
    if Assigned(FControl) and (Msg.message = WM_MOUSEWHEEL) then begin
  try

        if ( FControl.Parent is TScrollBox) then begin
            if i > 0 then begin
                with TScrollingWinControl(FControl.Parent).VertScrollBar do begin
                    if TScrollBox(FControl.Parent).VertScrollBar.Range > 0 then begin
                        Position:= Position - Increment;
                    end;
                end;
            end else begin
                with TScrollingWinControl(FControl.Parent).VertScrollBar do begin
                if TScrollBox(FControl.Parent).VertScrollBar.Range > 0 then begin
                        Position:= Position + Increment;
                    end;
                end;
            end;
    end else begin
      if ( FControl.Parent.Parent is TScrollBox) then begin
            if i > 0 then begin
                with TScrollingWinControl(FControl.Parent.Parent).VertScrollBar do begin
                    if TScrollBox(FControl.Parent.Parent).VertScrollBar.Range > 0 then begin
                        Position:= Position - Increment;
                    end;
                end;
            end else begin
                with TScrollingWinControl(FControl.Parent.Parent).VertScrollBar do begin
                if TScrollBox(FControl.Parent.Parent).VertScrollBar.Range > 0 then begin
                        Position:= Position + Increment;
                    end;
                end;
            end;

    end;
     ///////////////
    end;

  except
      next;
  end;
    end;
   Handled := False;
end;

FideRosado 21-10-2013 19:08:46

analiar el contenido. buscando un scrollbox
 
unke pienso que necesita un codigo que busque si el componente o control tiene un parent scrollbox,,

es decir , va leyendo marcha atras para saber si hay un scroll box ...
y hacer el procedimiento..
yo solo utilice el

parent.parent

porque tengo un maximo de 2 niveles.. pero eso se puede mejorar verdad..

ecfisa 21-10-2013 23:25:37

Hola.

Con el código del mensaje #16, note que:
  1. Estando los paneles creados, si el ListBox tiene un ítem seleccionado, haciendo mouse whell cuando el cursor del mouse está sobre el ScrollBox se provoca el scroll en ambos controles.
  2. Si ningún item del ListBox ha sido seleccionado, nunca efectua el scroll mediante mouse whell, aún estando el cursor del mouse sobre él.

Saludos :)

FideRosado 21-10-2013 23:48:06

respuesta
 
que estas hablando me parece que en el ejemplo no se usan listbox solo scrollbox,, me vas a confundir ...

ecfisa 22-10-2013 00:21:32

Hola FideRosado.

Cita:

Empezado por FideRosado (Mensaje 468771)
que estas hablando me parece que en el ejemplo no se usan listbox solo scrollbox,, me vas a confundir ...

Si recordas, este código parte de:
Cita:

Empezado por ecfisa (Mensaje 468618)
Hola FideRosado.

Revisa este enlace: Ratón arriba, ratón abajo, ratón arriba...
...

Que trata una rutina para el manejo de la rueda del mouse lo suficientemente amplia para ser aplicada a distintos controles. Lo que implica detectar previamente el control donde se halla posicionado el mouse.


Si hubieras especificado que se aplicaría solamente a un ScrollBox de un form, te hubiera dado una respuesta mucho mas simple:
Código Delphi [-]
procedure TForm1.MouseWheel(var Msg: tagMSG; var Handled: Boolean);
var
  i: ShortInt;
begin
  if PtInRect(BoundsRect, Mouse.CursorPos) then
  begin
    i := HiWord(Msg.wParam);
    if Msg.message = WM_MOUSEWHEEL then
      with ScrollBox1.VertScrollBar do
        if i > 0 then
          Position:= Position - Increment
        else
          Position:= Position + Increment;
  end;
  Handled := False;
end;
Ya que en este caso no interesa en que parte del form se encuentre el cursor del mouse, el ScrollBox es el único que debe realizar la acción.

Saludos :)


La franja horaria es GMT +2. Ahora son las 12:33:55.

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