| 网站首页 | 文章中心 | 下载中心 | 图片中心 | 雁过留声 | 
最新公告:

  没有公告

您现在的位置: 蘸雪网络 >> 文章中心 >> 软件技巧 >> 正文
专题栏目
更多内容
最新推荐 更多内容
相关文章
没有相关文章
更多内容
[图文]Spy++原理初探         ★★★
Spy++原理初探
作者:佚名 文章来源:本站原创 点击数: 更新时间:2008-10-3 20:54:42

API函数,就会提到句柄,像SendMessage, GetWindowText等,最常用到的参数就是句柄。啥是句柄呢?就是窗口的锅把儿,你拎着它,整个锅儿都听你的话。那啥是窗口呢?不仅仅指我们常说的窗体Form,还包括所有控件,如文本框,按钮,复选框等等。这些句柄怎么获取呢?用Spy++呀。本文中,笔者就和您一起打造一个VB版的Spy++。(笔者以前写过一篇VC版的Spy++,得到了许多网友的关注,所以撰写此文,以飨VB战壕的朋友们。)

一.         界面设计

新建EXE工程,在窗体frmMain上画一个PictureBoxpicShot),用以装载探测器的靶形图标;画两个CheckBoxchkAlwaysOnTopchkHex)用于选择窗口是否在最上面和句柄等值的返回形式是否为十六进制。

再下面是选项卡控件,我们有两种选择。一种是用Microsoft Windows Common Controls6.0(mscomctl.ocx)中的TabStrip,这种控件的用法与VC中类似,标签页不可以在主窗体设计时直接做,而是要画N个子窗体或PictureBox,然后在运行时按情况调用;第二种选择是Microsoft Tabbed Dialog Control6.0(tabctl32.ocx),这个控件可以直接在上面设计每个标签页,我们就选择它。

把选项卡控件命名为SSTab1,通过其属性页设置好各标签页的标题为“常规”、“样式”、“类”、“窗口”和“消息”。程序界面设计如图。

 

 

二、探测器制作

准备好两个图标(ico)和一个鼠标指针(cur)文件,分别用于正常状态下的显示、鼠标拖出时的显示以及拖出时的鼠标指针;正常状态下显示一幅有靶的图标。当鼠标在上面按下时,显示内容立刻换为另一幅无靶的图标,同时鼠标指针变为靶状。这样,就给人一种靶心被拖出去的感觉了。通过上面的叙述,我们了解到图片框需要响应MouseDownMouseUp事件。而鼠标左键松开处一般不会在图片框上,所以,要想让图片框的MouseUp来响应,我们要用到一个API函数:SetCapture。这个函数用以对鼠标事件的捕获,我们在图片框的MouseDown事件中SetCapture后,以后即使鼠标指针离开图片框,发生的事件也是由图片框(或指定窗口)来处理。其API函数声明自己用API浏览器查,不再赘述。需强调的是,在MouseUp事件中别忘了释放捕获(另一个APIReleaseCapture)。在鼠标按下时,还涉及到换图标换指针等操作,代码如下:

Private Sub picShot_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single)

    Screen.MousePointer = vbCustom

    Screen.MouseIcon = Image1.Picture     '用鼠标指针变为靶状

    picShot.Picture = Image2.Picture     '此时图片框加载另一无靶图标

    '将以后的鼠标输入消息都发送到图片框窗口

    SetCapture (picShot.hWnd)

End Sub

Private Sub picShot_MouseUp(Button As Integer, Shift As Integer, X As Single, Y As Single)

    Screen.MousePointer = vbDefault

    picShot.Picture = Image3.Picture

    ReleaseCapture

End Sub

获取窗口句柄。根据鼠标位置来确定窗口需要用到API函数GetCursorPosWindowFromPoint。此外,我们还想做到像抓图程序那样,鼠标移动到的地方,窗口四周会出现闪烁的矩形。这一点,我们用定时器来实现。在桌面背景上绘图,大致过程如下:用GetDesktopWindow()获取桌面句柄,再用GetWindowDC()获得设备场景(或叫设备上下文)。啥叫设备场景?就当成是画布吧,要画画嘛,就要找找到窗口对应的画布。还有用到一个SetROP2(),用以“设定当前前景色的混合模式”(从MSDN中直译,如果觉得不通,请看MSDN原文),这里采用R2_NOTXORPEN混合模式(其值为10),载入一支反色画笔。GetWindowRect()用以获得窗口的矩形,Rectangle()函数用于画这个矩形,ReleaseDC用于释放设备场景。实现代码如下:

