Pregunta

tengo un TGridPanel en un formulario y desea agregar un control a una "celda" específica en la que se hace clic.

Puedo obtener el punto con suficiente facilidad:

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;

Probablemente no necesito el if ControlAtPos(P) = nil then Línea, pero quiero asegurarme de que no estoy insertando un control en una celda que ya tenga uno.

Entonces ... ¿qué código utilizo para obtener Inscol e Insrow? He estado arriba y abajo del TGridPanel y TControlCollection Código de clase y no puede encontrar nada que me dé una columna o valor de fila de las coordenadas del mouse. Tampoco parece ser un evento relevante para usar que no sea OnDblClick().

Cualquier ayuda sería muy apreciada.

Editar: cambiado de resultado variable a MyControl para evitar confusiones.

¿Fue útil?

Solución

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;

Otros consejos

Aquí hay una optimización del enfoque de Ravaut123 (debería ser mucho más rápido para cuadrículas más grandes). Esta función devolverá la ubicación de la cuadrícula x/y en un punto t. Si el usuario hizo clic en una columna válida pero no en una fila válida, entonces la información de columna válida todavía se devuelve y lo mismo ocurre con las filas. Por lo tanto, no es "todo o nada" (celda válida o celda no válida). Esta función supone que la cuadrícula es "regular" (cada columna tiene la misma altura de la fila que la primera columna, al igual que cada fila tiene el mismo ancho de la columna que la primera fila). Si la cuadrícula no es regular, entonces la solución de Ravaut123 es la mejor opción.

// 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;
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top