Delphi 每次TStringGrid';您选择的位置是否已更改?

Delphi 每次TStringGrid';您选择的位置是否已更改?,delphi,Delphi,我有一个stringgrid,它显示了一堆文件和关于这些文件的信息。有关当前选定项目的详细信息将显示在单独的面板中。因此,我想知道所选行何时更改以更新面板。OnSelectCell不好,因为它在选择实际移动到新位置之前触发。这就是我的意思: function TStrGrd.SelectCell(ACol, ARow: Longint): Boolean; {override} begin Result:= inherited SelectCell(ACol, ARow); Mesage

我有一个stringgrid,它显示了一堆文件和关于这些文件的信息。有关当前选定项目的详细信息将显示在单独的面板中。因此,我想知道所选行何时更改以更新面板。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;
如果我创建自己的事件处理程序,并将要移动选择的行传递给它,它就会起作用。它应该100%工作,但我对此不太满意,因为用户必须在该事件处理程序中编写一些额外的代码

我可以截取所有用户交互(鼠标/按键按下)和所有选择更改,但这需要大量代码。应该有更优雅的方式

  • 这个问题类似于但不是重复的。这个问题的答案是“使用OnDataChange”,但TStringGrid没有该事件
  • @安德烈M在这里提出了OnSelectCell不起作用的原因:

  • 没有答案。只是张贴它有多行文字

    我想你的意思是“更新面板”,而不是“大约”:-)

    但我仍然无法了解行参数的错误。您说“用户必须在该事件处理程序中编写一些额外的代码”,但实际上恰恰相反

    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;
    
    过程参数(常量网格:TStringGrid;常量行:整数);
    开始
    …对grid.Rows[Row]执行某些操作以更新面板
    //…如果我需要的话,我也已经事先知道选择了哪一行了!
    终止
    过程参数();
    
    var网格:TStringGrid;行:整数;//“在选定内容实际移动之前”是什么意思?
    已更改。我希望您可以将PostMessage(POST not SEND)发送到您的网格,某种形式的WM_用户+增量。我希望当所有其他消息都被处理时,你会得到你自己的自定义消息——所有的工作包括更改属性和绘制都已经完成了。实际上,PostMessage是WinGDI/VCL卸载某些任务的最典型方式然而,我的直觉告诉我,你只是在尝试使用错误的工具。描述整个问题,您试图通过延迟事件处理程序解决的问题是什么?也许你可以用更类似VCL的方式来解决它?@Arioch'The-请看更新的问题。@sale你认为或者你做过测试吗?@Arioch-别担心,OP不会羞于稍后将接受转换为他自己的答案。@Arioch'The-我现在在我的电脑前,我可以测试它。看起来不错。无论如何,最好的答案是:)
    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;
    
    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;