2024年2月23日发(作者:)
按键精灵实现多线程多开脚本教程
来源:按键学院 【按键精灵】
“多线程到底怎么实现?好复杂!” 小编时常在论坛里.看到有童鞋发出这样的疑问。
小编觉得多线程就好似冰山美人.外冷内热。乍一看.好像很不好相处.近一步.则会发现其实她很温柔。
到底有多温柔呢?一起来看看~
QUI界面
写代码之前.我们先画脚本的Qui界面。如下图:
思路
我们拿记事本作为多开的对象。脚本由以下三个按钮点击事件组成:
1、点击QUI界面中的"一键启动"按钮.启动记事本.启动的记事本个数由InputBox1里填入的数值决定。启动线程.将线程id、窗口句柄记录到ini文件中。在线程调用的子程序里.对记事本输入内容。
2、点击“关闭所有窗口”按钮.则读取ini中保存的线程id、窗口句柄.关闭线程之后关闭窗口。
. .
3、点击“暂停”按钮.则读取ini文件中和InputBox2文本框中对应数值的窗线程id.暂停该线程。再次点击“暂停”按钮.则读取ini文件中和InputBox2文本框中对应数值的窗线程id.恢复该线程。
“一键启动”按钮点击事件
步骤:
1、启动记事本窗口。
2、修改记事本的标题名称。
3、每个记事本窗口对应启动一个线程。
4、将窗口句柄、线程id记录到ini文件中。
1、启动记事本窗口。
获取InputBox1中的数值。利用for循环打开记事本窗口。
For i = 1 To
//打开记事本
RunApp ""
Next
打开记事本之后.我们需要判断下记事本是不是已经打开.如果打开了则获取窗口句柄.如果没有打开.则继续循环判断记事本是不是已经打开。避免当游戏窗口还没有打开获取不到窗口句柄的情况。
do
hwnd = (0, "无标题 - 记事本")//获取记事本句柄
Loop while (Hwnd=0)
2、修改记事本窗口的标题。
修改了窗口标题.便于我们管理多窗口。且:第1点中说到的判断记事本窗口是不是打开.当游戏窗口标题都是一样的情况下.这个方法就会失效。第一个窗口打开了.第二个窗口不管有没有打开.那么获取到的还是第一个窗口的句柄。
Do
If stext ="第"&i&"窗口" Then
Exit Do
End If
call t(hwnd,"第"&i&"窗口")
stext = t(hwnd)
Loop //循环的第一次修改窗口标题.第二次开始判断标题有没有修改成功.没有的话则继续修改.成功的话则退出do循环。
3、启动多线程。( 线程相关知识 )
. .
线程ID = BeginThread(打字)
在for循环里加入这一句启动线程的代码.每循环一次开启一个新的线程。
所以.在启动完线程之后.要趁热把线程id记录起来。
4、将窗口句柄、线程id 存放到ini文件中。 ( ini文件读取写入相关知识 )
Call NI("窗口句柄", "第"&i&"窗口",hwnd, "C:记录.ini")
Call NI("线程ID", "第"&i&"窗口",线程ID, "C:记录.ini")
线程调用子程序
被线程调用的子程序和平常的子程序有什么不同吗?
有两点不一样:
1、被线程调用的子程序.不支持参数传递。
2、被线程调用的子程序.不支持dim定义的局部变量的传递。
建立一个要被线程调用的子程序 .命名为 “打字”
Sub 打字()
窗口句柄 = hwnd//hwnd是环境变量.在一键启动事件中.将窗口句柄赋值给了它。
Do
hwnds = (窗口句柄, 0, "Edit", 0)
Loop While(hwnds=0)
For i = 1 To 200
Call ring(hwnds, i)
Call ss(Hwnds, 13)
Next
End Sub
注意:为什么在子程序的开头 .要拿一个新的变量 窗口句柄 去获取 hwnd 的值呢?
本例中.我们循环多开窗口的时候.每循环一次.hwnd的值就变化一次。
循环第一次.hwnd的值为:328202.启动线程之后. 调用 sub 打字() 子程序.获取记事本的子窗口句柄。
循环第二次.hwnd的值为:197298.启动线程之后. 调用 sub 打字() 子程序.获取记事本的子窗口句柄。
如果顺利循环下去没有问题.但是.如果第一个窗口开启的时候卡住了呢?第二个窗口开启的速度比第一个快.hwnd中存放的数据变成了第二个窗口的句柄.这个时候第一个窗口缓过来了.它调用到的hwnd里已经不是自己的窗口句柄.而是第二个窗口的。
所以. 当第一个窗口启动线程.调用 sub 打字() 子程序.在子程序的开头位置.第一个窗口的窗口句柄hwnd用新的变量存起来。 新的变量没有定义.默认是dim局部变量.局部变量是不能在线程间传递的.所以它只在当前线程有效.不影响其它线程。
. .
“暂停”按钮点击事件
步骤:
1、当按钮的标题名称为“暂停”的时候:
暂停InputBox2文本框中数值对应的线程。并且将按钮的标题修改为"继续"。
2、当按钮的标题名称为“继续”的时候:
恢复InputBox2文本框中数值对应的线程。并且将按钮的标题修改为"暂停"。
If Form1.暂停.Caption = "暂停" Then
暂停线程id = I("线程ID", "第" &cint() & "窗口", "C:记录.ini")
PauseThread 暂停线程id
Form1.暂停.Caption = "继续"
else
继续线程id = I("线程ID", "第" &cint() & "窗口", "C:记录.ini")
ContinueThread 继续线程id
Form1.暂停.Caption = "暂停"
End If
“关闭所有窗口”按钮点击事件
步骤:
1、 获取ini文件中记录的线程id.关闭所有线程。
2、 获取ini文件中记录的窗口句柄.关闭所有记事本窗口。
For i = 1 To cint()
关闭线程id = I("线程ID", "第" & i & "窗口", "C:记录.ini")
StopThread 关闭线程id //关闭线程
Call (I("窗口句柄", "第" & i & "窗口", "C:记录.ini")) //关闭窗口
Next
. .
整体代码:
Dimenv hwnd
Event Form1.一键启动.Click
For i = 1 To
//打开记事本
RunApp ""
//判断记事本是否打开
do
hwnd = (0, "无标题 - 记事本")//获取记事本句柄
Loop while (Hwnd=0)
Call (hwnd,i*50+100,200) //设置记事本出现在屏幕上的位置.横坐标递增.然后窗口可以依次排列开.方便查看运行效果
//////////////修改窗口标题////////////////
Do
If stext ="第"&i&"窗口" Then
Exit Do
End If
call t(hwnd,"第"&i&"窗口")
stext = t(hwnd)
Loop
////启动线程每使用BeginThread启动一次打字子程序.都是生成一条新的线程
线程ID = BeginThread(打字)
//将窗口句柄、线程id记录到ini文件中.便于之后调用
Call NI("窗口句柄", "第"&i&"窗口",hwnd, "C:记录.ini")
Call NI("线程ID", "第"&i&"窗口",线程ID, "C:记录.ini")
Next
Form1.一键启动.Enabled=False
End Event
. .
//////////////////关闭线程(StopThread)////////////////////////////
Event Form1.关闭所有窗口.Click
Form1.一键启动.Enabled = true
For i = 1 To cint()
关闭线程id = I("线程ID", "第" & i & "窗口", "C:记录.ini")
StopThread 关闭线程id //关闭线程
Call (I("窗口句柄", "第" & i & "窗口", "C:记录.ini")) //关闭窗口
Next
End Event
////////////////线程暂停(PauseThread)、线程恢复(ContinueThread)///
Event Form1.暂停.Click
If Form1.暂停.Caption = "暂停" Then
暂停线程id = I("线程ID", "第" &cint() & "窗口", "C:记录.ini")
PauseThread 暂停线程id
Form1.暂停.Caption = "继续"
else
继续线程id = I("线程ID", "第" &cint() & "窗口", "C:记录.ini")
ContinueThread 继续线程id
Form1.暂停.Caption = "暂停"
End If
End Event
////////////////打字线程/////////////////////////
Sub 打字()
. .
窗口句柄 = hwnd
Do
hwnds = (窗口句柄, 0, "Edit", 0)
Loop While(hwnds=0)
For i = 1 To 200
Call ring(hwnds, i)
Call ss(Hwnds, 13)
Next
End Sub
. .
发布评论