引言

这两天沉迷了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

下载本文的XPS版本:http://www.uushare.com/user/icesee/file/1869213

转载请遵循此协议:署名 - 非商业用途 - 保持一致

并保留此链接:http://skyd.cnblogs.com/

在WebBrowser中通过模拟键盘鼠标操控网页中的文件上传控件(转)的更多相关文章

  1. ASP.NET中的FileUpload文件上传控件的使用

    本篇文章教大家如何将客户端的图片或者文件上传到服务器: 无论是上传图片(.jpg .png .gif等等) 文档(word excel ppt 等等). 第一步:放入以下三个控件 Image控件,Fi ...

  2. js_ajax模拟form表单提交_多文件上传_支持单个删除

    需求场景: 用一个input type="file"按钮上传多张图片,可多次上传,可单独删除,最后使用ajax模拟form表单提交功能提交到指定方法中: 问题:由于只有一个file ...

  3. NeatUpload上传控件在asp.net中的使用

    1.先导包,Brettle.Web.NeatUpload.dll导进web层中,再添加到vs控件中. 2.把NeatUpload文件夹放到根目录下. 3.直接拉要用到的控件到页面上,在使用 <U ...

  4. vue+ElementUI项目中,上传控件为必填项,上传图片后清空提示信息

    (ps:以下是我在项目中遇到得问题及解决方法,希望对你们有帮助.如果还有其他方法,可以留言,谢谢) 一个表单页面,使用element-ui中el-upload上传图片,此项为必填项,然后写了校验规则, ...

  5. jquery中选择ID以什么字符开头的匹配主要用于多个上传控件的时候,id无法使用,而且class不起作用的时候

    $("[id^=remark]")选择ID以remark开头的所有数据进行匹配

  6. Eclipse中使用GIT将已提交到本地的文件上传至远程仓库

    GIT将已提交到本地的文件上传至远程仓库: 1.  右击项目——Team——Push to Upstream,即可将已保存在本地的文件上传推至GIT远程仓库.

  7. JQuery文件上传插件ajaxFileUpload在Asp.net MVC中的使用

    0 ajaxFileUpload简介 ajaxFileUpload插件是一个非常简单的基于Jquery的异步上传文件的插件,使用过程中发现很多与这个同名的,基于原始版本基础之上修改过的插件,文件版本比 ...

  8. 转:在Struts 2中实现文件上传

    (本文转自:http://www.blogjava.net/max/archive/2007/03/21/105124.html) 前一阵子有些朋友在电子邮件中问关于Struts 2实现文件上传的问题 ...

  9. 转:MVC中的文件上传

    上传文件与与上传数据区别 上传数据主要指json等简单字符串,上传文件指的是上传word.excel图片等.在上传数据的时候enctype默认为第一个application/x-www-form-ur ...

随机推荐

  1. (2016弱校联盟十一专场10.5) F. Fibonacci of Fibonacci

    题目链接 题目大意就是这个,先找出下标的循环节,再快速幂对20160519取余就行了. 找出下标循环节: #include <cstdio> #include <iostream&g ...

  2. 【jquery】字符ascii码转换函数

    js 字符ascii码转换函数 字符转ascii码:用charCodeAt();ascii码砖字符:用fromCharCode(); 看一个小例子 <script> str="A ...

  3. 如何用Jquery判断在键盘上敲的哪个按键

    有时候我们需要判断我们在键盘上敲了哪个键,这个需要查询下键盘上的键对应的值是多少,比如Enter键是13. 下面是Jquery代码,别忘了引用Jquery包哈. <script type=&qu ...

  4. ASP.NET 下载文件并继续执行JS解决方法

    需求说明:当用户点击按钮时使当前按钮为不可用,并打开新页面,关闭新页面时,按钮变为可用.并且如果不关闭新页面,当前按钮过10秒钟自动变为可用. 包含3个页面: 一.按钮页 前台代码:当刷新后采用js进 ...

  5. Shell之变量操作

    1.定义变量:为了避免与环境变量冲突,一般用小写:如pp="mydql,kdkfeof"; 第二赋值方案: 调用变量使用$符号: 变量叠加: 2.输出采用echo,如上图所示: 3 ...

  6. 关于快捷键 Ctrl+Alt+[方向键] 的知识

    在用PS作图时使用 Ctrl+Alt+[方向键]  组合建时屏幕莫名翻转, 平时电脑懒得维护所以略卡,我不会说一般早上起床摁了开机去上完厕所回来还--咳咳 刚按下时瞬间一黑,再黑,,继续黑--真是大吃 ...

  7. Loadrunner连接Mysql数据库

    1.库文件下载地址:http://files.cnblogs.com/files/xiaoxitest/MySQL_LoadRunner_libraries.zip 分别添加到Loadrunner b ...

  8. Linq to json

    Json.Net系列教程 4.Linq To JSON 一.Linq to JSON是用来干什么的? Linq to JSON是用来操作JSON对象的.可以用于快速查询,修改和创建JSON对象.当JS ...

  9. gbdt可视化

    gbdt的最大优点,和决策树一样,高度可解释,最喜欢的分类模型:) #!/usr/bin/env python #coding=gbk # ============================== ...

  10. probe函数何时调用的

    转自:http://blog.csdn.net/xiafeng1113/article/details/8030248 Linux中 probe函数何时调用的 所以的驱动教程上都说:只有设备和驱动的名 ...