PDA

Ver la Versión Completa : Tab Order


shoulder
19-11-2012, 14:12:13
Hola, me estan solicitando un tema de Tab Order, quieren que cuando con la tecla tab se vayan moviendo por cada tecla la misma cambie de color porque no quieren usar tanto el mouse y no se dan cuenta donde se van posicionando...

Gracias.

MartinS
19-11-2012, 14:21:03
Hola: Por cada tecla o cada edit o similar?

Podes usar los eventos OnEnter y On Exit de cada componente y cambiarle el color..

Saludos

nlsgarcia
19-11-2012, 19:17:48
shoulder,

quieren que cuando con la tecla tab se vayan moviendo por cada tecla la misma cambie de color porque no quieren usar tanto el mouse y no se dan cuenta donde se van posicionando...

Revisa este código:

unit Unit1;

interface

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

type
TForm1 = class(TForm)
Edit1: TEdit;
Edit2: TEdit;
Edit3: TEdit;
Memo1: TMemo;
BitBtn1: TBitBtn;
BitBtn2: TBitBtn;
BitBtn3: TBitBtn;
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure ActiveControlChanged(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

// Evento de Control del Focus sobre el Form1 por medio de la Matriz de Controles
procedure TForm1.ActiveControlChanged(Sender: TObject);
var
I: Integer;
begin
for I:= 0 to ControlCount -1 do
begin
TEdit(Controls[I]).Color := clWindow;
TMemo(Controls[I]).Color := clWindow;
if (Controls[i] is TEdit) and (Controls[i] as TEdit).Focused then
TEdit(Controls[I]).Color := clYellow;
if (Controls[i] is TMemo) and (Controls[i] as TMemo).Focused then
TMemo(Controls[I]).Color := clYellow;
end;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
// Activa el Evento de Control de Focus en el Form1
Screen.OnActiveControlChange := ActiveControlChanged;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
// Desactiva el Evento de Control de Focus en el Form1
Screen.OnActiveControlChange := nil;
end;

end.

En el código anterior se resaltan los controles de entrada del formulario al momento de obtener el focus por medio de la propiedad OnActiveControlChange, lo cual incluye la tecla Tab, además al usar controles BitBtn con imágenes distintivas se destacan unos de otros y es más fácil determinar visualmente cual BitBtn tiene el focus activo en un momento dado.

En el link anexo esta implementado el código anterior.

El link es : http://terawiki.clubdelphi.com/Delphi/Ejemplos/?download=OnActiveControlChange.rar

Espero sea útil :)

Nelson.

ecfisa
19-11-2012, 20:27:45
Hola.

Yo estoy de acuerdo con nlsgarcia, aunque aparentemente se teclea un poco más, el modo es mas contemplativo. Algo similar se planteó aquí (http://www.clubdelphi.com/foros/showthread.php?t=78232) hace unos meses, pero está limitado a determinados controles, o a realizar la evaluacion del control activo mediante una larga serie de if - then.

Usando RTTI se puede reducir y flexibilizar el código para que contemple cualquier control que posea la propiedad TColor:

...
const
WM_AFTER_CREATE = WM_USER + 300;

type
TForm1 = class(TForm)
...
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private
FPrevFocusedCtrl: TControl;
FPrevColor: TColor;
procedure WmAfterCreate(var Msg: TMessage); message WM_AFTER_CREATE;
procedure ActiveCtrlChange(Sender: TObject);
public
end;
...

implementation

uses TypInfo;

procedure TForm1.ActiveCtrlChange(Sender: TObject);
begin
if Assigned(GetPropInfo(FPrevFocusedCtrl.ClassInfo, 'Color')) then
SetOrdProp(FPrevFocusedCtrl, 'Color', FPrevColor);
if Assigned(GetPropInfo(Screen.ActiveControl.ClassType,'Color')) then
begin
FPrevColor:= TColor(GetOrdProp(Screen.ActiveControl,'Color'));
SetOrdProp(Screen.ActiveControl, 'Color', clGradientActiveCaption); // color a gusto...
end;
FPrevFocusedCtrl:= Screen.ActiveControl;
end;

procedure TForm1.WmAfterCreate(var Msg: TMessage);
begin
Screen.OnActiveControlChange := ActiveCtrlChange;
FPrevFocusedCtrl:= Screen.ActiveControl;
if Assigned(GetPropInfo(FPrevFocusedCtrl.ClassInfo,'Color')) then
FPrevColor:= TColor(GetOrdProp(Screen.ActiveControl,'Color'));
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
//...
PostMessage(Self.Handle, WM_AFTER_CREATE,0,0);
end;

...

procedure TForm1.FormDestroy(Sender: TObject);
begin
Screen.OnActiveControlChange := nil;
end;

De esta manera destacará tanto un Edit como un CheckBox, RadioButton, StringGrid, RichEdit,..., etc.

Saludos :)

