以前就提过的问题,现在还没有解决
问题是这样的,我有一个窗体专门用来截留屏幕某一区域的鼠标操作,并且如同痕迹显示一样在窗体上绘制鼠标操作相应的数据记录,然后将鼠标消息继续传给Z轴上在窗体之下的其它窗口。这样的窗体我可以简单的令其透明来显示下层窗口,绘制的部分也很简单,但是如何简洁明了的将鼠标消息分析并传递给下层窗体应该怎么写?
最主要的是,考虑到VB消息截流的效率,这样的代码应该越简单越好,用FindWindow然后按照鼠标位置逐一排除窗口的方法会带来很大的问题。本人对SubClass不熟,没什么思路,所以向各位高手请教,小弟在此先谢谢各位了。

解决方案 »

  1.   

    SSubTmr.dll
    網上直接搜索就有含Source的.
      

  2.   

    谢谢楼上的朋友,能简单说说用这个SubClassLibrary要怎样实现我的要求呢?谢谢!
      

  3.   

    这为什么要用SubClass?用在哪呢?桌面窗体基本都是跨进程,又怎么用SubClass呢?
    我想的的方法是WindowFromPoint加SendMassage应该可以搞定, 不过没试过,LZ再研究看看
      

  4.   

    忘了说,可能还要ClientToScreen和ScreenToClient进行坐标转换。
      

  5.   

    小吉兄您好,您说的方法我也想过,但是WindowsFromPoint可以获得我的窗口之下的窗口吗?
    或者请您谈谈如何不用SubClass?谢谢了!
      

  6.   

    WindowFromPoint忽略屏蔽、隐藏以及透明窗口,所以你临时将你的窗口隐藏即可,然后再恢复,这样会有闪烁,不过应该有办法可以解决
    //然后将鼠标消息继续传给Z轴上在窗体之下的其它窗口
    这个我不知道你的目的何在,“其它窗口”具体是什么
    PS:个人感觉,你的问题用钩子解决更合理一些
      

  7.   

    现在想想WindowFromPoint解决是有点免强,不过可以试试,也不要隐藏那么大动作了,用setWindowsPos ..HWND_BOTTOM...放在底层,就可以再次WindowFromPoint了,这样循环,直到又回到第一个窗体为止,而且窗体顺序也不会变。
    但这样做,还是会闪动,所以用Enum才是合理选择,效率也不会低,而且稳定。SubClass不能跨进程,进程外的窗体消息拦截要用Hook,但VB做有些难,更重要的是我实在想不出用钩子的目的,钩哪个窗体呢?钩住又有什么用呢?只有一点我可以肯定,上钩后效率会更低。这样吧,我先抽空写个Enum的代码试试。
      

  8.   

    模块中的代码
    Option Explicit
    Private Const DESKTOP_ENUMERATE = &H40&
    Private Type POINTAPI
            x As Long
            y As Long
    End TypePrivate Type RECT
            Left As Long
            Top As Long
            Right As Long
            Bottom As Long
    End Type
    Private Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA" (ByVal hwnd As Long, ByVal lpString As String, ByVal cch As Long) As Long
    Private Declare Function GetWindowRect Lib "user32" (ByVal hwnd As Long, lpRect As RECT) As Long
    Private Declare Function IsIconic Lib "user32" (ByVal hwnd As Long) As Long
    Private Declare Function IsWindowEnabled Lib "user32" (ByVal hwnd As Long) As Long
    Private Declare Function IsWindowVisible Lib "user32" (ByVal hwnd As Long) As Long
    Private Declare Function EnumDesktopWindows Lib "user32" (ByVal hDesktop As Long, ByVal lpfn As Long, ByVal lParam As Long) As Long
    Private Declare Function OpenDesktop Lib "user32" Alias "OpenDesktopA" (ByVal lpszDesktop As String, ByVal dwFlags As Long, ByVal fInherit As Boolean, ByVal dwDesiredAccess As Long) As Long
    Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
    Private Declare Function ClientToScreen Lib "user32" (ByVal hwnd As Long, lpPoint As POINTAPI) As Long
    Private TestPoint As POINTAPIPrivate Function EnumWindowsProc(ByVal hwd As Long, ByVal lp As Long) As Boolean
        Dim rec As RECT, s As String
        If hwd <> lp Then   '排除自己,当然最底层的“Program Manager”可能也需排除,你自己加吧
            If IsIconic(hwd) = 0 And IsWindowEnabled(hwd) And IsWindowVisible(hwd) Then
                GetWindowRect hwd, rec
                If TestPoint.x >= rec.Left And TestPoint.x <= rec.Right And TestPoint.y >= rec.Top And TestPoint.y <= rec.Bottom Then
                    '这里你可用SendMassge传递鼠标消息,
                    '我建议最好MouseDown时把它们加入一个数组或集合,这样在MouseMove时可直接使用,MouseUp时清空数组或集合
                    s = String$(100, " ")
                    GetWindowText hwd, s, 100
                    Debug.Print Trim$(s)
                End If
            End If
        End If
        EnumWindowsProc = 1
    End FunctionPublic Sub FindDownWin(hwnd As Long, x As Long, y As Long)
        Dim hDesk As Long, xy(1) As Integer, lp As Long
        TestPoint.x = x
        TestPoint.y = y
        ClientToScreen hwnd, TestPoint
        '这种方法不适于9X系统,对于Win9X,你还是用EnumWindows吧
        hDesk = OpenDesktop(vbNullString, 0, False, DESKTOP_ENUMERATE)
        EnumDesktopWindows hDesk, AddressOf EnumWindowsProc, hwnd
        CloseHandle hDesk
    End Sub----------------------------------------
    窗体中的代码
    Option ExplicitPrivate Sub Form_Load()
        Me.ScaleMode = 3
    End SubPrivate Sub Form_MouseDown(Button As Integer, Shift As Integer, x As Single, y As Single)
        FindDownWin Me.hwnd, CLng(x), CLng(y)
    End
      

  9.   

    to rainstormmaster(暴风雨 v2.0):
    关于我为什么要向下传递鼠标消息,可以大致理解为我的窗口就是一片软件滤色膜,“贴”在所有窗口之上,滤色膜显然不会影响鼠标的操作所以需要将鼠标操作向下传递。
    至于键盘的输入操作因为我可以令窗口TOPMOST所以丢失焦点的情况不需要在意。to all:
    刚刚想到这个问题,用窗口枚举的时候会导致本窗口获得焦点吗?是不是需要采取措施防止焦点的获得?
    谢了!