在WebBrowser中通过模拟键盘鼠标操控网页中的文件上传控件

简介:

引言

image这两天沉迷了Google SketchUp,刚刚玩够,一时兴起,研究了一下WebBrowser。

我在《WebBrowser控件使用技巧分享》一文中曾谈到过“我现在可以通过WebBrowser实现对各种Html元素的操控,唯独无法控制Html的上传控件”,出于安全原因,IE没有对上传控件提供操控支持,这使得我们没法像控制其他控件一样用简单的代码进行赋值。

比较实际的解决方案就是模拟操作了,下面我就将演示通过键盘、鼠标两种方式模拟点击“浏览”按钮,然后配合键盘模拟输入文件路径,并按回车键确认。

初始环境

测试使用了一个简单的HTML页面,页中各个位置中分布了一些文件上传控件,有些是直接放置的,有些是横向排列的,有些是嵌套在表格中的,用以测试不同位置的触发效果:

image 

将此页面用WebBrowser控件加载。

在程序界面中,我放置了一些控件用于选择上传文件所在目录,测试时首先选定一个包含有文件的目录,然后从中随机抽选一个文件填写到上传控件中:

image

并在代码中建立了一个辅助方法,用以读取页面上所有的文件上传控件,在测试时也是从中随机抽取一个进行操控:

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秒,延迟结束后在回调事件中进行操作。

键盘模拟方式

先看录制的动画:

2009-8-5 23-01-36

在这里首先选择了一个上传文件所在目录,然后进行了几次键盘模拟操作测试。

键盘模拟的操作流程如下:

首先激活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(" ");

    延迟操作对话框(填写文件路径);

}

鼠标模拟方式

还是先看录制的动画:

2009-8-5 23-16-51

鼠标模拟的主要流程是:

首先递归计算页面中的文件上传控件相对于页面左上角的坐标位置

接着再递归计算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, 0000);

    延迟操作对话框(填写文件路径);

}

总结

两种方法中推荐使用键盘模拟方法,简单而直接;鼠标模拟方法需要使用到API,还需要精确计算,并且如果页面带有滚动条,且滚动条进行了滚动或文件上传控件处于可视区之外的话,将无法通过上述方法计算和操控,而其优点仅仅是直观一些而已。

 

下载本文的示例源代码:http://www.uushare.com/user/icesee/file/1869210

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


本文转自斯克迪亚博客园博客,原文链接http://www.cnblogs.com/SkyD/archive/2009/08/06/1540021.html,如需转载请自行联系原作者

相关文章
|
Web App开发 前端开发
浏览器鼠标点击特效
浏览器鼠标点击特效
61 0
墨刀右键菜单被浏览器右键菜单遮挡导致墨刀右键菜单无法使用
墨刀右键菜单被浏览器右键菜单遮挡导致墨刀右键菜单无法使用
104 0
|
JavaScript 前端开发 API
前端|获取网页中鼠标选中文字
前端|获取网页中鼠标选中文字
249 0
|
前端开发 C# Windows
WPF鼠标、键盘、拖拽事件、用行为封装事件
本文主要介绍了WPF中常用的鼠标事件、键盘事件以及注意事项,同时使用一个案例讲解了拓展事件。除此之外,本文还讲述如何用行为(Behavior)来封装事件。
网页鼠标点击特效代码
我在网页的源代码中找到了这个鼠标点击特效代码,贴在下面。
165 0
|
C#
C# WPF 中用代码模拟鼠标和键盘的操作
原文:C# WPF 中用代码模拟鼠标和键盘的操作   原文地址   C#开发者都知道,在Winform开发中,SendKeys类提供的方法是很实用的。
2245 0
|
C# Windows
WPF 窗体中获取键盘和鼠标无操作时的超时提示
原文:WPF 窗体中获取键盘和鼠标无操作时的超时提示 通过调用Windows API中的GetLastInputInfo来获取最后一次输入的时间 using System;using System.
899 0