2016-08-24 69 views
3

我如何可以检测如果用户通过tab键或鼠标click进入组件得到一个组件的焦点检测?如果用户通过标签或通过点击

更新1

其实是关于其根据的方式是越来越集中在一个TVirtualStringTree,它打开一个自定义编辑器集中在一个或另一个列。

UPDATE 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键或
  • 进入,如果通过输入编辑相应hited列鼠标click

如果我点击组件,OnEnter首先触发和OnClick后,因此T他的问题是编辑节点被触发2次。

+1

您预计不会在意。毕竟有很多其他的方式来做到这一点。 –

+0

拦截所有鼠标点击,并且如果在获得焦点之前的最后一次点击是在该组件上,那么它可能就是它。但是你真的不应该在意。如果我只是恢复一个最小化的窗口 - 这是另一种获得重点的方法。如果我最小化另一个应用程序的窗口 - 第四种获得焦点的方法。如果我解锁Windows会话或连接到正在运行的终端服务会话,该怎么办?等等等等。 –

+0

看到我的更新...我害怕我太笼统了。 – REALSOFO

回答

1

因为通过点击总会产生一个鼠标按下事件的事件的OnEnter之前,你可以设置在鼠标按下事件说“gMousedown”实现重点:= true,那么在事件的OnEnter您可以检查是否鼠标按下。不要忘记在onMouseUp事件中将gMousedown重置为false。

+0

好点!我更喜欢这个答案,因为它很简单。 TKS! – REALSOFO

2

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

  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; 
  • VTV具有焦点改变的两个事件:在除了标准OnEnterOnExit事件OnFocusChangedOnFocusChanging
    我不知道哪一种最适合您的需求,您必须进行实验。
  • 假设使用鼠标的焦点总是得到,除非我们可以证明它是使用标签获得。这是一个不稳固的假设,但没关系。

    首先我们使用插入器来覆盖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;