通过api获取句柄控制其他窗体

很多时候,编写程序模拟鼠标和键盘操作可以方便的实现你需要的功能,而不需要对方程序为你开放接口。比如,操作飞信定时发送短信等。我之前开发过飞信耗子,用的是对飞信协议进行抓包,然后分析协议,进而模拟协议的执行,开发出了客户端,与移动服务器进行通信,但是这有一些缺点。如果移动的服务器对接口进行变更,我所编写的客户端也要进行相应的升级。如果服务器的协议进行了更改,甚至个人编写的这种第三方客户端需要重写。而我个人也没有这个时间和精力,或者说没有足够的利益支撑我继续去重构飞信耗子。因此,这款还算优秀的软件,现在就束之高阁了,我自己也觉得遗憾。上周,某项目验收,需要修改界面,但是零时找不到源码了。我在两三个小时内要解决这个问题,时间紧迫。我突然想起室友以前做过模拟鼠标键盘去发送飞信消息的小程序。于是我赶紧电话咨询了一下。然后掌握了这个技巧,按时解决了问题。我觉得这个技巧还是很有用的,现总结如下:
首先,引入如下三个API接口:

[DllImport("user32.dll")]

public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

[DllImport("User32.dll", EntryPoint = "SendMessage")]

private static extern int SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, stringlParam);

[DllImport("User32.dll ")]

public static extern IntPtr FindWindowEx(IntPtr parent, IntPtr childe, string strclass, string FrmText);

第一个与第三个是用于查找窗口句柄的,凡运行于Windows上的窗口,都具有句柄。窗口上的文本框,按钮之类的,也有其句柄(可看作子窗口句柄)。这些句柄的类型可以通过

Spy++进行查询。比如C语言编写的程序中,文本框的句柄类型一般为“EDIT”,C#写的程序则不是,可以具体去查。第二个接口则是用于向窗口发送各种消息,比如向文本框发送

字符串,或者向按钮发送按下与弹起的消息等。详细解释如下:

IntPtr hwnd = FindWindow(null, "无标题 - 记事本");

这是用于查找操作系统中打开的窗口中标题名为无标题 - 记事本的窗口。第一个参数是此窗口的类型。这两个参数知道一

个即可,另一个可以填null。但是如果是用窗口类型查找,则可能只能得到其中的一个窗口。因此通过标题进行查找是非常方便的。

IntPtr htextbox = FindWindowEx(hwnd, IntPtr.Zero, "EDIT", null);

这个函数用于获得窗口中子窗口的句柄,子窗口指的其实就是窗口中的各种控件。第一个参数是父窗口的句柄,第二个参数指示获得的是同一类型中的第几个子窗口。填

IntPtr.Zero则表示获得第一个子窗口。第三个参数表示你需要找的子窗口的类型,第四个参数一般为null。如果一个窗口中有两个文本框,那么可以用如下操作获得第二个文本框

的句柄。

IntPtr htextbox = FindWindowEx(hwnd, IntPtr.Zero, "EDIT", null);

IntPtr htextbox2 = FindWindowEx(hwnd, htextbox, "EDIT", null);//填上次获得的句柄,可以得到下一个的句柄。

这里只是先将第二个参数填为IntPtr.Zero,获取第一个EDIT类型的文本框,然后第二次调用时,再将第二参数填为第一个文本框的句柄,那么执行返回的就是下一个文本框的句柄

了。因此htextbox2得到的就是第二文本框的句柄。
在可以自由获得各种窗口及其上控件的句柄后,我们就可以向其发送各种消息进行鼠标和键盘的模拟了。比如:

SendMessage(htextbox, WM_SETTEXT, IntPtr.Zero, name);

这句是为文本框填写相应的字符串name。

IntPtr hbutton = FindWindowEx(hwnd, IntPtr.Zero, "BUTTON", null);

SendMessage(hbutton, WM_LBUTTONDOWN, IntPtr.Zero, null);

SendMessage(hbutton, WM_LBUTTONUP, IntPtr.Zero, null);

这三句是获得了窗口的一个button,然后发送按下,弹起消息给它,模拟了点击鼠标的动作。
SendMessage函数的第一个参数是窗口句柄,或者窗口中控件的句柄,第二个参数是消息的类型Flag,这些值是在API的一些头文件中定义好的。你要是在C#中用,就自己去定义他们,比如

constint WM_SETTEXT =0x000C;constint WM_LBUTTONDOWN =0x0201;constint WM_LBUTTONUP =0x0202;constint WM_CLOSE =0x0010;

还有其他的类型Flag,可以参考上一篇Blog查询,也可以去查MSDN。第三个参数和第四个参数都是消息的具体内容。一般我们用的是最后一个参数。第三个参数填为IntPtr.Zero。

当然如果是鼠标的动作,那么最后一个参数就是null。

