2011-11-30 68 views
2

我在表单上有一个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?我已经上下了TGridPanelTControlCollection类代码,并且找不到任何能够从鼠标坐标中获得列或行值的内容。它们似乎也不是使用OnDblClick()以外的相关事件。

任何帮助将不胜感激。

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

回答

3
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; 
+0

我希望能有一个更有效的方式,但是这似乎是一种可靠的方法。顺便说一句,Windows有一个名为'PtInRect()'的API,它可以完成你的'PointInRect()'函数的功能,但是参数的顺序是相反的。 –

+0

更正:您的PointInRect()和Windows的PtInRect()之间的区别在于Windows版本排除了右侧和底部边缘。 –

+0

我知道存在像PointInRect这样的东西。因为我曾经见过它,但我找不到它。谢谢杰里让我想起这个功能 – Ravaut123

0

这是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; 
相关问题