请问如何模拟鼠标点击消息 使treeview的nodeclick事件发生希望有详尽代码,谢谢!

解决方案 »

  1.   


    Private Sub Command1_Click()
        '……
        Dim m_Node As MSComctlLib.Node
        
        set m_node=
        Call TreeView1_NodeClick(m_Node)
        '……
    End SubPrivate Sub TreeView1_NodeClick(ByVal Node As MSComctlLib.Node)
        '……
    End Sub
    这样做应该就可以了,不需要api
      

  2.   


    不行啊,我是自动化测试用的。就要激发这个事件才成,而且这个事件之后要被VB的事件机制转发给一连串指向同一个treeview的对象变量的
      

  3.   

    postmessage hwnd,wm_leftbuttondown,0,[坐标]句柄就是主窗体句柄,而坐标是相对坐标,主窗体的内部坐标.你的TAB控件应该不会跑来跑去吧.....所以这招应该管用....
      

  4.   


    你这个家伙,呵呵,这回这个是treeview控件的nodeclick事件哦。
      

  5.   

    用mouse_event来模拟吧,程序在响应消息时经常会取鼠标的位置,这种情况用消息是不行的。
      

  6.   

    cnzdgs 
    满天星\n技术问题请勿私聊 
    等级: 
    可用分等级:乞丐 
    总技术分:217292 
    总技术分排名:11 
    //
    你分都哪去了啊
      

  7.   

    Private Declare Function SetCursorPos Lib "user32" (ByVal x As Long, ByVal y As Long) As Long '这个是设置鼠标的位置!
    Private Declare Sub mouse_event Lib "user32" (ByVal dwFlags As Long, ByVal dx As Long, ByVal dy As Long, ByVal cButtons As Long, ByVal dwExtraInfo As Long) '定义鼠标事件
    Dim i As Long
    'vb模拟鼠标在屏幕的x = 10 : y = 20 的位置上点击一下左键
    Private Sub Form_Load()
     Timer1.Enabled = True
     Timer1.Interval = 2000      '2秒
    End SubPrivate Sub Timer1_Timer()
    Call SetCursorPos(10, 20) '让鼠标移动到(10,20)
    mouse_event MOUSEEVENTF_LEFTDOWN Or MOUSEEVENTF_LEFTUP, 0, 0, 0, 0 '模拟鼠标的左键单击!
     i = i + 1
    Print "点击屏幕" & i
    End Sub
      

  8.   

    谢谢goosen。这个代码好用,可是我不知道如何得到节点的坐标?
      

  9.   

    TVM_GETITEMRECT
    注意项目的 hItem 是通过 rc.Left 传进去的。
      

  10.   

    谢谢zhao的提醒。可是折腾了半天,坐标还是搞不对。有两点折腾不对:(1)getrectitem得到的是相对treeview控件的坐标,可我找不到treeview控件的left和top。比如,我用spy++看到treeview控件的左上角是(147,191)。可是我程序里得到的是(2098,1251)。一头雾水啊。我程序里是这么写的:
    'for test
    Public Property Get Left() As Long
        Left = Forms(m_strTreeWnd).WindowLeft + Forms(m_strTreeWnd).Controls(m_strTreCtl).Left
    End Property
    'for test
    Public Property Get Top() As Long
        Top = Forms(m_strTreeWnd).WindowTop + Forms(m_strTreeWnd).Controls(m_strTreCtl).Top
    End Property其中,m_strTreeWnd是树窗的名字;strTreCtl是treeview控件的名字。
    (2)后来我就直接把spy++得到的坐标代进去,这回鼠标能点到树控件里,可是点的位置不对,高度总是比我想要的位置少12.
    Public Sub NodeClick(ByVal nodX As MSComctlLib.Node, trcX As CTreeCtl)
        Dim rc As RECT
        
        rc.Left = GetHTreeItem(nodX, trcX)
        Call SendMessage(trcX.HTvw, TVM_GETITEMRECT, True, rc)
            
    '    Call SetCursorPos(trcX.Left + rc.Left, trcX.Top + rc.Top)
        Call SetCursorPos(147 + rc.Left, 191 + rc.Top + 12) '现在只好这样写,晕死了
        mouse_event MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0
        mouse_event MOUSEEVENTF_LEFTUP, 0, 0, 0, 0    
    End SubPrivate Function GetHTreeItem(ByVal nodX As MSComctlLib.Node, trcX As CTreeCtl) As Long
        nodX.Selected = True
        GetHTreeItem = SendMessage(trcX.HTvw, TVM_GETNEXTITEM, TVGN_CARET, 0)
    End Function
      

  11.   

    'basAPI
    '****for nodeclick
    Public Declare Function SetCursorPos Lib "user32" (ByVal x As Long, ByVal y As Long) As Long '这个是设置鼠标的位置!
    Public Declare Sub mouse_event Lib "user32" (ByVal dwFlags As Long, ByVal dx As Long, ByVal dy As Long, ByVal cButtons As Long, ByVal dwExtraInfo As Long) '定义鼠标事件
    Public Const MOUSEEVENTF_LEFTDOWN As Long = &H2
    Public Const MOUSEEVENTF_LEFTUP As Long = &H4'for get treeitem position
    Public Type RECT
        Left As Long
        Top As Long
        Right As Long
        Bottom As Long
    End Type
      

  12.   

    有什么办法可以根据hwnd得到对应的窗体的left和top绝对坐标么?
      

  13.   

    用 ClientToScreen()、ScreenToClient()
    或者 MapWindowPoints()
      

  14.   

    谢谢zhao。ClientToScreen这个函数真好使。还有个问题想请教:    mouse_event MOUSEEVENTF_LEFTDOWN Or MOUSEEVENTF_LEFTUP, 0, 0, 0, 0上面这一句是不是等价于下面这两句
        mouse_event MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0
        mouse_event MOUSEEVENTF_LEFTUP, 0, 0, 0, 0像这种dwflag类型的参数用or传进去多个的时候是怎么理解啊?
      

  15.   

    另外,你看我在14楼贴的GetHTreeItem函数,每次我都得改变treeview的当前节点。有没有什么办法不要改变当前节点,得到对应的hitem啊?我看Public Enum TVGN_Flags
            TVGN_ROOT = &H0
            TVGN_NEXT = &H1
            TVGN_PREVIOUS = &H2
            TVGN_PARENT = &H3
            TVGN_CHILD = &H4
            TVGN_FIRSTVISIBLE = &H5
            TVGN_NEXTVISIBLE = &H6
            TVGN_PREVIOUSVISIBLE = &H7
            TVGN_DROPHILITE = &H8
            TVGN_CARET = &H9
    #If (WIN32_IE >= &H400) Then               '   >=   Comctl32.dll   v4.71
            TVGN_LASTVISIBLE = &HA
    #End If
    End Enum貌似只能找到和当前节点有特定关系的节点的hitem。如果就想找一个指定节点对应的hItem,和当前节点没任何关系的。该如何做?
      

  16.   

    另外,我很疑惑的是,何以用这种办法(mouse-event)发送消息,程序的流程是先执行发送消息之后的语句,再执行对应的事件过程;而用sendmessage,则是先执行对应的事件过程,再执行发送消息之后的语句。比如,在那个帖子http://topic.csdn.net/u/20090412/21/5cc102c6-f281-4870-a7d6-3755f785c715.html,我是用SendMessage做的。那么执行顺序是:
    m_tvw_expand()
    msgbox "aaa"而这个帖子用mouse-event, 执行顺序是
    msgbox "aaa"
    m_tvw_NodeClick()注:msgbox "aaa"是紧接在发送消息之后的语句。
      

  17.   

    我找到了postmessage和sendmessage的区别。我猜mouse-event是post方式。可是我希望的是同步的。我试了sendmessage WM_LBUTTONDOWN消息,像下面注释掉的这两行,但是这回点击动作压根不发生了好像。
    '    I = SendMessage(hwnd, WM_LBUTTONDOWN, 0, (mX And &HFFFF) + (mY And &HFFFF) * &H10000)
    '    I = SendMessage(hwnd, WM_LBUTTONUP, 0, (mX And &HFFFF) + (mY And &HFFFF) * &H10000)
      

  18.   

    http://topic.csdn.net/t/20041008/11/3433163.html
    GetTVItemFromNode()
      

  19.   

    谢谢各位指点。虽然问题没有完全解决,但是学到了很多东西,小结在这里:http://blog.csdn.net/slowgrace/archive/2009/04/15/4076404.aspx遗留的问题开新帖继续讨教,恳请各位移步前来指点:http://topic.csdn.net/u/20090416/15/f990c1f4-34d0-48b6-8fdf-ac3bb4836bd7.html
      

  20.   

            [DllImport("user32.dll")]
            public static extern int GetWindowRect(IntPtr hwnd, out  Rect lpRect);
            public struct Rect
            {
                public int Left;
                public int Top;
                public int Right;
                public int Bottom;
            }
            [DllImport("User32")]
            public extern static void SetCursorPos(int x, int y);            WinAPI.Rect retCombox = new WinAPI.Rect();
                WinAPI.GetWindowRect(hWndCombox, out retCombox);
                WinAPI.SetCursorPos(retCombox.Left + 10, retCombox.Top + 10);
                WinAPI.mouse_event(WinAPI.MouseEventFlags.LeftDown, retCombox.Left + 10, retCombox.Top + 10, 0, (IntPtr)0);
                WinAPI.mouse_event(WinAPI.MouseEventFlags.LeftUp, retCombox.Left + 10, retCombox.Top + 10, 0, (IntPtr)0);
                Thread.Sleep(500);