• 按键公众号 :
按键精灵电脑版
立即下载

软件版本:2014.06
软件大小:22.9M
更新时间:2021-12-03

按键精灵安卓版
立即下载

软件版本:3.7.2
软件大小:46.2M
更新时间:2023-05-10

按键精灵iOS版
立即下载

软件版本:1.8.0
软件大小:29.2M
更新时间:2023-03-21

按键手机助手
立即下载

软件版本:3.8.0
软件大小:262M
更新时间:2023-05-30

快捷导航

登录 后使用快捷导航
没有帐号? 注册

返回列表 12345678» / 23
发新话题 回复该主题

[技术交流] 【院刊】-【201412期】多线程多开脚本如何实现? [复制链接]

1#

多线程多开脚本如何实现?


您所在的用户组无法下载或查看附件


本文按键学院提供技术支持




“多线程到底怎么实现?好复杂!” 小编时常在论坛里,看到有童鞋发出这样的疑问。
小编觉得多线程就好似冰山美人,外冷内热。乍一看,好像很不好相处,近一步,则会发现其实她很温柔。
到底有多温柔呢?一起来看看~





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循环打开记事本窗口。
  1. For i = 1 To Form1.InputBox1.Text
  2. //打开记事本
  3. RunApp "Notepad.exe"
  4. Next
复制代码
打开记事本之后,我们需要判断下记事本是不是已经打开,如果打开了则获取窗口句柄,如果没有打开,则继续循环判断记事本是不是已经打开。避免当游戏窗口还没有打开获取不到窗口句柄的情况。
  1. do
  2. hwnd = Plugin.Window.Find(0, "无标题 - 记事本")//获取记事本句柄
  3. Loop while (Hwnd=0)
复制代码
2修改记事本窗口的标题。
修改了窗口标题,便于我们管理多窗口。且:第1点中说到的判断记事本窗口是不是打开,当游戏窗口标题都是一样的情况下,这个方法就会失效。第一个窗口打开了,第二个窗口不管有没有打开,那么获取到的还是第一个窗口的句柄。
  1. Do
  2. If stext ="第"&i&"窗口" Then
  3. Exit Do
  4. End If
  5. call Plugin.Window.SetText(hwnd,"第"&i&"窗口")
  6. stext = Plugin.Window.GetText(hwnd)
  7. Loop //循环的第一次修改窗口标题,第二次开始判断标题有没有修改成功,没有的话则继续修改,成功的话则退出do循环。
复制代码

3启动多线程。( 线程相关知识 )
  1. 线程ID = BeginThread(打字)
复制代码
在for循环里加入这一句启动线程的代码,每循环一次开启一个新的线程。
所以,在启动完线程之后,要趁热把线程id记录起来。

4将窗口句柄、线程id 存放到ini文件中。 ( ini文件读取写入相关知识 )
  1. Call Plugin.File.WriteINI("窗口句柄", "第"&i&"窗口",hwnd, "C:\记录.ini")
  2. Call Plugin.File.WriteINI("线程ID", "第"&i&"窗口",线程ID, "C:\记录.ini")
复制代码





线程调用子程序


被线程调用的子程序和平常的子程序有什么不同吗?
有两点不一样:
1、被线程调用的子程序,不支持参数传递。
2、被线程调用的子程序,不支持dim定义的局部变量的传递。
建立一个要被线程调用的子程序 ,命名为 “打字”


  1. Sub 打字()
  2. 窗口句柄 = hwnd//hwnd是环境变量,在一键启动事件中,将窗口句柄赋值给了它。
  3. Do
  4. hwnds = Plugin.Window.FindEx(窗口句柄, 0, "Edit", 0)
  5. Loop While(hwnds=0)
  6. For i = 1 To 200
  7. Call Plugin.Bkgnd.SendString(hwnds, i)
  8. Call Plugin.Bkgnd.KeyPress(Hwnds, 13)
  9. Next
  10. End Sub
复制代码
注意:为什么在子程序的开头 ,要拿一个新的变量 窗口句柄 去获取 hwnd 的值呢?
本例中,我们循环多开窗口的时候,每循环一次,hwnd的值就变化一次。
循环第一次,hwnd的值为:328202,启动线程之后, 调用 sub 打字() 子程序,获取记事本的子窗口句柄。
循环第二次,hwnd的值为:197298,启动线程之后,
调用 sub 打字() 子程序,获取记事本的子窗口句柄。
如果顺利循环下去没有问题,但是,如果第一个窗口开启的时候卡住了呢?第二个窗口开启的速度比第一个快,hwnd中存放的数据变成了第二个窗口的句柄,这个时候第一个窗口缓过来了,它调用到的hwnd里已经不是自己的窗口句柄,而是第二个窗口的。

所以, 当第一个窗口启动线程,调用 sub 打字() 子程序,在子程序的开头位置,第一个窗口的窗口句柄hwnd用新的变量存起来。 新的变量没有定义,默认是dim局部变量,局部变量是不能在线程间传递的,所以它只在当前线程有效,不影响其它线程





“暂停”按钮点击事件


步骤:
1、当按钮的标题名称为“暂停”的时候:
暂停InputBox2文本框中数值对应的线程。并且将按钮的标题修改为"继续"。
2、当按钮的标题名称为“继续”的时候:
恢复InputBox2文本框中数值对应的线程。并且将按钮的标题修改为"暂停"。
  1. If Form1.暂停.Caption = "暂停" Then

  2. 暂停线程id = Plugin.File.readINI("线程ID", "第" &cint(Form1.InputBox2.Text) & "窗口", "C:\记录.ini")
  3. PauseThread 暂停线程id
  4. Form1.暂停.Caption = "继续"
  5. else

  6. 继续线程id = Plugin.File.readINI("线程ID", "第" &cint(Form1.InputBox2.Text) & "窗口", "C:\记录.ini")
  7. ContinueThread 继续线程id
  8. Form1.暂停.Caption = "暂停"

  9. End If
