Board logo

标题: [问题求助] vbs如实现无需激活指定窗口也能对该窗口模拟点击按键 [打印本页]

作者: zgh7878788    时间: 2012-12-8 21:03     标题: vbs如实现无需激活指定窗口也能对该窗口模拟点击按键

本帖最后由 pcl_test 于 2016-7-17 21:55 编辑

求一个用VBS写的脚本(纯VBS,网上只有按键精灵版的),后台往t.txt文本里写东西,比如,前台是这样的语句:
Set WshShell=CreateObject("WScript.Shell")
WshShell.AppActivate "t - 记事本"
crt.Screen.Send "it"
crt.sleep 100
crt.Screen.Send " "
crt.sleep 100
crt.Screen.Send "is"
crt.sleep 100
crt.Screen.Send " 9"
crt.sleep 100
crt.Screen.Send "{Enter}"
这个问题困扰我好久了,麻烦各位老师赐教,谢谢!非常感谢!
作者: czjt1234    时间: 2012-12-11 17:44

  1. Set objFSO = CreateObject("Scripting.FileSystemObject")
  2. Set objTextStream = objFSO.OpenTextFile("D:\test.txt", 8, True)
  3. '这里的8代表追加文件内容,要清空原有文件内容换成2
  4. objTextStream.WriteLine "111"
  5. objTextStream.WriteLine "222"
  6. objTextStream.Close
复制代码

作者: czjt1234    时间: 2012-12-11 18:20

Set objTextStream = objFSO.OpenTextFile("D:\test.txt",1|2|8,True|False,-2|-1|0)
'打开文件,返回 TextStream 对象
'可以读写文件内容,不能使用文件属性,不可以复制、移动、删除文件
'True表示文件不存在时自动新建文件,False为不新建(缺省值)
  Const ForReading         = 1   '只读(缺省值)
  Const ForWriting         = 2   '清空文件,覆盖写入
  Const ForAppending       = 8   '在文件末尾追加写入
  Const TristateUseDefault = -2  '以系统默认格式打开文件
  Const TristateTrue       = -1  '以 Unicode 格式打开文件
  Const TristateFalse      = 0   '以 ASCII 格式打开文件(缺省值)


objTextStream.Skip(3)
'在读取数据时,跳过3个字符,光标位置移到3个字符之后
'每行末尾的回车换行算2个字符
'要求打开方式为只读


objTextStream.SkipLine
'在读取数据时,跳过一行,光标位置移到下一行行首
'要求打开方式为只读


strRead = objTextStream.Read(3)
'从光标位置读取3个字符,光标移到3个字符之后
'要求打开方式为只读


strRead = objTextStream.ReadLine
'从光标位置读取一行,光标移到下一行行首
'要求打开方式为只读


strRead = objTextStream.ReadAll
'从光标位置读取文件所有内容,光标移到文末
'要求打开方式为只读


blnYN = objTextStream.AtEndOfLine
'判断光标位置是否在某一行末尾,返回True|False
'要求打开方式为只读


blnYN = objTextStream.AtEndOfStream
'判断光标位置是否在文末,返回True|False
'要求打开方式为只读


objTextStream.Write "test"
'从光标位置插入字符串


objTextStream.WriteLine "test"
'从光标位置插入字符串,并回车换行


objTextStream.WriteBlankLines 5
'从光标位置插入5个空行


strRead = objTextStream.Line
'返回当前光标所在行号


strRead = objTextStream.Column
'返回当前光标所在列号


objTextStream.Close
'关闭文件对象,立刻保存到磁盘

作者: zgh7878788    时间: 2012-12-12 18:08

回复 2# czjt1234


    老师,非常感谢!这个能实现向文件追加内容的目的。现在我想的是用SENDKEY的方式,只是那是前台,我想要后台的。我知道老师要问我有您写那种方式为啥还要后台的SENDKEY?可能我一时也解释不清,但我确实需要那种后台的SENDKEY的例子。不知道老师能不能帮帮忙?占用您宝贵时间,十分过意不去,只能万分感谢!谢谢!!!
作者: zgh7878788    时间: 2012-12-12 19:42

