如何通过tab
键或鼠标click
检测用户是否输入了组件?
更新1
事实上,约有一个TVirtualStringTree
,它取决于重点,它打开一个专注于一个或另一个列的自定义编辑器。
更新2
检查下面的代码。
procedure TForm1.Tree1Click(Sender: TObject);
var
Tree: TVirtualStringTree;
Click: THitInfo;
HitNode: PVirtualNode;
HitColumn: TColumnIndex;
col: Integer;
begin
Tree:= Sender as TVirtualStringTree;
Tree.GetHitTestInfoAt(Mouse.CursorPos.X-Tree.ClientOrigin.X, Mouse.CursorPos.Y-Tree.ClientOrigin.Y, True, Click);
HitNode:= Click.HitNode;
if not Assigned(Click.HitNode) and Assigned(Tree.FocusedNode) then
HitNode:= Tree.FocusedNode;
HitColumn:= Click.HitColumn;
//get first visible and editable column
if (HitColumn <= NoColumn) or
((HitColumn > NoColumn) and
(not (coVisible in Tree.Header.Columns.Items[HitColumn].Options) or
not (coEditable in Tree.Header.Columns.Items[HitColumn].Options))) then
if Tree.Header.Columns.Count > 0 then
for col := 0 to Tree.Header.Columns.Count - 1 do
if (coVisible in Tree.Header.Columns.Items[col].Options) and
(coEditable in Tree.Header.Columns.Items[col].Options) then
begin
HitColumn:= col;
Break;
end;
if Assigned(HitNode) and (HitColumn > NoColumn) then
{if (Tree.IsEditing and (HitNode <> Tree.FocusedNode)) or
((not Tree.IsEditing) and (HitNode = Tree.FocusedNode)) then}
Tree.EditNode(HitNode,HitColumn);
end;
procedure TForm1.Tree1Enter(Sender: TObject);
var
Tree: TVirtualStringTree;
Click: THitInfo;
HitNode: PVirtualNode;
HitColumn: TColumnIndex;
col: Integer;
begin
Tree:= Sender as TVirtualStringTree;
HitNode:= Tree.FocusedNode;
if not Assigned(Tree.FocusedNode) then
HitNode:= Tree.GetFirstVisible;
HitColumn:= NoColumn;
//get first visible and editable column
if Tree.Header.Columns.Count > 0 then
for col := 0 to Tree.Header.Columns.Count - 1 do
if (coVisible in Tree.Header.Columns.Items[col].Options) and
(coEditable in Tree.Header.Columns.Items[col].Options) then
begin
HitColumn:= col;
Break;
end;
if Assigned(HitNode) and (HitColumn > NoColumn) then
Tree.EditNode(HitNode,HitColumn);
end;
我想做的是:
Tab
键或click
如果我点击组件,OnEnter
会先触发OnClick
,所以问题就是编辑节点会被触发2次。
答案 0 :(得分:2)
为了知道是否通过使用 tab 或通过鼠标点击获得了焦点,你需要做一些侦探工作。
procedure TBaseVirtualTree.WMKeyUp(var Message: TWMKeyUp); begin inherited; case Message.CharCode of VK_SPACE: .... [snip] .... VK_TAB: //This method causes a flurry of event handlers to be called. EnsureNodeFocused(); end; end;
OnFocusChanged
和OnFocusChanging
事件外,VTV还有两个重点更改事件:OnEnter
和OnExit
。
我不知道哪个最适合你的需求,你必须进行实验。 让我们假设使用鼠标总是获得焦点,除非我们能够证明它是使用 tab 获得的。这是一个不稳定的假设,但没关系。
首先,我们使用内插器来覆盖WMKeyUp
消息处理程序
WMKeyUp
是私有的,but luckily message handlers can always be overriden, even if they are private。
插播者
您可以使用a trick called an interposer重新定义VST以满足我们的需求
由于采用了范围规则,“改进的”TVST取代了默认的VST。这不会干扰流式传输或表单创建或任何事情。它只是有效。
type
TVirtualStringTree = class(VirtualTrees.TVirtualStringTree)
private
FTabPressed: boolean;
protected
procedure WMKeyUp(var Message: TWMKeyUp); message WM_KEYUP;
property TabPressed: boolean read FTabPressed;
end;
TForm56 = class(TForm)
VirtualStringTree1: TVirtualStringTree;
....
procedure TVirtualStringTree.WMKeyUp(var Message: TWMKeyUp);
begin
case Message.CharCode of
VK_TAB: FTabPressed:= true;
else FTabPressed:= false;
end; {case}
inherited;
FTabPressed:= false;
end;
焦点事件处理程序
使用其中一个两个三个事件处理程序。
//use the standard onEnter....
procedure TForm56.VirtualStringTree1Enter(Sender: TObject);
begin
if VirtualStringTree1.TabPressed then .....
else ....
end;
//... or use this event, or...
procedure TForm56.VirtualStringTree1FocusChanged(Sender: TBaseVirtualTree;
Node: PVirtualNode; Column: TColumnIndex);
begin
if VirtualStringTree1.TabPressed then .....
else ....
end;
//.... this event if you want to mess with the focus.
procedure TForm56.VirtualStringTree1FocusChanging(Sender: TBaseVirtualTree;
OldNode, NewNode: PVirtualNode; OldColumn, NewColumn: TColumnIndex;
var Allowed: Boolean);
begin
Allowed:= VirtualStringTree1.TabPressed; //just a silly example.
end;
答案 1 :(得分:1)
因为通过点击实现的焦点总是会在onEnter事件之前生成一个mousedown事件,你可以在mousedown中设置一个事件'gMousedown':= true然后在OnEnter事件中你可以检查是否已经mousedown。不要忘记在onMouseUp事件中将gMousedown重置为false。