经过前四天的学习,我想很多朋友一定已经完成一个简单的挂机程序了,不过是不是觉得还不够智能,不够完善呢!如果我们能得到更多的数据,就能更好的控制流程。
学习目的:
1.第四天教程后续延伸
2.地面物品显示
内容:
1.第四天我们已经学会如何监视血量达到加血的功能,其实自动攻击和加血的核心原理是一样的,同样是发送消息给游戏窗口,只不过要先通过按Tab键选去身边的怪然后按攻击快捷键打怪。
提示:
SYSKEYDOWN = &H104
KeyDOWN = &H100
KeyUP = &H101
CHAR = &H102
SHIFT = &H10 'Shift键的常数
CONTROL = &H11 'Ctrl键的常数
MENU = &H12 'Windows键的常数
TAB = &H9 'Tab键的常数
[[eax]+ &H798] '&H798 或地址 &H0354AF44 当前目标怪物ID ,为负就是怪,为正就是NPC或玩家,为0则怪物死亡或没有选择
[[eax] + &H408] '人物攻击状态,攻击时为1,无动作为0
[[eax] + &H25C] '&H25C 当前经验值,十进制
[[[[eax]+&h8]+&h24]+&h14] '地上所有物品数量,包含别人打掉地上的物品
2.今天我们要做一个小程序,用于显示地面上的所有物品。添加一个List控件、一个Time控件,如下图所示。
3.下面添加代码!
3.1.模块:
Option Explicit
'---------------声明函数-----------------------
'得到窗体句柄的函数,FindWindow函数用来返回符合指定的类名( ClassName )和窗口名( WindowTitle )的窗口句柄
Public Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
'得到窗体控件句柄的函数
Public Declare Function FindWindowEx Lib "user32" Alias "FindWindowExA" (ByVal hWnd1 As Long, ByVal hWnd2 As Long, ByVal lpsz1 As String, ByVal lpsz2 As String) As Long
'得到进程标识符的函数
Public Declare Function GetWindowThreadProcessId Lib "user32" (ByVal hwnd As Long, lpdwProcessId As Long) As Long
'得到目标进程句柄的函数
Public Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, ByVal dwProcessId As Long) As Long
'关闭句柄的函数
Public Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
'读取进程内存的函数
Public Declare Function ReadProcessMemory Lib "kernel32.dll" (ByVal hProcess As Long, ByVal lpBaseAddress As Long, ByRef lpBuffer As Any, ByVal nSize As Long, ByRef lpNumberOfBytesWritten As Long) As Long
'参数决定了对进程的存储权限,使用完全控制
Public Const PROCESS_ALL_ACCESS = &H1F0FFF
3.2.Form_Load:
Option Explicit
Dim hwd As Long
Dim pid As Long
Dim hProcess As Long '存放进程句柄
Private Sub Form_Load()
hwd = FindWindow("QElementClient Window", "Element Client")
If hwd = 0 Then
MsgBox "未启动游戏", vbOKOnly, "提示"
Unload Form1
End If
GetWindowThreadProcessId hwd, pid '获取进程标识符
'将进程标识符做为参数,返回目标进程PID的句柄,得到此句柄后
'即可对目标进行读写操,PROCESS_ALL_ACCESS表示完全控制,权限最大
hProcess = OpenProcess(PROCESS_ALL_ACCESS, 0, pid)
If hProcess = 0 Then
MsgBox "不能打开进程", vbOKOnly, "提示"
Unload Form1
End If
End Sub
3.3.Timer_Timer:
'Timer.interval=1000,利用1秒的延迟显示列表
Private Sub Timer1_Timer() '显示地面物品名称列表
Dim base As Long '存储地址
Dim mecxi As Long '存储地址
Dim pn As Integer '循环变量
Dim WpName(65) As Byte '存储物品名称
List1.Clear '用于刷新物品列表
If hProcess Then
ReadProcessMemory hProcess, ByVal &H8C9E54, mecxi, 4, 0
ReadProcessMemory hProcess, ByVal mecxi + &H8, mecxi, 4, 0
ReadProcessMemory hProcess, ByVal mecxi + &H24, mecxi, 4, 0 '得到物品数量
If mecxi <> 0 Then
For pn = 0 To 768 '循环用来判断那个值内存在物品
ReadProcessMemory hProcess, ByVal mecxi + &H18, base, 4, 0
ReadProcessMemory hProcess, ByVal base + pn * 4, base, 4, 0 '从列表中选出地面上物品的地址
If base > 0 Then '判断是否存在物品
ReadProcessMemory hProcess, ByVal base + 4, base, 4, 0
ReadProcessMemory hProcess, ByVal base + &H164, base, 4, 0
ReadProcessMemory hProcess, ByVal base, WpName(0), 64, 0 '得到物品名称
List1.AddItem WpName '添加到List控件
End If
Next pn
End If
End If
End Sub
3.4.Form_Unload:
Private Sub Form_Unload(Cancel As Integer)
CloseHandle hProcess
End Sub
4.我只想到了用Clear的方法刷新List,其实并不是很完美,不知道其他大大们有没有更好的方法。
学习目的:
1.第四天教程后续延伸
2.地面物品显示
内容:
1.第四天我们已经学会如何监视血量达到加血的功能,其实自动攻击和加血的核心原理是一样的,同样是发送消息给游戏窗口,只不过要先通过按Tab键选去身边的怪然后按攻击快捷键打怪。
提示:
SYSKEYDOWN = &H104
KeyDOWN = &H100
KeyUP = &H101
CHAR = &H102
SHIFT = &H10 'Shift键的常数
CONTROL = &H11 'Ctrl键的常数
MENU = &H12 'Windows键的常数
TAB = &H9 'Tab键的常数
[[eax]+ &H798] '&H798 或地址 &H0354AF44 当前目标怪物ID ,为负就是怪,为正就是NPC或玩家,为0则怪物死亡或没有选择
[[eax] + &H408] '人物攻击状态,攻击时为1,无动作为0
[[eax] + &H25C] '&H25C 当前经验值,十进制
[[[[eax]+&h8]+&h24]+&h14] '地上所有物品数量,包含别人打掉地上的物品
2.今天我们要做一个小程序,用于显示地面上的所有物品。添加一个List控件、一个Time控件,如下图所示。
![](http://www.ghoffice.com/bbs/attachment/Fid_74/74_16889_8db2a1c61be4d87.jpg)
3.下面添加代码!
3.1.模块:
Option Explicit
'---------------声明函数-----------------------
'得到窗体句柄的函数,FindWindow函数用来返回符合指定的类名( ClassName )和窗口名( WindowTitle )的窗口句柄
Public Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
'得到窗体控件句柄的函数
Public Declare Function FindWindowEx Lib "user32" Alias "FindWindowExA" (ByVal hWnd1 As Long, ByVal hWnd2 As Long, ByVal lpsz1 As String, ByVal lpsz2 As String) As Long
'得到进程标识符的函数
Public Declare Function GetWindowThreadProcessId Lib "user32" (ByVal hwnd As Long, lpdwProcessId As Long) As Long
'得到目标进程句柄的函数
Public Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, ByVal dwProcessId As Long) As Long
'关闭句柄的函数
Public Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
'读取进程内存的函数
Public Declare Function ReadProcessMemory Lib "kernel32.dll" (ByVal hProcess As Long, ByVal lpBaseAddress As Long, ByRef lpBuffer As Any, ByVal nSize As Long, ByRef lpNumberOfBytesWritten As Long) As Long
'参数决定了对进程的存储权限,使用完全控制
Public Const PROCESS_ALL_ACCESS = &H1F0FFF
3.2.Form_Load:
Option Explicit
Dim hwd As Long
Dim pid As Long
Dim hProcess As Long '存放进程句柄
Private Sub Form_Load()
hwd = FindWindow("QElementClient Window", "Element Client")
If hwd = 0 Then
MsgBox "未启动游戏", vbOKOnly, "提示"
Unload Form1
End If
GetWindowThreadProcessId hwd, pid '获取进程标识符
'将进程标识符做为参数,返回目标进程PID的句柄,得到此句柄后
'即可对目标进行读写操,PROCESS_ALL_ACCESS表示完全控制,权限最大
hProcess = OpenProcess(PROCESS_ALL_ACCESS, 0, pid)
If hProcess = 0 Then
MsgBox "不能打开进程", vbOKOnly, "提示"
Unload Form1
End If
End Sub
3.3.Timer_Timer:
'Timer.interval=1000,利用1秒的延迟显示列表
Private Sub Timer1_Timer() '显示地面物品名称列表
Dim base As Long '存储地址
Dim mecxi As Long '存储地址
Dim pn As Integer '循环变量
Dim WpName(65) As Byte '存储物品名称
List1.Clear '用于刷新物品列表
If hProcess Then
ReadProcessMemory hProcess, ByVal &H8C9E54, mecxi, 4, 0
ReadProcessMemory hProcess, ByVal mecxi + &H8, mecxi, 4, 0
ReadProcessMemory hProcess, ByVal mecxi + &H24, mecxi, 4, 0 '得到物品数量
If mecxi <> 0 Then
For pn = 0 To 768 '循环用来判断那个值内存在物品
ReadProcessMemory hProcess, ByVal mecxi + &H18, base, 4, 0
ReadProcessMemory hProcess, ByVal base + pn * 4, base, 4, 0 '从列表中选出地面上物品的地址
If base > 0 Then '判断是否存在物品
ReadProcessMemory hProcess, ByVal base + 4, base, 4, 0
ReadProcessMemory hProcess, ByVal base + &H164, base, 4, 0
ReadProcessMemory hProcess, ByVal base, WpName(0), 64, 0 '得到物品名称
List1.AddItem WpName '添加到List控件
End If
Next pn
End If
End If
End Sub
3.4.Form_Unload:
Private Sub Form_Unload(Cancel As Integer)
CloseHandle hProcess
End Sub
4.我只想到了用Clear的方法刷新List,其实并不是很完美,不知道其他大大们有没有更好的方法。