Execute code on Mouse Click and Keyboard node selection

I have Virtual Treeview and I use OnClick to execute code, when user clicks on node. In order for the same code is executed also when user uses keyboard to move from node to node, I use OnFocusChanged. In OnFocusChanged I call OnClick, so it is always same code executed, of course.

So, when a node is selected and user clicks on another node, both events are called OnClick and OnFocusChanges... and since OnFocusChanged calls OnClick, I use a little trick to avoid double executino of OnClick. I use flag to set to ignore 2nd call of OnClick.

Here is the code - 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;

And here is 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;

This works as expected, either user clicks on node or moves with keyboard.

BUT, Is there better way to do this, easier to maintain or just makes more sense?


EDIT:

I think I need to add a little more info. Only specific code is executed when user selects node. Either with mouse, keyboard, if it was focused or not, already selected one node before and now selecting new one... basically in any and all occurrences, only specific code needs to be executed. I chose to use OnClick method where I have this code, I could use another function that gets called from OnClick, but that is practically the same. I do not execute different code based on condition of what happened, either it was a click, it was a keyboard move... all the same, no distinction between where the code was fired from. I hope this makes more sense of what is going on and provides more info where I need help.

EDIT #2:

Update on my progress: I started moving all my code from OnClick into separate procedures, which improves maintainability and easier execution while node is selected (Mouse click or with keyboard) or under other circumstances. The answer below and comments gave me nudge into right direction that OnClick is not the right place where code that is not based on OnClick event should be executed.


The main idea is use global selected Node for every VirtualTree.

Here is the code :

  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 es así:

    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/35004.html

上一篇: 是否有可能在虚拟字符串树中有多个标题行?

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