[新手上路]批处理新手入门导读[视频教程]批处理基础视频教程[视频教程]VBS基础视频教程[批处理精品]批处理版照片整理器
[批处理精品]纯批处理备份&还原驱动[批处理精品]CMD命令50条不能说的秘密[在线下载]第三方命令行工具[在线帮助]VBScript / JScript 在线参考
返回列表 发帖

[问题求助] 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}"
这个问题困扰我好久了,麻烦各位老师赐教,谢谢!非常感谢!

  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
复制代码

QQ 20147578

TOP

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
'关闭文件对象,立刻保存到磁盘

QQ 20147578

TOP

回复 2# czjt1234


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

TOP

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

TOP

本帖最后由 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}"
复制代码

QQ 20147578

TOP

回复 6# czjt1234


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

TOP

回复 6# czjt1234
主界面[attach]5965[/attach]我按31后变成[attach]5966[/attach]

TOP

这个是按键精灵版的后台向记事本发送按键的例子
'获得符合标题为"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!")

TOP

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

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

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

有2个版本,一个36K,一个44K,都可以用

QQ 20147578

TOP

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
复制代码

QQ 20147578

TOP

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
复制代码

QQ 20147578

TOP

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

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

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

正好我也想研究“向指定句柄发送按键”,我们一起交流交流

QQ 20147578

TOP

回复 13# czjt1234

非常感谢老师!给您添麻烦了!我先看看,研究一下再来说说。谢谢!非常感谢!!!!

TOP

回复 12# czjt1234

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

TOP

返回列表