【问题标题】:Getting the cell clicked on in a TGridPanel在 TGridPanel 中单击单元格
【发布时间】:2011-11-30 14:22:22
【问题描述】:

我在表单上有一个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?我一直在 TGridPanelTControlCollection 类代码上下移动,找不到任何可以从鼠标坐标中给我列或行值的东西。除了OnDblClick()之外,它们似乎也不是可以使用的相关事件。

任何帮助将不胜感激。

编辑:将变量 Result 更改为 MyControl 以避免混淆。

【问题讨论】:

    标签: delphi delphi-2007 tgridpanel


    【解决方案1】:
    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;
    

    【讨论】:

    • 我希望有一种更有效的方法,但这似乎是一种可靠的方法。顺便说一句,Windows 有一个名为 PtInRect() 的 API,它执行您的 PointInRect() 函数所做的事情,但参数顺序相反。
    • 更正:您的 PointInRect() 和 Windows 的 PtInRect() 的区别在于 Windows 版本不包括右边缘和下边缘。
    • 我知道存在类似 PointInRect 的东西。因为我见过它,但我找不到它。感谢 Jerry 提醒我这个功能
    【解决方案2】:

    这是对 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;
    

    【讨论】:

      猜你喜欢
      • 2021-12-16
      • 1970-01-01
      • 2014-12-13
      • 1970-01-01
      • 1970-01-01
      • 2016-04-21
      • 2011-12-07
      • 2021-12-05
      • 1970-01-01
      相关资源
      最近更新 更多