时间我不是用在记事本上,只是把记事本当例子,本是想用在其他软件上,起一个模拟按键操作的作用.谢谢各位老师了,拜托了!
作者: czjt1234    时间: 2012-12-13 09:53

本帖最后由 czjt1234 于 2012-12-13 10:01 编辑

后台发送按键,SendKeys不行

可以考虑调用api

vbs调用api,一个是用第三方软件dynwrap.dll
一个是用Excel,如果你装了Excel

还有你的后台不知道是什么意思

如果你可以在屏幕上看到该窗口,并且该窗口是活动窗口
那么也可以用SendKeys

objwsh.SendKeys strRead    '向当前活动窗口发送按键
'下面是操作键的发送代码
退格键             {BACKSPACE}、{BS} 或 {BKSP}
BREAK              {BREAK}
CAPS LOCK          {CAPSLOCK}
DEL 或 DELETE      {DELETE} 或 {DEL}
向下键             {DOWN}
END                {END}
ENTER              {ENTER} 或 ~
ESC                {ESC}
HELP               {HELP}
HOME               {HOME}
INS 或 INSERT      {INSERT} 或 {INS}
向左键             {LEFT}
NUM LOCK           {NUMLOCK}
PAGE DOWN          {PGDN}
PAGE UP            {PGUP}
向右键             {RIGHT}
SCROLL LOCK        {SCROLLLOCK}
TAB                {TAB}
向上键             {UP}
F1 至 F12          {F1} 至 {F12}
SHIFT              +
CTRL               ^
ALT                %
+ { 等修饰符       {+} {{} {^} {}} {%}

'如果在按 e 和 c 的同时按 SHIFT 键,则发送字符串参数 +(ec)
'可发送一个键的重复键击。如10次x,为{x 10},但不可发送10次组合键,如Ctrl+x
'不能发送 PRINT SCREEN 键 {PRTSC}
'常用 Wscript.Sleep 来延时若干毫秒发送按键,避免程序来不及响应


比如你的代码可以用vbs这么写

  1. Set objWsh = CreateObject("WScript.Shell")
  2. objWsh.AppActivate "t - 记事本"
  3. objwsh.SendKeys "it"
  4. Wsctipt.Sleep 100
  5. objwsh.SendKeys " "
  6. Wsctipt.Sleep 100
  7. objwsh.SendKeys "is"
  8. Wsctipt.Sleep 100
  9. objwsh.SendKeys " 9"
  10. Wsctipt.Sleep 100
  11. objwsh.SendKeys "{Enter}"
复制代码

作者: zgh7878788    时间: 2012-12-13 20:35

回复 6# czjt1234


    非常感谢老师!我用的是一个模拟显示的程序,它是集显示和按键一体的,我想对这个程序模拟按键进行设置,比如,我按A3,这个模拟按键程序就进入相应菜单,我能看到这个按键过程,但是用SENDKEY是一个前台命令,必须保证电脑没人动,否则就不知道发送到哪去了,所以我就想把它转换成后台命令,这样,我只要开着模拟按键程序就可以用电脑做其他事情了。可我不会后台,网上找了好久,也没有老师帮我。确实太困惑了。网上找了个按键精灵版的后台向记事本发送,也不懂怎么移植到纯VBS上来。老师说的API,具体我的知识有限,所以我也不懂,恳请老师写个简单的实例,小可不剩感激!非常感谢!
作者: zgh7878788    时间: 2012-12-13 20:39

回复 6# czjt1234
主界面[attach]5965[/attach]我按31后变成[attach]5966[/attach]
作者: zgh7878788    时间: 2012-12-13 20:42

这个是按键精灵版的后台向记事本发送按键的例子
'获得符合标题为"t - 记事本"的窗口句柄
HwndEx = Plugin.Window.Find(0, "t - 记事本")
If HwndEx = 0 Then
MsgBox "没有找到符合的窗口,请检查标题是否正确"
End If
'获得记事本子窗口,类名为"Edit"
Hwnd = Plugin.Window.FindEx(HwndEx, 0, "Edit", 0)
'向指定窗口输入一个按键,按键码49为1键
Call Plugin.Bkgnd.KeyPress(Hwnd, 49)
Delay 500
'向指定窗口输入一个按键,按键码65为A键
Call Plugin.Bkgnd.KeyPress(Hwnd, 65)
Delay 500
'向指定窗口输入一个按键,按键码13为回车键
Call Plugin.Bkgnd.KeyPress(Hwnd, 13)
Delay 500
'向指定窗口发送一个文本消息
Call Plugin.Bkgnd.SendString(Hwnd, "我是文本内容,OY!")
作者: czjt1234    时间: 2012-12-14 08:52

6楼的vbs也是前台的,不行

按键精灵我没用过,不过看9楼的代码,用到了句柄,那就是调用了api

我找了个vbs调用api的例子,你研究下,需要用到dynwrap.dll文件

有2个版本,一个36K,一个44K,都可以用
作者: czjt1234    时间: 2012-12-14 09:02

Declare Function keybd_event Lib "user32" Alias "keybd_event" (ByVal bVk As Byte, ByVal bScan As Byte, ByVal dwFlags As Long, ByVal dwExtraInfo As Long)

发送按键用这个api

这里有api原型和vbs调用的格式
  1. Dim UserWrap,hWnd
  2. Set UserWrap = CreateObject("DynamicWrapper")
  3. 'Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
  4. UserWrap.Register "USER32.DLL", "FindWindow", "I=ss", "f=s", "R=l"
  5. 'Declare Function SetWindowPos Lib "user32" Alias "SetWindowPos" (ByVal hwnd As Long, ByVal hWndInsertAfter As Long, ByVal x As Long, ByVal y As Long, ByVal cx As Long, ByVal cy As Long, ByVal wFlags As Long) As Long
  6. UserWrap.Register "USER32.DLL", "SetWindowPos", "I=Hllllll", "f=s", "R=l"
  7. hWnd = UserWrap.FindWindow(vbNullString, "计算器")
  8. UserWrap.SetWindowPos hWnd, -1, 0, 0, 0, 0, 3
  9. MsgBox "现在将鼠标移到左上角!"
  10. 'Declare Function SetCursorPos Lib "user32" (ByVal X As Long, ByVal Y As Long) As Long
  11. UserWrap.Register "USER32.DLL", "SetCursorPos", "I=ll", "f=s", "R=l"
  12. UserWrap.SetCursorPos 0,0
复制代码

作者: czjt1234    时间: 2012-12-14 09:08

REM i: (Argument Type)
REM 'a', sizeof(IDispatch*), VT_DISPATCH}        // a IDispatch*
REM 'c', sizeof(unsigned char), VT_I4}                // c signed char
REM 'd', sizeof(double), VT_R8}                        // d 8 byte real
REM 'f', sizeof(float), VT_R4}                        // f 4 byte real
REM 'k', sizeof(IUnknown*), VT_UNKNOWN}                // k IUnknown*
REM 'h', sizeof(long), VT_I4}                        // h HANDLE
REM 'l', sizeof(long), VT_I4}                        // l long
REM 'p', sizeof(void*), VT_PTR}                        // p pointer
REM 's', sizeof(BSTR), VT_LPSTR}                // s string
REM 't', sizeof(short), VT_I2}                        // t short
REM 'u', sizeof(UINT), VT_UINT}                        // u unsigned int
REM 'w', sizeof(BSTR), VT_LPWSTR}                // w wide string

