gpt4 book ai didi

delphi - 检测用户是否通过选项卡或单击获得组件的焦点

转载 作者:行者123 更新时间:2023-12-03 15:53:55 26 4
gpt4 key购买 nike

如何检测用户是通过tab键还是通过鼠标点击进入组件?

更新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 键输入或
  • ,则编辑焦点节点的第一列
  • 鼠标输入点击即可编辑对应的点击列

如果我点击组件,首先触发OnEnter,然后触发OnClick,所以问题是编辑节点被触发了2次。

最佳答案

为了知道焦点是通过使用 tab 还是通过鼠标单击获得的,您需要做一些侦探工作。

  1. 这是确保按下 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;
  • 除了标准的 OnEnterOnExit 之外,VTV 还有两个用于焦点更改的事件:OnFocusChangedOnFocusChanging事件。
    我不知道哪一个最适合您的需求,您必须进行试验。
  • 假设焦点始终是使用鼠标获得的,除非我们可以证明它是使用 tab 获得的。这是一个有点不稳定的假设,但没关系。

    首先,我们使用插入器来覆盖 WMKeyUp 消息处理程序。
    WMKeyUp 是私有(private)的,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;

    关于delphi - 检测用户是否通过选项卡或单击获得组件的焦点,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39118427/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com