Получение ячейки, нажатой в TGridPanel
У меня есть 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()
.
EDIT: изменил переменную Result на MyControl, чтобы избежать путаницы.
2 ответа:
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 (должна быть намного быстрее для больших сеток). Эта функция возвращает расположение сетки X/Y в точке T. Если пользователь нажал на допустимый столбец, но не на допустимую строку, то информация о допустимом столбце все равно возвращается, и то же самое относится к строкам. Таким образом, это не "все или ничего" (допустимая ячейка или недопустимая ячейка). Эта функция предполагает, что сетка "регулярна" (каждый столбец имеет ту же высоту строки, что и первый столбец, также каждая строка имеет ту же высоту). ширина столбца как первой строки). Если сетка не является регулярной, то решение 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;