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上一篇: 是否有可能在虚拟字符串树中有多个标题行?
下一篇: 在鼠标点击和键盘节点选择上执行代码