原文:[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. php实现旋转数组的最小数字

    php实现旋转数组的最小数字 一.总结 1.题目描述定位法:掐准输入输出这两个关键词,然后题目意思就很清晰了 2.这个题目就是找数组的最小值 二.php实现旋转数组的最小数字 题目描述: 把一个数组最 ...

  2. 分层抽样(Stratified sampling)

    1. 基本概念 统计学理论中,分层抽样针对的是对一个总体(population)进行抽样的方法.尤其适用于当总体内部,子总体(subpopulations)间差异较大时.每一个 subpopulati ...

  3. GDB(十)--调试正在运行的进程

    我编写了一个循环: long i;    for (i = 0; i < 999999; i++) {        mt.a += 1;        sleep(1);    }把它编译成a ...

  4. thinkphp5 tp5 获取模块名控制器名方法名

    <?php namespace app\index\controller; use think\Db; use think\Controller; class Base extends Cont ...

  5. php 中英文字符串截取,字符串长度

    在做PHP开发的时候,由于我国的语言环境问题,所以我们常常需要对中文进行处理.在PHP中,我们都知道有专门的mb_substr和mb_strlen函数,可以对中文进行截取和计算长度,但是,由于这些函数 ...

  6. 【54.08%】【BZOJ 1941】Hide and Seek

    Time Limit: 16 Sec  Memory Limit: 162 MB Submit: 919  Solved: 497 [Submit][Status][Discuss] Descript ...

  7. [GraphQL] Write a GraphQL Mutation

    In order to change the data that we can query for in a GraphQL Schema, we have to define what is cal ...

  8. RESET MASTER 和RESET SLAVE 命令的使用方法 注意事项

    RESET MASTER 删除所有index file 中记录的所有binlog 文件,将日志索引文件清空,创建一个新的日志文件,这个命令通常仅仅用于第一次用于搭建主从关系的时的主库,注意  rese ...

  9. Android Studio上手,基于VideoView的本地文件及流媒体播放器

    既然是第一个Android程序.少不了要Hello World. 1. 新建安卓project watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvZm0wNTE ...

  10. 一小时内破解16位强password

    password能够用来保护你的金融交易.你的社交网络站点,和其它貌似安全的在线站点的主机.人们常常说:"不要把字典里的单词用来做password.它们超级不安全". 但是,要是黑 ...