Friday, June 16, 2006

Selezionare con il mouse: DrawFocusRect

Ecco come disegnare un rettangolo che permette di selezionare un area della form:

Servono 2 variabili boolean per indicare l'avvio della operazione di disegno ed il fatto che si sia effettivamente disegnato un rettangolo (per evitare effetti indesidetati).
Gli eventi da gestire sono il mousedown (che consente di attivare la procedura e per indicare il punto di inizio del disegno), il mousemouve (che cancella il precedente rettangolo e disegna il nuovo) ed il mouseup che disattiva l'operazione.

Ecco il codice inserito in Delphi:

type
TForm2 = class(TForm)
procedure FormMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure FormMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
procedure FormMouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
private { Private declarations }
disegnato:boolean;
start:boolean;
rS:TRect;
xS,yS:Integer;

public { Public declarations }
end;

var Form2: TForm2;

implementation
{$R *.dfm}
procedure TForm2.FormMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);

begin
start:=true;
xS:=X;
yS:=Y;
rS.Left:=X;
rS.Top:=Y;
rS.Right:=X;
rS.Bottom:=Y;
disegnato:=false;
end;

procedure TForm2.FormMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
var tmp:integer;
begin
caption:=Format('(%d,%d) x (%d,%d)',[xS,yS,X,Y]);
if start then
begin
//cancello il vecchio
if disegnato then canvas.DrawFocusRect(rS);

// verifico se sono a sinistra o a destra del punto iniziale xS
if xS>X then
begin
rS.Right:=xS;
rs.Left:=X
End
else
begin
rS.Right:=X;
rS.Left:=xS;
end;

//verifico se sono sopra o sotto del punto iniziale yS

if yS>Y then
begin
rS.Bottom:=yS;
rS.Top:=Y
end
else
begin
rS.Bottom:=Y;
rS.Top:=yS;
end;

//disegno il rettangolo
canvas.DrawFocusRect(rS);
disegnato:=true;
end; //if Start
end;

procedure TForm2.FormMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
start:=false;
//forza il repaint e la cancellazione dell'ultimo rettangolo
invalidate;
end;

La cosa più complicata è la gestione dei vertici del rettangolo: un rettangolo con un vertice finale sopra o a sinistra di quello iniziale non viene disegnato. Per questo bisogna invertire i vertici.

No comments: