在鼠标点击和键盘节点选择上执行代码

当用户点击节点时,我有虚拟TreeView,并使用OnClick来执行代码。 为了在用户使用键盘从一个节点移动到另一个节点时执行相同的代码,我使用OnFocusChanged。 在OnFocusChanged中,我调用了OnClick,所以它总是执行相同的代码,当然。

所以,当一个节点被选中并且用户点击另一个节点时,这两个事件都被称为OnClick和OnFocusChanges ...并且由于OnFocusChanged调用OnClick,我使用一个小技巧来避免OnClick的双重执行。 我使用标志来设置忽略OnClick的第二个调用。

这里是代码 - OnFocusChanged

procedure TForm1.VTVFocusChanged(Sender: TBaseVirtualTree;
  Node: PVirtualNode; Column: TColumnIndex);
begin
  gTVFocusHasJustChanged_SkipClickEvent := false; // enable executing  OnClick code
  VTVClick(Sender);
  gTVFocusHasJustChanged_SkipClickEvent := True; // disable executing OnClick code
end;

这里是OnClick

procedure TForm1.VTVClick(Sender: TObject);
var
  Data: ^rTreeData;
begin
  // skip second OnClick call!
  if gTVFocusHasJustChanged_SkipClickEvent then
  begin
    gTVFocusHasJustChanged_SkipClickEvent := false;
    Exit;
  end;

  ... // code to be executed when node selected

end;

这可按预期工作,无论是用户点击节点还是随键盘移动。

但是,有没有更好的方法来做到这一点,更容易维护或更有意义?


编辑:

我想我需要添加更多信息。 用户选择节点时只执行特定的代码。 无论是鼠标,键盘,如果它被聚焦或不是,之前已经选择了一个节点并且现在选择了新节点......基本上在任何和所有情况下,只需要执行特定的代码。 我选择了使用OnClick方法的地方,我可以使用另一个从OnClick调用的函数,但实际上它是相同的。 我不会根据发生的情况执行不同的代码,要么是点击,要么是键盘移动......都一样,代码之间没有区别。 我希望这可以更好地理解发生了什么,并提供更多信息,我需要帮助。

编辑#2:

我的进度更新:我开始将我的所有代码从OnClick移动到单独的过程中,这样可以在选择节点(鼠标单击或键盘)或其他情况下提高可维护性和更轻松的执行。 下面的答案和评论让我推动了正确的方向,即OnClick不是正确的地方,不应该执行基于OnClick事件的代码。


主要思想是为每个VirtualTree使用全局选定的节点。

代码如下:

  TForm1 = class(TForm)
    ..........
  private
    fselectedVTNode : PVirtualNode;   // used as global selected node for VTV
    ..........
  public
    ..........
  end;


//========== Event for VTV.OnFocusChanged ===============
procedure TForm1.VTVFocusChanged(Sender: TBaseVirtualTree;
  Node: PVirtualNode; Column: TColumnIndex);
var
  Data: ^rTreeData;
begin
  if (fselectedVTNode <> Node) then begin
    fselectedVTNode := Node;

    // ....... code to be executed when node selected

  end;
end;

//========== Event for VTV.OnFreeNode ===============
procedure TForm1.VTVFreeNode(Sender: TBaseVirtualTree; Node: PVirtualNode);
begin
  if fselectedVTNode = Node then
    fselectedVTNode := nil; 

  // .......code to be executed when node freed
end;

//========== Event for VTV.OnEnter ===============
procedure TForm1.VTVEnter(Sender: TObject);
var
  VT:TBaseVirtualTree;
begin
  fselectedVTNode := nil; 
  VT:=TBaseVirtualTree(Sender); 
  VTVFocusChanged(VT, VT.FocusedNode, VT.FocusedColumn);
end;

Saludos amigos,en lazarus esasí:

    TForm2 = class(TForm)
        ..........
      private
        fselectedVTNode : PVirtualNode;   // used as global selected node for VTV
        ..........
      public
        ..........
      End;


    // ESTE ES EL CODE PRINCIPAL PARA OBTENER LOS DATOS NECESARIOS
    procedure TForm2.VSTFocusChanged(Sender: TBaseVirtualTree; 
Node: PVirtualNode; Column: TColumnIndex);
        var
          Data: Pdata;
        begin
        //VST.Refresh;
          if (fselectedVTNode <> Node) then begin
            fselectedVTNode := Node;

            // ....... code to be executed when node selected
            Data := VST.GetNodeData(Node);
            //ShowMessage(Data^.Fnotes);  // funciona
            Memo_comentarios.Text:=Data^.Fnotes;  // funciona
          end;
        end; 


        procedure TForm2.VSTFreeNode(Sender: TBaseVirtualTree; Node: PVirtualNode);
        begin
              if fselectedVTNode = Node then
                fselectedVTNode := nil;

              // .......code to be executed when node freed
        end;

        procedure TForm2.VSTEnter(Sender: TObject);
          var
            VT:TBaseVirtualTree;
         begin
            fselectedVTNode := nil;
            VT:=TBaseVirtualTree(Sender);
            VSTFocusChanged(VT, VT.FocusedNode, VT.FocusedColumn);

         end;

Saludos :)

链接地址: http://www.djcxy.com/p/35003.html

上一篇: Execute code on Mouse Click and Keyboard node selection

下一篇: Delphi what is the Ideal method to populate a VirtualStringTree?