在鼠标单击和键盘节点选择上执行代码 - 虚拟树视图
Execute code on Mouse Click and Keyboard node selection - Virtual 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;
我有虚拟树视图,当用户单击节点时,我使用 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;