在 TGridPanel 中单击单元格
-
26-10-2019 - |
题
我有一个 TGridPanel
在窗体上并希望将控件添加到单击的特定“单元格”。
我很容易明白这一点:
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;
我可能不需要 if ControlAtPos(P) = nil then
行,但我想确保我没有在已有控件的单元格中插入控件。
所以...我应该使用什么代码来获取 InsCol 和 InsRow?我曾上下过 TGridPanel
和 TControlCollection
类代码,找不到任何可以从鼠标坐标为我提供列或行值的内容。他们似乎也不是一个可以使用的相关事件 OnDblClick()
.
任何帮助将不胜感激。
编辑:将变量 Result 更改为 MyControl 以避免混淆。
解决方案
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;
其他提示
这是 Ravaut123 方法的优化(对于较大的网格来说应该更快)。该函数将返回 TPoint 中的 X/Y 网格位置。如果用户点击了有效列而不是有效行,那么仍然返回有效列信息,行也是如此。所以它不是“全有或全无”(有效单元格或无效单元格)。此函数假设网格是“规则的”(每列具有与第一列相同的行高,同样每行具有与第一行相同的列宽)。如果网格不规则,那么 Ravaut123 的解决方案是更好的选择。
// 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;
不隶属于 StackOverflow