代码改变世界

一步一步分析Caliburn.Micro(二:绑定执行方法Message现学现卖之自定命令)

2012-08-17 10:12  旦旦  阅读(2513)  评论(1编辑  收藏  举报

还记得上章中说到的CM演示程序中出现的cal:Message.Attach="[Key Enter] = [EnterPressed]" ?在分析代码中可是见不到Key这个事件触发关键字的.看看CM是怎么允许让我们在适当的范围内修改吧.打开在官网上下载的原代码的samples目录下Caliburn.Micro.KeyBinding方案.打开解决方案发现项目很简洁没什么文件.KeyBindingBootstrapper.cs

对这个委托的重写会不会觉得让人觉得很特别呢.看上去很不习惯呢.让我们以一个正常的重写代码.演示下这段代码

protected override TriggerBase CreateTrigger(DependencyObjecttarget,stringtriggerText)

{

if(triggerText == null) {

var defaults = ConventionManager.GetElementConvention(target.GetType());

return defaults.CreateTrigger();

}

 

var triggerDetail = triggerText.Replace("[", string.Empty).Replace("]", string.Empty);

 

var splits = triggerDetail.Split((char[])null, StringSplitOptions.RemoveEmptyEntries);

if(splits[0] == "Key") {

var key = (Key)Enum.Parse(typeof(Key), splits[1], true);

return new KeyTrigger { Key = key };

}

return base.CreateTrigger (target, triggerText);

}

这样子的重写方式是否很特别呢?但红色区域的有问题喔.怎么只能支持单键响应.要是组合键怎么办呢(:[Ctrl+S] [Ctrl+Alt+S] [Ctrl+Alt+Shift+S]这样子的组合键怎么处理)还是看看KeyTrigger这个触发类

还好是有功能键的属性的,只是在解释这段代码上没有正确解释了.CM项目组的人员懒,还是想让我们自己去修正扩展呢.个人觉得应该是后者更有可能了.这我可是有根据的.Input目录下也就是KeyTrigger这个类所在的目录.大家会发现还有几个文件.那这几个文件中的类又是有什么功能呢?.看看其它文件发现处理的方式和样例中的方式也太大出入了吧?这些文件都是继承于System.ComponentModel.TypeConverter, System.Windows.Input.InputBinding,System.Windows.Input.InputGesture这都是硬件输入所用到的这有点复杂还是别理了.由相关文件看看发现是个特殊组合键处理.

特殊组合键基本上分为两类(:[ Ctrl+E,D] [ Ctrl+Alt+E,D][ Ctrl+E+D]  [ Ctrl+Alt+E+D])那对于这两类的是有什么区别的.第一次种如按住Ctrl后连续按ED键就会触发的功能我称为连续组合键(通常这是玩游戏时在用来触发作弊器用的,如格斗游戏的←+++A+B为普通大招,按着一个功能键后再依次连续输入←+++A+B变成了加强版大招一招KO对方秒杀).另一种为只有同时按住了几个键才触发的功能我称为并发组合键.键盘输入有个不足错为键盘同时按键响有上限不同品牌有不同的上限限制性比较大.而连续组合键就不会因硬件的问题产生影响.如果想在程序做个小功能程序如程序员的调试组件或小后门这也是个不错的选择.

而演示代码中的解释方式采用的应该是后一种的并发组合键.由于并发组合键的事件并不好处理硬件是一个问题另一个问题则是没有顺序性导致太容易触发.所以在分析演示代码中发现CM的做法是连续组合键的算法事件.看到这应该是我与CM项目成员的理解有所偏差吧,可能人家觉得功能键可以无序而普通键是有序的不存在连续组合键与并发组合键的区分吧.然后那个CM项目的人员好像没教我们怎么把System.Windows.Input.InputBinding,System.Windows.Input.InputGesture这类型接入到CM.CM你的演示代码都只是用TriggerBase<UIElement>来处理的吧.我再一分析不用TriggerBase<UIElement>来处理那可是要对你好几个地方的委托都要进行重写的不用这样子来让我们自己来学习学习吧.工作量太大下次再说CM留下的问题吧.(其实这时我在想了不会是写演示代码那位大哥觉得接入CM太麻烦了不写了但又不想把代码删除所以才产生这样子的局面).就自己以TriggerBase<UIElement>方式来写个连续组合键的方法吧.

连续组合重点是对连续输入键的验证.先把命令字符串转为按键转成数组(采用[ Ctrl+E,D] [ Ctrl+Alt+E,D]对这种字符解释.对键值的解释要注意个问题命令字符串一般输入的都是与物理键盘所显示字符一样的,但这字符并不是编程中所对应的字符那就可能要自己写段代码自己转换了).在输入键盘时就判断输入的键是否为第一元素的键值,是否话就等待下次输入键的判断与递进位的元素键值是一致.直到数组全部判断完成.只要其中任何一次输入出错都认为失败索引值归零.当然还要加上一个叫超时判断不可能等太久的吧.(代码就直接附上原码算法也不是核心的基本上都能想到的)

public bool IsEffectiveInputKeys(Key inputKey)

{

if (this.Keys == null || Keys.Length == 0) return false;

bool flag=false;

if (_keyIndex == 0) _lastInputTime = DateTime.Now;

 

if (_keyIndex == Keys.Length - 1)

{

if (KeyboardHelper.IsMatchInputKey(Keys[_keyIndex], inputKey, Modifiers) &&

DateTime.Now - _lastInputTime < _timeout)

{

flag = true;

}

_keyIndex = 0;

}

else

{

if (KeyboardHelper.IsMatchInputKey(Keys[_keyIndex], inputKey, Modifiers) &&

DateTime.Now - _lastInputTime < _timeout)

{

_lastInputTime = DateTime.Now;

_keyIndex++;

}

else

{

_keyIndex = 0;

}

}

return flag;

}

没想到还是出了个问题如果单以[Alt]的功能组合键,一个都不能成功触发,[Ctrl+Alt]的多个功能键组合都可以触发.这我就是在想是不是WPF的机制问题呢.大家应该记得在Windows系统下的窗口按了[Alt]功能键是触发了菜单的激活功能.输出信息找找原因.

看来真的是WPF的机制问题了.单按[Alt]键它的键状态为None,如果按别的键那可是有状态的.看来我也无能为力了.PS:如果想要做并发组合键的话就要用到Keyboard.GetKeyStates(inputKey)只要几个并运算为真就算成功触发.

自定命令字符这就算完成了.加了[Key {key}]如果有别的触发事件也可以封装起来这当然是与业务需求有关了.[Timer {time}]定时器啦;[Value {valuepath}={value}]当什么数值到了什么值.没有什么做不到只有我们想不到的.

附件:Caliburn.Micro.KeyBinding.rar修改CM中的演示代码