vfp调用外部程序 并且模拟键盘输入

qq_37289819 2017-01-09 05:38:59
调用外部exe文件后 希望在用户名和密码框中模拟键盘输入

FUNCTION mykeybd(Virtual_Key as Integer)
PRIVATE Virtual_Key &&键盘虚拟值,请参阅列表。
DECLARE keybd_event IN user32; &&键盘模拟API
SHORT bVk,; &&表示虚拟键值,其取值范围为1-254。
SHORT bScan,; &&该值为0
INTEGER dwFlags,; &&0按下,2弹起
INTEGER dwExtraInfo &&关于操作的附加说明,一般为0
DECLARE INTEGER MapVirtualKey IN user32;
INTEGER VK,;
INTEGER VI
DECLARE Sleep IN kernel32 INTEGER dwMilliseconds
= keybd_event(Virtual_Key, MapVirtualKey(Virtual_Key,0), 0, 0)
sleep(700)&&按键延时
= keybd_event(Virtual_Key, MapVirtualKey(Virtual_Key,0), 2, 0)
ENDFUNC

这个函数模拟键盘输入在vfp当前窗口有用,在外部程序似乎没用
...全文
1318 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
dfwxj 2017-02-05
  • 打赏
  • 举报
回复
好贴!先顶 相当有用,去年我已研究过,尚未实施。今年要解决了。我也是需要调用一个外部数据采集程序,自动输入用户名和密码登录后隐藏运行,在系统托盘中显示图标。 感谢taohua300、dkfdtf的指点~~~
kmyz_yyl 2017-01-15
  • 打赏
  • 举报
回复
能否请楼主贴出完整代码? 先感谢!
都市夜猫 2017-01-10
  • 打赏
  • 举报
回复
只有在需要挂接的文本控件补发得到句柄时,才转用模拟按键的方式,但也存在一些问题,例如,被挂接的窗口要置前,如果是最小化状态还得恢复,另一问题是还得判断中文输入法的状态 ... 如果只是写记事本,还是用消息机制比较简单,用下面代码试试:
#define WM_CHAR         0x0102
Declare Long FindWindowEx in win32api Long, Long, String, String
Declare Long SendMessage in win32api Long, Long, Long, Long

m.hWnd = FindWindowEx(0, 0, 'Notepad', Null)
If m.hWnd == 0
    MessageBox('先打开一个空记事本')
    Return .f.
EndIf
m.hEdit = FindWindowEx(m.hWnd, 0, 'Edit', Null)
If m.hEdit == 0
    ? '没找到记事本编辑区'
    Return .f.
EndIf

m.cTime = Time() + 0h0d0a      && 写入当前时间字符串
For m.ii = 1 to Len(m.cTime)
    m.cc = Substr(m.cTime, m.ii, 1)
    SendMessage(m.hEdit, WM_CHAR, Asc(m.cc), 0)
EndFor
taohua300 2017-01-10
  • 打赏
  • 举报
回复
以上简单测试通过 没有整理 另外调用其他程序在这里应该使用ShellExecuteEx 而不是ShellExecute ShellExecute执行的程序并没有等程序执行完就直接运行下面的代码 所以执行到下面的代码的时候ShellExecute执行的程序还不一定打开 这里notepad简单,加了inkey稍等 模拟用户名和密码还是建议使用版主的方法
taohua300 2017-01-10
  • 打赏
  • 举报
回复
Declare long AttachThreadInput In user32.dll long,long,integer && 连接线程输入
Declare long GetForegroundWindow In user32.dll && 获得当前顶层窗口句柄
Declare long GetCurrentThreadId In kernel32.dll && 获取当前进程ID
Declare integer GetWindowThreadProcessId In user32.dll long ,long @ && 获取创建制定窗口的进程ID
Declare long SetForegroundWindow In user32.dll long &&设置顶层窗口
Declare integer GetLastError In kernel32.dll 
Declare integer FindWindow In user32.dll string @ ,string @


