原文:[WPF] PerformClick ?

[WPF] PerformClick ? 

周银辉

WPF没有提供这个方法,还真是让人觉得有些讨厌啊。而关于这个嘛,Google中搜一下,一大堆,但一般是利用XXXAutomationPeer。

这个原本用于支持自动化测试的,被拿来干了这事,代码如下:

        public static void PerformClick(this Button button)        {            var peer =new ButtonAutomationPeer(button);            var invokeProv = peer.GetPattern(PatternInterface.Invoke) as IInvokeProvider;            if (invokeProv != null)            {                invokeProv.Invoke();            }        }

但很快地,你会发现去其依赖于具体的类:ButtonAutomationPeer, 所以WPF实现了一堆XXXAutomationPeer, 这多少让人觉得有些.... 比如“我想在任意UI元素上模拟下鼠标点击”,这种方法便不可行了,虽然有一堆Peer,再多也不是“任意”,那么用SendMessage吧,这才是王道,代码如下:

        public static void PerformClick(this UIElement element, Point point)        {            var window = Window.GetWindow(element);            if (window != null)            {                var windowHwnd = GetHwnd(window);                var locOfElement = element.TranslatePoint(new Point(0, 0), window);                var pointToWindow = new Point(point.X + locOfElement.X, point.Y + locOfElement.Y);                Int32 lparam = MakeLong((int)pointToWindow.X, (int)pointToWindow.Y);                // WM_LBUTTONDOWN = 0x0201                SendMessage(windowHwnd, WM_LBUTTONDOWN, 0, lparam);                // WM_LBUTTONUP = 0x0202;                SendMessage(windowHwnd, WM_LBUTTONUP, 0, lparam);            }        }        internal static int MakeLong(int lowWord, int highWord)        {            return (highWord << 16) | (lowWord & 0xffff);        }        internal static IntPtr GetHwnd(this Window window)        {            var winHelper = new WindowInteropHelper(window);            return winHelper.Handle;        }

这个方法可以拓展到任意UI元素上,但很奇怪的是:居然不会引发Button的Click事件!从效果上看,的确点击了,因为焦点都转移上去了。那好吧,再用用下面的方法吧:反射,我比较喜欢这个方式:

        public static void PerformClick(this ButtonBase button)        {            var method = button.GetType().GetMethod("OnClick",                 BindingFlags.NonPublic | BindingFlags.Instance);            if (method != null)            {                method.Invoke(button, null);            }            //button.Focus();        }

OK,总结一下:
第一种方法,依赖于具体的XXXPeer, 能力有限,不够灵活

第二种方法,较灵活,但由于SendMessage第一个参数要求传入hwnd,而WPF普通控件没有句柄,所以其依赖于窗口句柄,也就是该方法依赖窗口

第三种方法,我喜欢。有什么缺点吗?如果没有,为啥Google上的朋友们都用第一种方法?如果有,是啥?

-----------------------

[update]

最近看到一个开源项目, 专门模拟键盘和鼠标,非常棒: http://inputsimulator.codeplex.com/

源代码打包下载 : http://files.cnblogs.com/zhouyinhui/WindowsInput.zip

使用方法嘛,比如:

 var sim = new InputSimulator(); sim.Mouse.LeftButtonDown();

[WPF] PerformClick ?的更多相关文章

  1. 在WPF中使用依赖注入的方式创建视图

    在WPF中使用依赖注入的方式创建视图 0x00 问题的产生 互联网时代桌面开发真是越来越少了,很多应用都转到了浏览器端和移动智能终端,相应的软件开发上的新技术应用到桌面开发的文章也很少.我之前主要做W ...

  2. MVVM框架从WPF移植到UWP遇到的问题和解决方法

    MVVM框架从WPF移植到UWP遇到的问题和解决方法 0x00 起因 这几天开始学习UWP了,之前有WPF经验,所以总体感觉还可以,看了一些基础概念和主题,写了几个测试程序,突然想起来了前一段时间在W ...

  3. MVVM模式解析和在WPF中的实现(六) 用依赖注入的方式配置ViewModel并注册消息

    MVVM模式解析和在WPF中的实现(六) 用依赖注入的方式配置ViewModel并注册消息 系列目录: MVVM模式解析和在WPF中的实现(一)MVVM模式简介 MVVM模式解析和在WPF中的实现(二 ...

  4. MVVM模式解析和在WPF中的实现(五)View和ViewModel的通信

    MVVM模式解析和在WPF中的实现(五) View和ViewModel的通信 系列目录: MVVM模式解析和在WPF中的实现(一)MVVM模式简介 MVVM模式解析和在WPF中的实现(二)数据绑定 M ...

  5. MVVM设计模式和WPF中的实现(四)事件绑定

    MVVM设计模式和在WPF中的实现(四) 事件绑定 系列目录: MVVM模式解析和在WPF中的实现(一)MVVM模式简介 MVVM模式解析和在WPF中的实现(二)数据绑定 MVVM模式解析和在WPF中 ...

  6. MVVM模式解析和在WPF中的实现(三)命令绑定

    MVVM模式解析和在WPF中的实现(三) 命令绑定 系列目录: MVVM模式解析和在WPF中的实现(一)MVVM模式简介 MVVM模式解析和在WPF中的实现(二)数据绑定 MVVM模式解析和在WPF中 ...

  7. MVVM模式和在WPF中的实现(二)数据绑定

    MVVM模式解析和在WPF中的实现(二) 数据绑定 系列目录: MVVM模式解析和在WPF中的实现(一)MVVM模式简介 MVVM模式解析和在WPF中的实现(二)数据绑定 MVVM模式解析和在WPF中 ...

  8. MVVM模式和在WPF中的实现(一)MVVM模式简介

    MVVM模式解析和在WPF中的实现(一) MVVM模式简介 系列目录: MVVM模式解析和在WPF中的实现(一)MVVM模式简介 MVVM模式解析和在WPF中的实现(二)数据绑定 MVVM模式解析和在 ...

  9. 逆天通用水印支持Winform,WPF,Web,WP,Win10。支持位置选择(9个位置 ==》[X])

    常用技能:http://www.cnblogs.com/dunitian/p/4822808.html#skill 逆天博客:http://dnt.dkil.net 逆天通用水印扩展篇~新增剪贴板系列 ...

随机推荐

  1. Intellij IDEA中使用Debug

    Intellij IDEA中使用Debug Debug用来追踪代码的运行流程,通常在程序运行过程中出现异常,启用Debug模式可以分析定位异常发生的位置,以及在运行过程中参数的变化.通常我们也可以启用 ...

  2. MHA 一主两从搭建-脚本VIP-自动切换

    环境介绍:主机名 IP MHA角色 MySQL角色node1 192.168.56.26 Node MySQL Master node2 192.168.56.27 Node MySQL Master ...

  3. Loader之二:CursorLoader基本实例 分类: H1_ANDROID 2013-11-16 10:50 5447人阅读 评论(0) 收藏

    参考APIDEMO:sdk\samples\android-19\content\LoaderCursor 1.创建主布局文件,里面只包含一个Fragment. <FrameLayout xml ...

  4. Android shape画圆点

    <?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http: ...

  5. Android 为开发者准备的最佳 Android 函数库(2016 年版)

    本文是翻译自 CloudRAIL 的官方博客(https://cloudrail.com/best-android-libraries-for-developers/),本文中分享的 Android ...

  6. Tomcat结合Apache、Nginx实现高性能的web服务器

    一.Tomcat为什么需要与apache.nginx一起结合使用? Tomcat虽然是一个servlet和jsp容器,但是它也是一个轻量级的web服务器.它既可以处理动态内容,也可以处理静态内容.不过 ...

  7. [Node.js] Create a model to persist data in a Node.js LoopBack API

    In this lesson you will learn what a LoopBack model is, you will create a Product model using the Lo ...

  8. CSS学习小结

    接触了B/S的东西之后才发现自己须要学习的东西太多了.html.xml.JavaScript.jquery.HTMLdom.VBScript.ajax.jquery.json等等技术都是须要我们一一研 ...

  9. nuklear(A single-header ANSI C gui library,界面还不错)

    Nuklear This is a minimal state immediate mode graphical user interface toolkit written in ANSI C an ...

  10. 谷歌 AI 中国中心成立,人工智能势不可挡?

    昨日,谷歌在上海举办了一年一度的Google中国开发者大会.在本届大会上,谷歌云首席科学家李飞飞宣布了一个重磅消息,即在北京将成立谷歌AI中国中心.对于这个即将成立的AI中心谷歌寄予厚望,希望与中国本 ...