REM f: (Call Method)
REM 'm' - DC_MICROSOFT 0x0000, Default
REM 'b' - DC_BORLAND 0x0001, Borland compat
REM 's' - DC_CALL_STD 0x0020, __stdcall
REM 'c' - DC_CALL_CDECL 0x0010, __cdecl
REM '4' - DC_RETVAL_MATH4 0x0100, Return value in ST
REM '8' - DC_RETVAL_MATH8 0x0200, Return value in ST

REM r: (Return Type)
REM Same as i

上面是"I=ss", "f=s", "R=l"参数
I是输入,s代表一个String类型的参数,
f=s不用管,照抄
R是输出

但是这种调用办法有很多局限,比如指针类型的参数就不行,自定义类型的参数也不行

用excel调用,格式方面比较简单

下面是个例子
  1. Option Explicit
  2. Dim WshShell, oExcel, strRegKey, strCode, x, y
  3. Set oExcel = CreateObject("Excel.Application")
  4. set WshShell = CreateObject("wscript.Shell")
  5. strRegKey = "HKEY_CURRENT_USER\Software\Microsoft\Office\$\Excel\Security\AccessVBOM"
  6. strRegKey = Replace(strRegKey, "$", oExcel.Version)
  7. '生成注册表路径,oExcel.Version 是当前版本号
  8. WshShell.RegWrite strRegKey, 1, "REG_DWORD"
  9. '写如注册表,1表示设置安全级别为低,这样添加宏就不会有安全提示了
  10. strCode = _
  11. "Private Declare Function SetCursorPos Lib ""user32"" (ByVal x As Long, ByVal y As Long) As Long" & vbCrLf & _
  12.                                                                                                     vbCrLf & _
  13. "Private Type POINTAPI"                                                                           & vbCrLf & _
  14.     "X As Long"                                                                                   & vbCrLf & _
  15.     "Y As Long"                                                                                   & vbCrLf & _
  16. "End Type"                                                                                        & vbCrLf & _
  17.                                                                                                     vbCrLf & _
  18. "Private Declare Function GetCursorPos Lib ""user32"" (lpPoint As POINTAPI) As Long"              & vbCrLf & _
  19.                                                                                                     vbCrLf & _
  20. "Sub SetCursor(x as Long, y as Long)"                                                             & vbCrLf & _
  21.     "SetCursorPos x, y"                                                                           & vbCrLf & _
  22. "End Sub"                                                                                         & vbCrLf & _
  23.                                                                                                     vbCrLf & _
  24. "Public Function GetXCursorPos() As Long"                                                         & vbCrLf & _
  25.     "Dim pt As POINTAPI"                                                                          & vbCrLf & _
  26.     "GetCursorPos pt"                                                                             & vbCrLf & _
  27.     "GetXCursorPos = pt.X"                                                                        & vbCrLf & _
  28. "End Function"                                                                                    & vbCrLf & _
  29.                                                                                                     vbCrLf & _
  30. "Public Function GetYCursorPos() As Long"                                                         & vbCrLf & _
  31.     "Dim pt As POINTAPI"                                                                          & vbCrLf & _
  32.     "GetCursorPos pt"                                                                             & vbCrLf & _
  33.     "GetYCursorPos = pt.Y"                                                                        & vbCrLf & _
  34. "End Function"
  35. oExcel.Workbooks.Add.VBProject.VBComponents.Add(1).CodeModule.AddFromString strCode
  36. x = oExcel.Run("GetXCursorPos")
  37. y = oExcel.Run("GetYCursorPos")
  38. WScript.Echo x, y
  39. oExcel.Run "SetCursor", 1024, 768
  40. oExcel.DisplayAlerts = False
  41. oExcel.Workbooks.Add.Close
  42. oExcel.Quit
复制代码

作者: czjt1234    时间: 2012-12-14 09:13

本帖最后由 czjt1234 于 2012-12-14 09:16 编辑

按键精灵屏蔽了具体的api,给你固定格式直接调用,很方便

看它代码,应该是先获取句柄,再向指定句柄发送按键,不知道是哪个api

正好我也想研究“向指定句柄发送按键”,我们一起交流交流
作者: zgh7878788    时间: 2012-12-14 20:14

回复 13# czjt1234

非常感谢老师!给您添麻烦了!我先看看,研究一下再来说说。谢谢!非常感谢!!!!
作者: zgh7878788    时间: 2012-12-14 20:32

回复 12# czjt1234

老师,12L那个例子好像是获取鼠标坐标的,实际应用中不知道该怎么用?11L的Set UserWrap = CreateObject("DynamicWrapper")报错,说ActiveX部件不能创建对象:'DynamicWrapper'
作者: czjt1234    时间: 2012-12-14 20:45

注册10楼的dll文件先
作者: zhangop9    时间: 2021-1-2 15:14

窗口模拟点击按键




欢迎光临 批处理之家 (http://www.bathome.net/) Powered by Discuz! 7.2