2011-05-17 54 views
5

這是關於Delphi字符串網格的我之前問題Delphi TStringGrid multi select, determining selected rows的後續。這是一個不同的問題。在Delphi中檢測單個vs多個選擇TStringGrid

我在仔細查看ONSelectCell事件 對象的TSelectCellEvent = procedure(Sender:TObject; ACol,ARow:Longint; var CanSelect:Boolean);

我注意到TStringGrid.Selection.Top,Bottom屬性不一定準確(在事件本身內)。基本上,如果有人從選擇多行到只有一行,選擇。*屬性不會得到更新,而如果選擇多行,它們會。

不管是否選擇了一行或多行,ARow參數都會得到更新,但是這隻會幫助我確定是否只有一行被選中。例如,如果只選擇了一行,則使用Arow參數,如果多於一行,則使用Selection。*屬性確定當前選中的行。

必須有一個更簡單的方法....

謝謝!

+0

我不知道你在問什麼。 「必須有一個更簡單的方法」一個問題? – 2011-05-17 02:39:23

+1

...必須有一種更簡單的方法來知道在onSelectCell事件中選擇了哪些行。 – sse 2011-05-17 13:26:16

+1

@sse - 你是如何解決這個問題的? – Ampere 2014-01-23 20:08:29

回答

0
for RowIndex := StringGrid1.Selection.Top to StringGrid1.Selection.Bottom do 
begin 
    DoSomethingWithRow(RowIndex); 
end; 

是的,我明白了你的觀點。看來Selection屬性在 OnSelectCell事件後更新,所以在事件中你只有舊的值(即在select事件之前)。答案就是將上面的代碼移動到stringgrid的OnMouseUp事件中。它似乎工作正常。

+1

謝謝,這是一個好主意,不幸的是,不能保證通過鼠標選擇細胞。我的另一個想法是跟蹤選擇。*在onDrawCell事件中,它總是準確的,但我不喜歡這個,因爲性能的原因(並且因爲它似乎kludgey)。其他想法? – sse 2011-05-17 04:47:10

+1

ps,我不介意降低另一個組件,如果我可以得到可能有所幫助的受保護屬性。接下來我將深入研究TStringGrid源代碼。 – sse 2011-05-17 04:49:46

0

我能夠自己解決這個問題,我使用OnDrawCell事件與onSelectCell事件結合 - 我認爲這會變得一團糟,但事實並非如此糟糕。

下面是我遇到同樣問題的其他人的解決方案摘要。以下是兩個關鍵事實:

  1. TStringGrid.Selection屬性在OnDrawCell中總是精確的。
  2. TStringGrid.Selection屬性在OnSelectCell中是唯一準確的IFF多行已被選中。

 
public 
    previousHighlightCount : integer; //flag to ensure that the necessary code within the onDraw only gets called once per row selection(s). Initialize to '1' in onFormCreate. 


procedure Grid.OnDrawCell(...) 
begin 
... 
SelectionCount := Grid.Bottom - Grid.Top;** 
if ((SelectionCount = 1) AND (previousHighlightCount 1)) then 
begin                    
    GridUpdateEdits; //your routine to update the grid properly for one row.*  
    previousHighlightCount := 1; 
end 
else 
    previousHighlightCount := PrtEdtGrid.SelectionCount; //the routine for multiply selected rows is in the onSelectCell Event and onSeelctCell works for multiple selections. 
.... 
end; 


感謝那些誰回答!

4

我覺得,問題的一部分就是用到的術語。在您完全瞭解發生了什麼之前,必須弄清楚如何使用'選擇'來表示'突出顯示''重點'。在這種特殊情況下,應該區分兩者。

我開始之前,我想你要記住的是,集中細胞也可以(實際上是)強調,但突出顯示的單元不一定是重點之一。

現在,OnSelectCell事件與重點關注。單擊單元格時或當您嘗試通過導航鍵在其上方導航時會觸發該處理程序。簡而言之,當試圖對一個單元格進行焦點時調用處理程序。您可以通過重置CanSelect參數(這又意味着本質上意味着CanFocus,因爲單元格可以可以被選中,即突出顯示,而不被聚焦,並且不能用OnSelectCell控制)來禁止聚焦單元格。

goRangeSelect選項和TDrawGrid.Selection財產,而另一方面,有選擇做,因爲突出。前者允許你(用戶)突出顯示多於一個單元格,而後者指向那些單元格的範圍突出顯示

現在我的主要觀點。在調用相關處理程序時,Selection從不準確,即與傳遞給處理程序的參數不相關。 Selection包含在調用處理程序之前突出顯示的單元格範圍,它在處理程序內從不自行更改。無論是一個單元還是多個單元,Selection保持相同,直到處理程序退出。當發生變化(處理程序退出)時(並且結果取決於您是否重置CanSelect,順便說一下)。

所以,總而言之,你不能使用OnSelectCell來確定實際Selection作爲用戶的最近作用的結果。相反,我會建議遵循@Sam的建議,並使用OnMouseUp*事件。它還允許您控制選擇:如果您認爲用戶選擇了「太多」,則可以更正最終範圍。在後一種情況下,我可能會考慮使用OnMouseMove來代替,因爲它允許您通過「實時」更正範圍來更順利地做出響應。

OnDrawCell只要您只需要確定選擇就好了。


*按照您的意見,我必須補充一點,你還不得不僱用OnKeyUp爲好,處理好與鍵盤所做的選擇。

+0

好文章!感謝徹底的答覆。實際情況是,雖然選擇**是準確的。在OnSelectCell中,TStringGrid.Selection屬性是準確的(在高亮方面)IFF多行已突出顯示。使用onMouseUp不是一個好的解決方案,因爲可以在沒有鼠標的情況下選擇和/或突出顯示事物。我同意onDrawCell是一個好辦法,只要使用標誌來避免不必要的重新計算。我希望有一個onAfterHighlight事件。有關我如何將它添加到後代類的想法? – sse 2011-05-19 15:26:15

+0

我同意,有些情況下,傳遞給處理程序的座標指向已選擇的單元格。但是,這只是因爲該單元格是由以前的用戶操作選擇的,而不是由用戶現在正在執行的操作單元選擇的。在我的測試中'Selection'總是在*'OnSelectCell'後更新*(*從處理程序返回後*)。另一方面,關於'OnMouseUp'的說法是非常真實的,到目前爲止,除了'OnMouseUp'之外,我還不知道其他解決方案(解決方法),而不是定義'OnKeyUp'事件。這使整個方法更不優雅,這是一個恥辱。 – 2011-05-19 16:40:26

0

StringGrid1.Selection.Top到StringGrid1.Selection.Bottom 是完美的工作,因爲我使用onkeypress事件來選擇/取消選擇的東西。