注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

The Bloom of Youth

本博客已搬家至http://kuangqi.me

 
 
 

日志

 
 

VB编程-破解大学英语学习大厅计时器  

2009-11-04 23:38:00|  分类: 工巧匠心 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

       学校真会省事。搞了个新理念大学英语学习大厅。让同学们自学。。。貌似唯一的考核标准就是学习时间。必须在那个学习软件中“学习”够一定时间,才能通过考核。恶心的是,那个软件只在窗口处于活动状态时才会计时。一旦窗口失去焦点,计时器就会马上停止。也就是说,你别想一边开着软件,一面上着小网来蹭时间。只要你一离开学习窗口,计时器就停下啦~~

       它越是这样,就越激起了我研究一下它的兴趣。利用我积累的代码,我用了大概10分钟的时间,当堂写出了一个该软件的计时器破解程序。开启该程序后,学习大厅窗口即使在非活动状态,计时器也不会停止。

       程序的原理很简单,计时器在窗口在失焦时停止,在窗口激活(得到焦点)时启动。Windows是消息驱动的系统,得到焦点时,窗口会收到WM_SETFOCUS消息。计时器也就是根据这个消息来启动的。如果在窗口失焦的情况下,人为的向该窗口发送WM_SETFOCUS消息,也同样可以启动计时器。

我用VB来实现这个过程:

这个程序需要用到两个重要的Win32 API函数。

1.FindWindow函数,详细情况如下:

【VB声明】
  Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long

【别名】
  FindWindowA

【说明】
  寻找窗口列表中第一个符合指定条件的顶级窗口(在vb里使用:FindWindow最常见的一个用途是获得ThunderRTMain类的隐藏窗口的句柄;该类是所有运行中vb执行程序的一部分。获得句柄后,可用api函数GetWindowText取得这个窗口的名称;该名也是应用程序的标题)

【返回值】
  Long,找到窗口的句柄。如未找到相符窗口,则返回零。会设置GetLastError

【备注】
  很少要求同时按类与窗口名搜索。为向自己不准备参数传递一个零,最简便的办法是传递vbNullString常数
  示例
  Dim hw& , cnt&
  Dim rttitle As String * 256
  hw&  = FindWindow("ThunderRT5Main", vbNullString) ' ThunderRTMain under VB4
  cnt = GetWindowText(hw& , rttitle, 255)
  MsgBox Left$(rttitle, cnt), 0, "RTMain title"

【参数表】
  lpClassName ----  String,指向包含了窗口类名的空中止(C语言)字串的指针;或设为零,表示接收任何类

  lpWindowName ---  String,指向包含了窗口文本(或标签)的空中止(C语言)字串的指针;或设为零,表示接收任何窗口标题

2.PostMessage函数,详情如下:

【VB声明】
  Private Declare Function PostMessage Lib "user32" Alias "PostMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long

【别名】
  PostMessageA

【说明】
  将一条消息投递到指定窗口的消息队列。投递的消息会在Windows事件处理过程中得到处理。在那个时候,会随同投递的消息调用指定窗口的窗口函数。特别适合那些不需要立即处理的窗口消息的发送

【返回值】
  Long,如消息投递成功,则返回TRUE(非零)。会设置GetLastError

【参数表】
  hwnd -----------  Long,接收消息的那个窗口的句柄。如设为HWND_BROADCAST,表示投递给系统中的所有顶级窗口。如设为零,表示投递一条线程消息(参考PostThreadMessage)

  wMsg -----------  Long,消息标识符

  wParam ---------  Long,具体由消息决定

  lParam ---------  Any,具体由消息决定

 

思路非常明了,先用FindWindow函数获得指定窗口的句柄,再用PostMessage函数向该句柄发送WM_SETFOCUS消息。另外,该软件还有一个特性,就是如果窗口是激活状态,但超过一段时间没有操作(大概是5-10分钟),就会弹出一个对话框,如果不点掉,计时器同样会停止。所以我还定时向其发送WM_KEYDOWN消息来模拟按键操作。

具体实现代码如下:

模块代码:

Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
Declare Function PostMessage Lib "user32" Alias "PostMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long
Declare Sub Sleep Lib "Kernel32" (ByVal dwMilliseconds As Long) '-----Sleep函数
Public Const WM_SETFOCUS = &H7
Public Const WM_KEYDOWN = &H100
'关闭窗口的句柄
Private winHwnd As Long
Private RetVal As Long

窗体代码:

Private Sub Command1_Click()
Timer1.Interval = 800
Label1.Caption = "状态:正在爆破!"
End Sub

Private Sub Command2_Click()
Timer1.Interval = 0
Label1.Caption = "状态:爆破停止。"
End Sub

Private Sub Timer1_Timer()
    '变量声明
    Dim winHwnd As Long
    Dim RetVal As Long
    winHwnd = 0
    '发现并结束窗体
    winHwnd = FindWindow(vbNullString, Text1.Text)  '找到指定标题的窗口
    If winHwnd <> 0 Then   '一旦找到指定窗口,进行以下操作
        RetVal = PostMessage(winHwnd, WM_SETFOCUS, 0&, 0&)  '发送消息设置焦点
        Sleep 200
        RetVal = PostMessage(winHwnd, WM_KEYDOWN, 0&, 0&)  '发送消息模拟按键
    End If  '那就跳出循环,继续等待
End Sub

窗体元素:

Timer1——计时器控件

Text1——输入窗口标题的文本框。这里输入的是“新理念大学英语学习大厅”

Command1—— “开始爆破”按钮

Command2——“暂停爆破”按钮

Label1——状态指示标签

补充:那个软件貌似是用.Net编写的,在考虑哪天有时间反编译一下看看,会不会有什么意外的发现~~哈哈!

免责声明:本文仅用于技术交流,不得用于商业用途,不接受菜鸟求助。由于使用本文介绍的方法导致的任何不良后果,本人不承担责任。未经授权不得转载。授权的转载请注明出处:http://kqwd.blog.163.com/

  评论这张
 
阅读(2596)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017