*****************引用你3楼的代码*************
DECLARE INTEGER ShellExecute IN shell32.DLL INTEGER HWND,STRING lpszOP,STRING lpszFile,STRING lpszParams,STRING lpszDir,INTEGER fsshowcmd 
DECLARE INTEGER GetDesktopWindow IN win32api 
HWND = GetDesktopWindow() 
lpszOP = "open" 
* ?????????
lpszFile ="C:\WINDOWS\system32\notepad.exe"
lpszParams = "" 
lpszDir = "c:\temp" 
fsshowcmd = 1
* ??ShellExecute?? 
LNRETURN = ShellExecute(HWND, lpszOP,lpszFile, lpszParams, lpszDir,fsshowcmd)
*********************************************
Inkey(3)
lnNotepad = FindWindow("Notepad","无标题 - 记事本")


lnNotepadId = 0 &&记事本窗口进程id
lnMyId = 0&&当前进程id
GetWindowThreadProcessId(lnNotepad ,@lnNotepadId)
AttachThreadInput(GetWindowThreadProcessId(lnNotepad ,@lnNotepadId),GetCurrentThreadId(),1)&&共享进程

SetForegroundWindow(thisform.HWnd)
mykeybd(98) &&将你一楼的代码保存为mykeybd.prg
AttachThreadInput(GetWindowThreadProcessId(lnNotepad ,@lnNotepadId),GetCurrentThreadId(),0)&& 撤销共享

qq_37289819 2017-01-10
  • 打赏
  • 举报
回复
谢谢二楼给予的指点,受益匪浅。 查找了 AttachThreadInput 函数的使用 *******************************************************非vfp代码 // 获取创建前台窗口的线程 DWORD dwThread = GetWindowThreadProcessId(GetForegroundWindow(), NULL); // 将前台窗口线程贴附到当前线程(也就是程序A中的调用线程) AttachThreadInput(dwThread, GetCurrentThreadId(), TRUE); // 获取焦点窗口句柄 HWND hFocus = GetFocus(); // 解除贴附 AttachThreadInput(dwThread, GetCurrentThreadId(), FALSE); // 发送消息 PostMessage(hFocus, WM_KEYDOWN, VK_TAB, 0); ******************************************************* 似乎问题就快找到答案了,但还是不知道具体步骤如何实现,譬如模拟打开记事本如何才能输入字符“abc”?请多指点,谢谢! ******************************************************* vfp中 可执行 DECLARE INTEGER ShellExecute IN shell32.DLL INTEGER HWND,STRING lpszOP,STRING lpszFile,STRING lpszParams,STRING lpszDir,INTEGER fsshowcmd DECLARE INTEGER GetDesktopWindow IN win32api HWND = GetDesktopWindow() lpszOP = "open" * 指定要打开的文件名 lpszFile ="C:\WINDOWS\system32\notepad.exe" lpszParams = "" lpszDir = "c:\temp" fsshowcmd = 3 * 执行ShellExecute命令 LNRETURN = ShellExecute(HWND, lpszOP,lpszFile, lpszParams, lpszDir,fsshowcmd) *******************************************************
qq_37289819 2017-01-10
  • 打赏
  • 举报
回复
fsshowcmd = 3 &&这个值选3 lnNotepad = FindWindow(null,null) &&如果是其他窗口就都选空 顺利通过 非常棒!!非常感谢!!
qq_37289819 2017-01-10
  • 打赏
  • 举报
回复
高手指点果然名不虚传啊,学会了AttachThreadInput,GetWindowThreadProcessId,FindWindow三个函数的定义和使用 SetForegroundWindow(thisform.HWnd) 这一行暂时不用 另外 http://www.docin.com/p-431584778.html 指定了虚拟按键值 这样4楼代码顺利通过 非常感谢2楼 4楼神人!!
都市夜猫 2017-01-09
  • 打赏
  • 举报
回复
一楼代码只是模拟发送按键,有些概念先要清楚 Windows 默认将键盘输入放入活动线程的消息队列中,因此一楼的代码只会将按键发送给自己,要发送给其他进程的活动线程,必须先用 AttachThreadInput 将两个线程关联起来共享键盘消息 另外,如果外部进程要接收键盘字符的控件有窗口句柄的话,用 SetWindowText 或者发送 WM_SETEXT 消息跟更简单

2,718

社区成员

发帖
与我相关
我的任务
社区描述
VFP,是Microsoft公司推出的数据库开发软件,用它来开发数据库,既简单又方便。
社区管理员
  • VFP社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