Per la cella cliccato in un TGridPanel
-
26-10-2019 - |
Domanda
Ho un TGridPanel
su una forma e desiderio di aggiungere un controllo a una "cella" specifico che viene cliccato.
posso ottenere il punto abbastanza facilmente:
procedure TForm1.GridPanel1DblClick(Sender: TObject);
var
P : TPoint;
InsCol, InsRow : Integer;
begin
P := (Sender as TGridPanel).ScreenToClient(Mouse.CursorPos);
if (Sender as TGridPanel).ControlAtPos(P) = nil then
begin
InsCol := ???;
InsRow := ???;
(Sender as TGridPanel).ControlCollection.AddControl(MyControl, InsCol, InsRow)
end;
end;
Probabilmente non c'è bisogno della linea if ControlAtPos(P) = nil then
, ma voglio fare in modo che non sto inserendo un controllo in una cella che ha già uno in esso.
Quindi ... quale codice devo utilizzare per ottenere inscol e InsRow? Sono stato su e giù per il codice TGridPanel
e la classe TControlCollection
e non riesco a trovare nulla che mi darà un valore di colonna o riga da coordinate del mouse. Né la loro sembra essere un evento rilevante per uso diverso da quello OnDblClick()
.
Qualsiasi aiuto sarebbe molto apprezzato.
EDIT:. Cambiato Risultato variabile MyControl per evitare confusione
Soluzione
procedure TForm1.GridPanel1Click(Sender: TObject);
var
P: TPoint;
R: TRect;
InsCol, InsRow : Integer;
begin
P := (Sender as TGridPanel).ScreenToClient(Mouse.CursorPos);
for InsCol := 0 to GridPanel1.ColumnCollection.Count - 1 do
begin
for InsRow := 0 to GridPanel1.RowCollection.Count - 1 do
begin
R:= GridPanel1.CellRect[InsCol,InsRow];
if PointInRect(P,R) then
begin
ShowMessage (Format('InsCol = %s and InsRow = %s.',[IntToStr(InsCol), IntToStr(InsRow)]))
end;
end;
end;
end;
function TForm1.PointInRect(aPoint: TPoint; aRect: TRect): boolean;
begin
begin
Result:=(aPoint.X >= aRect.Left ) and
(aPoint.X < aRect.Right ) and
(aPoint.Y >= aRect.Top ) and
(aPoint.Y < aRect.Bottom);
end;
end;
Altri suggerimenti
Ecco un'ottimizzazione dell'approccio di Ravaut123 (dovrebbe essere molto più veloce per le griglie più grandi). Questa funzione restituisce la posizione Y X / griglia in una TPoint. Se l'utente fa clic su una colonna valida ma non una riga valida, quindi le informazioni di colonna valida è ancora tornato, e lo stesso vale per le righe. Quindi non è "tutto o niente" (cella valido o di cella non valido). Questa funzione presuppone la griglia è "normale" (ogni colonna ha la stessa altezza della riga della prima colonna, analogamente ogni riga ha la stessa larghezza della colonna come prima riga). Se la griglia non è regolare, allora la soluzione di Ravaut123 è la scelta migliore.
// APoint is a point in local coordinates for which you want to find the cell location.
function FindCellInGridPanel(AGridPanel: TGridPanel; const APoint: TPoint): TPoint;
var
ICol, IRow : Integer;
R : TRect;
begin
Result.X := -1;
Result.Y := -1;
for ICol := 0 to AGridPanel.ColumnCollection.Count - 1 do
begin
R := AGridPanel.CellRect[ICol, 0];
if (APoint.X >= R.Left) and (APoint.X <= R.Right) then
begin
Result.X := ICol;
Break;
end;
end;
for IRow := 0 to AGridPanel.RowCollection.Count - 1 do
begin
R := AGridPanel.CellRect[0, IRow];
if (APoint.Y >= R.Top) and (APoint.Y <= R.Bottom) then
begin
Result.Y := IRow;
Break;
end;
end;
end;