复制代码
“关闭所有窗口”按钮点击事件

步骤:
1、 获取ini文件中记录的线程id,关闭所有线程。
2、 获取ini文件中记录的窗口句柄,关闭所有记事本窗口。
  1. For i = 1 To cint(Form1.InputBox1.Text)
  2. 关闭线程id = Plugin.File.readINI("线程ID", "第" & i & "窗口", "C:\记录.ini")
  3. StopThread 关闭线程id //关闭线程
  4. Call Plugin.Window.Close(Plugin.File.readINI("窗口句柄", "第" & i & "窗口", "C:\记录.ini")) //关闭窗口
  5. Next
复制代码
整体代码:

  1. Dimenv hwnd


  2. Event Form1.一键启动.Click
  3. For i = 1 To Form1.InputBox1.Text

  4. //打开记事本
  5. RunApp "Notepad.exe"


  6. //判断记事本是否打开
  7. do
  8. hwnd = Plugin.Window.Find(0, "无标题 - 记事本")//获取记事本句柄
  9. Loop while (Hwnd=0)
  10. Call Plugin.Window.Move(hwnd,i*50+100,200) //设置记事本出现在屏幕上的位置,横坐标递增,然后窗口可以依次排列开,方便查看运行效果


  11. //////////////修改窗口标题////////////////
  12. Do
  13. If stext ="第"&i&"窗口" Then
  14. Exit Do
  15. End If
  16. call Plugin.Window.SetText(hwnd,"第"&i&"窗口")
  17. stext = Plugin.Window.GetText(hwnd)
  18. Loop


  19. ////启动线程每使用BeginThread启动一次打字子程序,都是生成一条新的线程
  20. 线程ID = BeginThread(打字)


  21. //将窗口句柄、线程id记录到ini文件中,便于之后调用
  22. Call Plugin.File.WriteINI("窗口句柄", "第"&i&"窗口",hwnd, "C:\记录.ini")
  23. Call Plugin.File.WriteINI("线程ID", "第"&i&"窗口",线程ID, "C:\记录.ini")
  24. Next


  25. Form1.一键启动.Enabled=False
  26. End Event




  27. //////////////////关闭线程(StopThread)////////////////////////////
  28. Event Form1.关闭所有窗口.Click

  29. Form1.一键启动.Enabled = true

  30. For i = 1 To cint(Form1.InputBox1.Text)

  31. 关闭线程id = Plugin.File.readINI("线程ID", "第" & i & "窗口", "C:\记录.ini")
  32. StopThread 关闭线程id //关闭线程
  33. Call Plugin.Window.Close(Plugin.File.readINI("窗口句柄", "第" & i & "窗口", "C:\记录.ini")) //关闭窗口

  34. Next
  35. End Event



  36. ////////////////线程暂停(PauseThread)、线程恢复(ContinueThread)///
  37. Event Form1.暂停.Click


  38. If Form1.暂停.Caption = "暂停" Then

  39. 暂停线程id = Plugin.File.readINI("线程ID", "第" &cint(Form1.InputBox2.Text) & "窗口", "C:\记录.ini")
  40. PauseThread 暂停线程id
  41. Form1.暂停.Caption = "继续"
  42. else

  43. 继续线程id = Plugin.File.readINI("线程ID", "第" &cint(Form1.InputBox2.Text) & "窗口", "C:\记录.ini")
  44. ContinueThread 继续线程id
  45. Form1.暂停.Caption = "暂停"

  46. End If
  47. End Event



  48. ////////////////打字线程/////////////////////////
  49. Sub 打字()
  50. 窗口句柄 = hwnd
  51. Do
  52. hwnds = Plugin.Window.FindEx(窗口句柄, 0, "Edit", 0)
  53. Loop While(hwnds=0)
  54. For i = 1 To 200
  55. Call Plugin.Bkgnd.SendString(hwnds, i)
  56. Call Plugin.Bkgnd.KeyPress(Hwnds, 13)
  57. Next
  58. End Sub
复制代码
Q文件下载:
您所在的用户组无法下载或查看附件









本文按键学院提供技术支持

━═━═━━═━═━━═━═━◥◤━═━═━━═━═━━═━═━

有钱,就是任性!按键学院的导师就是土豪!

按键学院实战班


    已有3评分我要评分查看所有评分

    本主题由 超级版主 瑞祥幽冥狼 于 2023/10/5 17:59:27 执行 审核帖子 操作
    按键学院免费交流群:376122403

    按键学院招生计划
    按键学院系统教程
    2#

    学无止境

    3#

    收益非浅,好贴

    接单 728263
    4#

    看看是什么

    5#

    不错不错。

    6#

    111111

    7#

    看看吧

    8#


    9#

    的撒个肺好

    10#

    看一下!!!!!!!!!!

    11#

    将窗口句柄、线程id 存放到ini文件中。

    12#

    1121231321321

    13#

    泛光灯个

    14#

    挺方便

    15#

    111111111111111

    16#

    感谢楼主,谢谢楼主

    17#

    asdasdadsa

    18#

    我也来看看

    19#


    20#

    想看一看的冲动
    想看一看的冲动
    想看一看的冲动

    发新话题 回复该主题