2011-11-30 60 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; 
相關問題