nlsgarcia
20-11-2012, 03:37:42
shoulder,

Siguiendo la idea de ecfisa del uso de RTTI, revisa este código:

unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, Buttons, TypInfo, Grids;

type
TForm1 = class(TForm)
Edit1: TEdit;
Edit2: TEdit;
Edit3: TEdit;
Memo1: TMemo;
BitBtn1: TBitBtn;
BitBtn2: TBitBtn;
BitBtn3: TBitBtn;
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure ActiveControlChanged(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

// Evento de Control del Focus sobre el Form1 por medio de la Matriz de Controles y RTTI
procedure TForm1.ActiveControlChanged(Sender: TObject);
var
PropInfo: PPropInfo;
i: Integer;
begin
for i := 0 to ControlCount - 1 do
begin
if TWinControl(Controls[i]).Focused then
begin
PropInfo := GetPropInfo(Self.Controls[i].ClassInfo,'Color');
if Assigned(PropInfo) then
SetOrdProp(Controls[i], PropInfo, ord(clYellow));
end
else
begin
PropInfo := GetPropInfo(Self.Controls[i].ClassInfo,'Color');
if Assigned(PropInfo) then
SetOrdProp(Controls[i], PropInfo, ord(clWindow));
end;
end;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
// Activa el Evento de Control de Focus en el Form1
Screen.OnActiveControlChange := ActiveControlChanged;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
// Desactiva el Evento de Control de Focus en el Form1
Screen.OnActiveControlChange := nil;
end;

end.

El código anterior cambia el color de cualquier control que tenga el focus activo si y solo si este tiene implementada la propiedad color. Esto lo hace de forma genérica por medio de RTTI (Run-Time Type Information) y la propiedad OnActiveControlChange que permite definir un manejador de evento para controlar el cambio de focus en un form.

El código anterior se encuentra implementado en el siguiente link: http://terawiki.clubdelphi.com/Delphi/Ejemplos/?download=OnActiveControlChange+con+RTTI.rar

Espero sea útil :)

Nelson.

ecfisa
20-11-2012, 04:59:40
Hola nlsgarcia.

Se hace ineficiente recorrer todos los controles del form dentro del evento que se dispara cada vez que cambia el control activo, para así obtener quien tiene el foco. Ese dato lo podemos tomar de la propiedad Screen.ActiveControl, que dentro del evento OnActiveControlChange, ya tiene al nuevo portador del foco de entrada.

Basta con salvar previamente el control que lo poseía para restaurarlo al estado anterior y luego darle el color deseado al nuevo control activo. Que, si ocurre otro cambio de foco, pasará a ser el control que lo perdió y así, cíclica y sucesivamente con cada uno de ellos.

Saludos. :)

nlsgarcia
20-11-2012, 05:23:36
ecfisa,

Entiendo tu punto, pero en el ejemplo propuesto el procesamiento es tan rápido y el código tan compacto que creo que es válido en este caso particular. Es un compromiso entre eficiencia relativa y simplicidad de código.

Gracias por tus comentarios, los tendré muy en cuenta :)

Nelson.

shoulder
20-11-2012, 19:30:28
Gracias a Todos!!!.