Private Sub tmr_Timer()

    ……Dim XXX……..

    DeskHwnd& = GetDesktopWindow()    '取得桌面句柄

    DeskDC& = GetWindowDC(DeskHwnd&)     '取得桌面设备场景

    oldRop2& = SetROP2(DeskDC&, 10)

    GetCursorPos pnt                '取得鼠标坐标

    PointText.Text = Str(pnt.X) & "," & Str(pnt.Y)

    UnHwnd = WindowFromPoint(pnt.X, pnt.Y)     '取得鼠标指针处窗口句柄

    grayHwnd = GetWindow(UnHwnd, GW_CHILD)

'因为WindowsFromPoint函数对Disabled的窗口无效,所以写了下面这个循环,否则无法选中“灰色按钮”类窗口

    Do While (grayHwnd)

        GetWindowRect grayHwnd, tempRc

        If PtInRect(tempRc, pnt.X, pnt.Y) Then

            FindIt = True

            Exit Do

       Else

            grayHwnd = GetWindow(grayHwnd, GW_HWNDNEXT)

        End If

    Loop

    If FindIt = True Then

        FindIt = False

        SnapHwnd = grayHwnd

    Else

        SnapHwnd = UnHwnd

    End If

    GetWindowRect SnapHwnd, rc        '获得窗口矩形

   If rc.Left < 0 Then rc.Left = 0

    If rc.Top < 0 Then rc.Top = 0

    If rc.Right > Screen.Width / 15 Then rc.Right = Screen.Width / 15

    If rc.Bottom > Screen.Height / 15 Then rc.Bottom = Screen.Height / 15

    newPen& = CreatePen(0, 3, &H0)       '建立新画笔,载入DeskDC

    oldPen& = SelectObject(DeskDC, newPen)

    Rectangle DeskDC, rc.Left, rc.Top, rc.Right, rc.Bottom '在指示窗口周围显示闪烁矩形

    Sleep tmr.Interval    '设置闪烁时间间隔

    Rectangle DeskDC, rc.Left, rc.Top, rc.Right, rc.Bottom

    SetROP2 DeskDC, oldRop2

    SelectObject DeskDC, oldPen

    DeleteObject newPen

ReleaseDC DeskHwnd, DeskDC:

DeskDC = 0

End Sub

三、两个复选框

复选框“总在最上面”用到的API函数是SetWindowPos()。由于比较直观,读者朋友直接看下面代码:

Private Sub chkalwaysontop_Click()

    If(chkAlwaysOnTop.Value= 1)

        SetWindowPos(g_hWnd,HWND_TOPMOST,0,0,0,0,SWP_NOMOVE | SWP_NOSIZE)

    Else

SetWindowPos(g_hWnd,HWND_NOTOPMOST,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE)

    End If

End Sub

第二个复选框决定返回值以16进制还是10进制显示,这对咱VB兄弟很有用,因为我们VB习惯使用的不是16进制。这里我们建立一个全局函数,根据复选框的不同状态有不同的返回值,代码如下:

Function DisplayNum(Num As Long) As String

    If frmMain.chkHex.Value = 1 Then

        DisplayNum = Hex(Num)

    Else

        DisplayNum = LTrim(Str(Num))

    End If

End Function

文章录入:zhanxue    责任编辑:zhanxue 
  • 上一篇文章:

  • 下一篇文章: 没有了
  • 【字体: 】【发表评论】【加入收藏】【告诉好友】【打印此文】【关闭窗口
      网友评论:(只显示最新10条。评论内容只代表网友观点,与本站立场无关!)

    | 设为首页 | 加入收藏 | 联系站长 | 友情链接 | 版权申明 | 管理登录 | 
    动易网络 版权所有©2008 站长:醉卧流霞
    模板设计:梅子
    信息产业部备案
    *ICP备********号