2014-01-23 2 views
1

У меня есть stringgrid, который показывает кучу файлов и информацию об этих файлах. Больше информации о текущем выбранном элементе отображается на отдельной панели. Поэтому я хочу знать, когда выбранная строка изменяется для обновления панели. OnSelectCell не очень хорош, потому что он запускается до того, как выбор действительно перемещен в новое место. Это то, что я имею в виду:Какое событие срабатывает при каждом изменении выбранного местоположения TStringGrid?

function TStrGrd.SelectCell(ACol, ARow: Longint): Boolean; {override} 
begin 
Result:= inherited SelectCell(ACol, ARow); 
Mesage('Cur row: '+ IntToStr(row)); 
Mesage('New row: '+ IntToStr(ARow)); 

{ My own event } 
if Assigned(FCursorChanged) 
then FCursorChanged(Self);   <-------- user will see the old row 
end; 

Если последняя строка выбрана и я нажимаю на первую строку, я буду получать эти сообщения:

Cur row: 999 
New row: 0 

Это будет работать, если я создаю свой собственный обработчик события и передайте ему строку, в которой выбор будет перемещен. Он должен работать на 100%, но я не очень доволен этим, потому что пользователю придется писать дополнительный код в обработчике событий.

Я мог бы перехватить все пользовательские взаимодействия (мышь/клавиша) и все изменения выбора я делаю программно, но для этого требуется довольно много кода. Должен быть более элегантный способ.

  1. Этот вопрос похож на What event fires every time a TDbGrid's selected location is changed?, но не дублируется. Ответ на этот вопрос: «Использовать OnDataChange», но TStringGrid не имеет этого события.
  2. @Andriy M предлагает здесь почему OnSelectCell не будет работать: Detecting single vs multiple selections in Delphi TStringGrid
+0

Что значит «до того, как выбор действительно перемещен»? «Строка» и «Кол» изменились. –

+2

Я ожидаю, что вы можете PostMessage (POST not SEND) в свою сетку, какой-то свой собственный WM_USER + delta. Я ожидаю, что к моменту, когда будут обработаны все другие сообщения, и вы получите это собственное сообщение - вся работа, включая изменение свойств и рисования, уже будет выполнена. Фактически PostMessage является наиболее типичным для WinGDI/VCL способом разгрузить некоторую задачу. // Однако мои чувства кишки говорят о том, что вы просто пытаетесь использовать неправильный инструмент. Опишите проблему как целое, что происходит, которую вы пытаетесь решить с помощью обработчика событий с задержкой? может быть, вы можете решить это более VCL-способами? –

+0

@ Arioch'The-См. Обновленный Вопрос. – Ampere

ответ

1

не ответ. Просто опубликуйте его, чтобы иметь многострочный текст.

Я думаю, что вы имели в виду «чтобы обновить панель», а не «до» :-)

Тем не менее я не могу получить то, что не так с параметром ROW. Вы говорите: «пользователь должен будет написать дополнительный код в обработчике событий». но на самом деле все наоборот.

procedure ParamEvent(const grid: TStringGrid; const Row: integer); 
begin 
    ..do something with grid.Rows[Row] to update the panel 

// ...and if I need, I also already know which Row was selected beforehand! 
end; 

procedure ParamLessEvent(); 
var grid: TStringGrid; Row: integer; // <<<<< EXTRA "coding" here 
begin 
    grid := ..... some way to get the needed grid  // <<<<< EXTRA coding here 
    Row := grid.Row;  // <<<<< EXTRA coding here 

    ...do something with grid.Rows[Row] to update the panel 

// ...and if I would want to know which file just was DE-selected, 
// I would have to code persisting of previous selected row 
// number somewhere outside the grid 
end; 

сейчас, действительно, почему бы не использовать PostMessage?

const WM_Grid_Event = WM_USER + 123; // I hope it is correct? I always mix wm_user and wm_app 
type TMyGrid = class (TStringGrid) 
    .... 
    private 
     procedure DelayedEvent(var MSG: TMessage); message WM_Grid_Event; 
    end; 

function TMyGrid.SelectCell(ACol, ARow: Longint): Boolean; {override} 
begin 
Result:= inherited SelectCell(ACol, ARow); 
Mesage('Cur row: '+ IntToStr(row)); 
Mesage('New row: '+ IntToStr(ARow)); 

PostMessage(Self.Handle, WM_Grid_Event, ARow, 0); 
end; 

procedure DelayedEvent(var MSG: TMessage); 
begin 
    { My own event } 
    if not Assigned(FCursorChanged) then exit; 

    if Self.Row = MSG.WParam (* changed already? *) then begin 
    FCursorChanged(Self); 
    end else begin 
    if MSG.LParam < 5 then // protection from infinite loop. OTOH I hope we would not EVER got here 
     PostMessage(Self.Handle, WM_Grid_Event, MSG.WParam, 1 + MSG.LParam); 
    end; 
end; 
+0

@Altar вы думаете или вы протестировали? –

+0

@Arioch - Не волнуйтесь, OP не стесняется о том, чтобы позже переключить Accept на свой собственный ответ. –

+0

@ Arioch'The-Я нахожусь на своем компьютере, и я могу проверить его. Выглядит хорошо. Во всяком случае, это лучший ответ вокруг :) – Ampere

Смежные вопросы