SendMessage(htextbox, WM_SETTEXT, IntPtr.Zero, name);//填写文本框。

SendMessage(hbutton, WM_LBUTTONDOWN, IntPtr.Zero, null);//鼠标按下按钮。

时间: 2024-08-30 02:10:53

通过api获取句柄控制其他窗体的相关文章

一个程序通过窗体句柄控制另一个窗体

接下来,我们来演示不同程序中,怎么通过窗体句柄控制其它程序窗体. 演示的例子是:控制系统的记事本窗体,先移动,再最大化,最后关闭 要求:桌面上有一个记事本,名称是:测试文本.txt - 记事本,保证是打开的 界面只有一个按钮,btnCloseText 引用的windowapi函数dll如下: /// <summary> /// 获取窗体的句柄函数 /// </summary> /// <param name="lpClassName">窗口类名<

通过API获取统计信息时报Access denied错误处理记录

通过API获取HDFS统计信息时报Access denied错误信息,错误信息如下: org.apache.hadoop.ipc.RemoteException(org.apache.hadoop.security.AccessControlException): Access denied for user xusweeter. Superuser privilege is required at org.apache.hadoop.hdfs.server.namenode.FSPermiss

获取句柄的类型以及对应的ID序号

遍历所有进程下的所有句柄,以及对应句柄类型. 一丶简介 在有的时候.我们会需要对应句柄名字.以及句柄类型的名称. 以及它所对应的的ID. 因为每个系统不一样.所以每次都是不一样的. 有的时候我们就需要借助Pchunter等类似的 Ark工具查看句柄名字. 以及对应的类型. 二丶原理讲解 想要获取 指定进程下的所有句柄,以及句柄名字. 句柄类型.我们只需要几步即可. 1.使用未导出API ZwQuerySystemInformation 获取系统所有进程信息. 2.根据PID打开进程句柄.(可以跳

CloudStack API访问权限控制

在我写开始之前,请先看下CS中国社区的一篇文章http://www.cloudstack-china.org/2012/12/1465.html,在第1点里讲了关于权限级别,command属性文件位置等问题.不过4.3现在的除了command.properties外,作者提到的其它properties文件现在好像都没有了,而且command里面现在形如***command=15,"="后面不再有处理请求命令的类. API请求由ApiServlet拦截后,会调用verifyRequest

开源项目成熟度分析工具-利用github api获取代码库的信息

1.github api github api是http形式的api,功能还是比较丰富的,博主因为项目的原因主要用到的是提取project信息这项功能,返回的数据是JSON格式. api页:https://developer.github.com/v3/ Options: (H) means HTTP/HTTPS only, (F) means FTP only --anyauth Pick "any" authentication method (H) -a, --append Ap

Web Api 获取post json数据

这周在做一个webApi的模拟后台.遇到些问题.和大家分享一下,以前没有搞过webapi.所以不是太懂. 当我发post请求的json数据过来的时候,如果我用context.Request .Form去收的时候会发现,一小半的json数据跑到了Key里面,其他数据在form[0]中,很奇怪.后来恍然大悟我发送的又不是表单干嘛用表单去接收,然后去用HttpContext.Current.Request.InputStream.Read(byts, 0, byts.Length);直接读取流然后再转

C# 网络编程之通过豆瓣API获取书籍信息(一)

这篇文章主要是讲述如何通过豆瓣API获取书籍的信息,起初看到这个内容我最初的想法是在"C# 网络编程之网页简单下载实现"中通过HttpWebResponse类下载源码,再通过正则表达式分析获取结点标签得到信息.但后来发现可以通过豆瓣API提供的编程接口实现. 该文章仅是基础性C#网络编程文章,尝试测试了下豆瓣API,并没什么高深的内容.但希望对大家有所帮助,仅供学习. (警告:文章仅供参考,提供一种想法,否则访问多次-10次被403 forbidden莫怪.建议认证使用豆瓣API) 一

调用ZoomEye API获取信息

最近在提高自己编程能力,拿一些实用的小工具练下.该脚本为python语言,主要涉及模块urllib,json,os模块. 功能:调用ZoomEye API获取信息 import urllib.request import json import os def login(): username = input("username:") password = input("password:") url = "https://api.zoomeye.org/

【转】百度API获取城市名地名(附源码)

在做一个软件时,用到了定位功能.网上有很多关于google 的GPS定位,但网上关于google定位都没有用, 搜索下原因:(这里建议大家在中国就尽量不使用系统自带的定位) 因为Google的服务器不在中国(就算能网上关于定位的代码能用,那也非常的慢,除非你的应用是在国外使用)    由于网络等原因所以定位一般会失败 于是转向使用百度api来定位. 所用到的百度API参考地址. 取得位置的百度官方sdk参考 Android定位SDK 由坐标获取地址方法参考 Geocoding API 的 7.逆