Обнаружение одиночного или множественного выбора в Delphi TStringGrid - PullRequest
5 голосов
/ 17 мая 2011

Это продолжение моего предыдущего вопроса Delphi TStringGrid multi select, определяющий выбранные строки относительно решеток Delphi String.Это другой вопрос.

Я присматривался к событию ONSelectCell TSelectCellEvent = процедура (Отправитель: TObject; ACol, ARow: Longint; var CanSelect: Boolean) объекта;

Я заметилчто свойства TStringGrid.Selection.Top, Bottom не обязательно являются точными (в пределах самого события).По сути, если кто-то переходит от выбора нескольких строк к одной строке, свойства selection. * Не обновляются, тогда как если выбирается несколько строк, они обновляются.

Параметр ARow обновляется независимо от того, выбрана ли одна или несколько строк, но это поможет мне, только если я смогу определить, что была выбрана одна и только одна строка.

Например, если выбрана только одна строка, то используйте параметр Arow, если более одной строки, то используйте свойства Selection. *, Чтобы определить, какие строки в настоящий момент выбраны.

Должен быть более простой способ ....

Спасибо!

Ответы [ 4 ]

4 голосов
/ 18 мая 2011

Я думаю, что часть проблемы в используемой терминологии.Пока вы полностью не поймете, что происходит, может показаться странным, что 'select' используется для обозначения 'highlight' и 'focus' .В этом конкретном случае должно быть различие между ними.

Прежде чем я продолжу, я хотел бы, чтобы вы помнили, что сфокусированная клетка также может быть (и есть) выделено , но выделенная ячейка не обязательно является сфокусированной.

Теперь событие OnSelectCell связано с фокусировкой .Обработчик срабатывает при щелчке ячейки или при попытке навигации по ней с помощью клавиш навигации.Короче говоря, обработчик вызывается при попытке сфокусировать ячейку.Вы можете запретить фокусировку ячейки, сбросив параметр CanSelect (что, опять же, означает, по существу, CanFocus , потому что ячейка может быть выбрана, т. Е. Выделена, без выделения, и выне может контролировать это с помощью OnSelectCell).

Опция goRangeSelect и свойство TDrawGrid.Selection, с другой стороны, связаны с выбором в качестве выделения .Первый позволяет вам (пользователю) выделить более чем одну ячейку, а второй указывает на диапазон этих ячеек выделен .

Теперь к моей основной точке,После вызова рассматриваемого обработчика Selection является никогда точным, т. Е. Не коррелируется с параметрами ACol & ARow, которые передаются обработчику.Selection содержит диапазон ячеек, которые были выделены непосредственно перед вызовом обработчика, и он никогда не изменяется сам по себе в обработчике .Будь то одна или несколько ячеек, Selection остается одинаковым до тех пор, пока обработчик не выйдет.И когда это происходит (обработчик завершает работу), Selection изменяется (и результат зависит, между прочим, сброс CanSelect или нет, кстати).

Таким образом, в заключение вы не можете использоватьOnSelectCell для определения фактического Selection как результата самого последнего действия пользователя.Вместо этого я бы предложил последовать совету @ Sam и использовать событие OnMouseUp*.Это также позволяет вам контролировать выбор: вы можете исправить окончательный диапазон, если считаете, что пользователь выбрал «слишком много».В последнем случае я бы, вероятно, подумал бы об использовании OnMouseMove вместо этого, так как он позволяет вам более плавно реагировать, исправляя диапазон «на лету».

OnDrawCell тоже выглядит хорошо, пока вынужно просто определить выбор.


* После вашего комментария я должен добавить, что вам также придется использовать OnKeyUp для обработкивыбор сделан с клавиатуры.

0 голосов
/ 27 августа 2013

StringGrid1.Selection.Top to StringGrid1.Selection.Bottom - это то, что отлично сработало для меня, поскольку я использую событие onkeypress для выбора / отмены выбора.

0 голосов
/ 18 мая 2011

Мне удалось решить это самостоятельно, я в конечном итоге использовал событие 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;


Спасибо тем, кто откликнулся !!

0 голосов
/ 17 мая 2011
for RowIndex := StringGrid1.Selection.Top to StringGrid1.Selection.Bottom do
begin
  DoSomethingWithRow(RowIndex);
end;

Да, я понимаю вашу точку зрения.Кажется, свойство Selection обновляется после события OnSelectCell, поэтому внутри события у вас есть только старые значения (т. Е. До события select).Ответ заключается в том, чтобы переместить приведенный выше код в событие OnMouseUp в stringgrid.Вроде нормально работает.

...