【问题标题】:What event fires every time a TStringGrid's selected location is changed?每次更改 TStringGrid 的选定位置时会触发什么事件?
【发布时间】:2014-01-23 19:38:37
【问题描述】:

我有一个字符串网格,它显示了一堆文件和有关这些文件的信息。有关当前所选项目的更多信息显示在单独的面板中。所以,我想知道所选行何时更改以更新面板。 OnSelectCell 不好,因为它在选择实际移动到新位置之前触发。这就是我的意思:

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

【问题讨论】:

  • “在实际移动选择之前”是什么意思? RowCol 已更改。
  • 我希望您可以将消息(POST 而非发送)发送到您的网格,某种您自己的 WM_USER+delta。我希望在处理所有其他消息并且您将获得您自己的自定义消息的那一刻,包括更改属性和绘画在内的所有工作都已经完成。实际上 PostMessage 是最典型的 WinGDI/VCL 卸载某些任务的方式。 // 但是,我的直觉表明您只是尝试使用错误的工具。整体描述问题,您试图通过延迟事件处理程序解决什么?也许你可以用更多类似 VCL 的方式来解决它?
  • @Arioch'The-请查看更新后的问题。

标签: delphi


【解决方案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;

【讨论】:

  • @Altar 你认为或者你做过测试?
  • @Arioch - 别担心,OP 并不羞于稍后将接受转换为他自己的答案。
  • @Arioch'The-我现在在我的电脑前,我可以测试它。这看起来不错的样子。无论如何,这是最好的答案:)
猜你喜欢
  • 2010-09-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-12-28
  • 2013-07-16
  • 2023-04-05
  • 1970-01-01
相关资源
最近更新 更多