在WebBrowser中通过模拟键盘鼠标操控网页中的文件上传控件
引言
这两天沉迷了Google SketchUp,刚刚玩够,一时兴起,研究了一下WebBrowser。
我在《WebBrowser控件使用技巧分享》一文中曾谈到过“我现在可以通过WebBrowser实现对各种Html元素的操控,唯独无法控制Html的上传控件”,出于安全原因,IE没有对上传控件提供操控支持,这使得我们没法像控制其他控件一样用简单的代码进行赋值。
比较实际的解决方案就是模拟操作了,下面我就将演示通过键盘、鼠标两种方式模拟点击“浏览”按钮,然后配合键盘模拟输入文件路径,并按回车键确认。
初始环境
测试使用了一个简单的HTML页面,页中各个位置中分布了一些文件上传控件,有些是直接放置的,有些是横向排列的,有些是嵌套在表格中的,用以测试不同位置的触发效果:
将此页面用WebBrowser控件加载。
在程序界面中,我放置了一些控件用于选择上传文件所在目录,测试时首先选定一个包含有文件的目录,然后从中随机抽选一个文件填写到上传控件中:
并在代码中建立了一个辅助方法,用以读取页面上所有的文件上传控件,在测试时也是从中随机抽取一个进行操控:
List<HtmlElement> 读取上传控件()
{
var l = new
List<HtmlElement>();
foreach (HtmlElement f in webBrowser1.Document.GetElementsByTagName("input"))
{
if (f.GetAttribute("type")
== "file")
{
l.Add(f);
}
}
return l;
}
在类中定义了一个Random类型成员变量用于生成随机数:
Random R = new Random();
此外还定义了一系列方法,用于在点击按钮后,延迟3秒以等待文件浏览对话框打开,然后模拟输入文件路径,再模拟输入回车键确定:
void 延迟操作对话框(string 填写文件路径)
{
button1.Enabled
= button2.Enabled
= button3.Enabled
= false;
BackgroundWorker
b = new BackgroundWorker();
b.RunWorkerCompleted
+= new RunWorkerCompletedEventHandler(b_RunWorkerCompleted);
b.DoWork
+= new DoWorkEventHandler(b_DoWork);
b.RunWorkerAsync(填写文件路径);
}
void b_DoWork(object sender, DoWorkEventArgs e)
{
Thread.Sleep(3000);
e.Result
= e.Argument;
}
void b_RunWorkerCompleted(object
sender, RunWorkerCompletedEventArgs
e)
{
SendKeys.Send(e.Result
as string);
SendKeys.Send("{Enter}");
button1.Enabled
= button2.Enabled
= button3.Enabled
= true;
}
这里就是通过使用BackgroundWorker组件在后台延迟3秒,延迟结束后在回调事件中进行操作。
键盘模拟方式
先看录制的动画:
在这里首先选择了一个上传文件所在目录,然后进行了几次键盘模拟操作测试。
键盘模拟的操作流程如下:
首先激活WebBrowser控件
然后让文件上传控件获取焦点,这时光标会处于文件上传控件左侧的文本框内
模拟输入Tab键切换焦点到“浏览..”按钮
模拟输入空格键点击该按钮
然后就是延迟3秒等待文件选取对话框显示,模拟输入文件路径并模拟输入回车键即可
主要代码如下:
private void button1_Click(object
sender, EventArgs
e)
{
var l = 读取上传控件();
var s = Directory.GetFiles(folderBrowserDialog1.SelectedPath);
键盘操作(l[R.Next(l.Count)], s[R.Next(s.Length)]);
}
void 键盘操作(HtmlElement
元素, string 填写文件路径)
{
webBrowser1.Select();
webBrowser1.Focus();
元素.Focus();
SendKeys.Send("{Tab}");
SendKeys.Send("
");
延迟操作对话框(填写文件路径);
}
鼠标模拟方式
还是先看录制的动画:
鼠标模拟的主要流程是:
首先递归计算页面中的文件上传控件相对于页面左上角的坐标位置
接着再递归计算WebBrowser控件相对于屏幕左上角的位置
在将位置值加上控件自身宽度及高度,并辅以修正值,以确保鼠标能够点到按钮上面
移动鼠标到计算好的位置处
单击鼠标
然后也是延迟3秒等待文件选取对话框显示,模拟输入文件路径并模拟输入回车键
递归计算页面元素相对于页面坐上角位置的函数:
Point 计算坐标(HtmlElement
元素, Point 起始坐标)
{
var p = 起始坐标;
p.Offset(元素.OffsetRectangle.Location);
return 元素.OffsetParent == null ?
p : 计算坐标(元素.OffsetParent,
p);
}
递归计算控件相对于屏幕左上角位置的函数:
private Point 计算坐标(Control 控件, Point 起始坐标)
{
var p = 起始坐标;
p.Offset(控件.Location);
return 控件.Parent ==
null ? p : 计算坐标(控件.Parent,
p);
}
此外,为了模拟鼠标移动和点击,还需要引入Windows API:
[DllImport("User32")]
public extern static
void SetCursorPos(int x, int
y);
[DllImport("user32.dll")]
static extern void
mouse_event(MouseEventFlag flags,
int dx, int
dy, uint data, int extraInfo);
[Flags]
enum MouseEventFlag :
uint
{
Move =
0x0001,
LeftDown =
0x0002,
LeftUp =
0x0004,
RightDown =
0x0008,
RightUp =
0x0010,
MiddleDown =
0x0020,
MiddleUp =
0x0040,
XDown =
0x0080,
XUp =
0x0100,
Wheel =
0x0800,
VirtualDesk =
0x4000,
Absolute =
0x8000
}
主要代码如下:
private void button2_Click(object
sender, EventArgs
e)
{
var l = 读取上传控件();
var s = Directory.GetFiles(folderBrowserDialog1.SelectedPath);
鼠标操作(l[R.Next(l.Count)], s[R.Next(s.Length)]);
}
void 鼠标操作(HtmlElement
元素, string 填写文件路径)
{
var p = 计算坐标(元素, new Point());
p =
计算坐标(webBrowser1, p);
p.Offset(元素.OffsetRectangle.Width -
5, 元素.OffsetRectangle.Height +
15);
SetCursorPos(p.X,
p.Y);
mouse_event(MouseEventFlag.LeftDown |
MouseEventFlag.LeftUp,
0, 0,
0, 0);
延迟操作对话框(填写文件路径);
}
总结
两种方法中推荐使用键盘模拟方法,简单而直接;鼠标模拟方法需要使用到API,还需要精确计算,并且如果页面带有滚动条,且滚动条进行了滚动或文件上传控件处于可视区之外的话,将无法通过上述方法计算和操控,而其优点仅仅是直观一些而已。
下载本文的示例源代码:http://www.uushare.com/user/icesee/file/1869210
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。