在使用全尺寸键盘的时候 键盘右边都有一排小键盘

但是这个小键盘的数字键值和普通键盘的数字键值是不一样的

在ANSI码里 标准数字键值是$30..$39, 而小键盘的键值是$60..$69

这样问题就来了 , 我们在属性编辑器里设置Action的ShortCut的时候, 使用的都是文字表示, 而VCL架构里, ShortCut的文字表示是不区分大小键盘数字键的

我们先看一下文字是真么转换成ShortCut的:

在Menus单元: TextToShortCut(Text: string): TShortCut; 函数

  1. function TextToShortCut(Text: string): TShortCut;
  2.  
  3. { If the front of Text is equal to Front then remove the matching piece
  4. from Text and return True, otherwise return False }
  5.  
  6. function CompareFront(var Text: string; const Front: string): Boolean;
  7. begin
  8. Result := False;
  9. if (Length(Text) >= Length(Front)) and
  10. (AnsiStrLIComp(PChar(Text), PChar(Front), Length(Front)) = ) then
  11. begin
  12. Result := True;
  13. Delete(Text, , Length(Front));
  14. end;
  15. end;
  16.  
  17. var
  18. Key: TShortCut;
  19. Shift: TShortCut;
  20. begin
  21. Result := ;
  22. Shift := ;
  23. while True do
  24. begin
  25. if CompareFront(Text, MenuKeyCaps[mkcShift]) then Shift := Shift or scShift
  26. else if CompareFront(Text, '^') then Shift := Shift or scCtrl
  27. else if CompareFront(Text, MenuKeyCaps[mkcCtrl]) then Shift := Shift or scCtrl
  28. else if CompareFront(Text, MenuKeyCaps[mkcAlt]) then Shift := Shift or scAlt
  29. else Break;
  30. end;
  31. if Text = '' then Exit;
  32. for Key := $ to $ do { Copy range from table in ShortCutToText }
  33. if AnsiCompareText(Text, ShortCutToText(Key)) = then
  34. begin
  35. Result := Key or Shift;
  36. Exit;
  37. end;
  38. end;

注意加亮的那几行, 实际上就是吧$08~$255的所有字符和传入的做个比较, 那么我们的焦点就关注到ShortCutToText上了:

  1. function ShortCutToText(ShortCut: TShortCut): string;
  2. var
  3. Name: string;
  4. begin
  5. case WordRec(ShortCut).Lo of
  6. $, $:
  7. Name := MenuKeyCaps[TMenuKeyCap(Ord(mkcBkSp) + WordRec(ShortCut).Lo - $)];
  8. $0D: Name := MenuKeyCaps[mkcEnter];
  9. $1B: Name := MenuKeyCaps[mkcEsc];
  10. $..$:
  11. Name := MenuKeyCaps[TMenuKeyCap(Ord(mkcSpace) + WordRec(ShortCut).Lo - $)];
  12. $2D..$2E:
  13. Name := MenuKeyCaps[TMenuKeyCap(Ord(mkcIns) + WordRec(ShortCut).Lo - $2D)];
  14. $..$: Name := Chr(WordRec(ShortCut).Lo - $ + Ord(''));
  15. $..$5A: Name := Chr(WordRec(ShortCut).Lo - $ + Ord('A'));
  16. $..$: Name := Chr(WordRec(ShortCut).Lo - $ + Ord(''));
  17. $..$: Name := 'F' + IntToStr(WordRec(ShortCut).Lo - $6F);
  18. else
  19. Name := GetSpecialName(ShortCut);
  20. end;
  21. if Name <> '' then
  22. begin
  23. Result := '';
  24. if ShortCut and scShift <> then Result := Result + MenuKeyCaps[mkcShift];
  25. if ShortCut and scCtrl <> then Result := Result + MenuKeyCaps[mkcCtrl];
  26. if ShortCut and scAlt <> then Result := Result + MenuKeyCaps[mkcAlt];
  27. Result := Result + Name;
  28. end
  29. else Result := '';
  30. end;

很明显, 这里面把标准数字键和小键盘数字键全部映射成0~9了, 那么自然在TextToShortCut的时候就只会认出标准键盘了

所以, 一般情况下, 是没办法在属性编辑器里设置小键盘热键的, 只能通过代码解决:

在代码模式下, Action的ShortCut属性是一个TShortCut类型: TShortCut = Low(Word)..High(Word); 也就是说, 是Ansi字符

那么我们就可以直接使用键值来设置ShortCut, 而绕过Text转换的步骤, 从而能够达到使用小键盘快捷键的目的:

  1. Action1.ShortCut := Menus.ShortCut(VK_NUMPAD0, [ssCtrl]);

这样就很简单的设置了一个ctrl+小键盘0的快捷键

那么, 如果要同时设置标准键0和小键盘0都能激活这个Action怎么做呢

这就要使用另一个属性: SecondaryShortCuts, 这个实际上是一个TStringList

  1. property SecondaryShortCuts: TShortCutList
  2.  
  3. TShortCutList = class(TStringList)
  4. private
  5. function GetShortCuts(Index: Integer): TShortCut;
  6. public
  7. function Add(const S: String): Integer; override;
  8. function IndexOfShortCut(const Shortcut: TShortCut): Integer;
  9. property ShortCuts[Index: Integer]: TShortCut read GetShortCuts;
  10. end;

OK, 现在出现了另一个问题, 我们向SecondaryShortCuts里写入多个快捷键, 是使用的Add, 可惜....Add的是一个文本, 这样我们又回到开始的问题了, 文本没办法区分大小键盘数字键, 咋办...-_-

有人会说, 吧小键盘设置到ShortCut上, 大键盘用SecondaryShortCuts, OK, 这当然没问题....不过始终不是正统的解决办法(程序员的偏执)

研究代码吧:

  1. function TShortCutList.Add(const S: String): Integer;
  2. begin
  3. Result := inherited Add(S);
  4. Objects[Result] := TObject(TextToShortCut(S));
  5. end;
  6.  
  7. function TShortCutList.GetShortCuts(Index: Integer): TShortCut;
  8. begin
  9. Result := TShortCut(Objects[Index]);
  10. end;

似乎有办法解决, add的时候实际上是吧ShortCut强制转换为TObject类型保存进Objects里了(其实是个取巧的办法, 我自己也总这么干...^_^)

而读取ShortCut的时候根本没读String, 直接读的就是Objects, 那么我们如果直接写Objects能否可行? 试试看:

  1. Action1.SecondaryShortCuts.AddObject('Ctrl+Num0', TObject(Menus.ShortCut(VK_NUMPAD0, [ssCtrl])));

OK, 测试完全可行......问题完美解决了

关于Action快捷键和小键盘的问题的更多相关文章

  1. PowerDesigner从Sqlserver中反转为带注释的字典及快捷键操作

    PowerDesigner的操作经常忘记,所以把常用的功能记录下来备忘. 1.修改反转过来的字段 PowerDesigner从数据库反转的时候,默认不带注释,需要先进行修改. 输入如下脚本: {OWN ...

  2. power designer 一般常用快捷键(转)

    一般快捷键 快捷键 说明 F4 打开检查模型窗口,检查模型 F5 如果图窗口内的图改变过大小,恢复为原有大小即正常大小 F6 放大图窗口内的图 F7 缩小图窗口内的图 F8 在图窗口内中查看全部图内容 ...

  3. 【转】PowerDesigner快捷键

    一般快捷键 快捷键 说明 F4 打开检查模型窗口,检查模型 F5 如果图窗口内的图改变过大小,恢复为原有大小即正常大小 F6 放大图窗口内的图 F7 缩小图窗口内的图 F8 在图窗口内中查看全部图内容 ...

  4. PowerDesigner快捷键【转】

    一般快捷键 快捷键 说明 F4 打开检查模型窗口,检查模型 F5 如果图窗口内的图改变过大小,恢复为原有大小即正常大小 F6 放大图窗口内的图 F7 缩小图窗口内的图 F8 在图窗口内中查看全部图内容 ...

  5. IntelliJ IDEA 快捷键(一)(window版)

    一.高效定位代码 1.跳转 1.项目之间的跳转 Next Project Window 快捷键 Ctrl + Alt + 左方括号. Previous Project Window 快捷键 Ctrl ...

  6. PowerDesigner 快捷键

    一般快捷键 快捷键 说明 F4 打开检查模型窗口,检查模型 F5 如果图窗口内的图改变过大小,恢复为原有大小即正常大小 F6 放大图窗口内的图 F7 缩小图窗口内的图 F8 在图窗口内中查看全部图内容 ...

  7. Android Studio笔记之快捷键

    Android Studio h2{ color: #4abcde; } pre{ background-color: #f8f8f8; border: solid 1px #ccc; border- ...

  8. PowerDesigner常用快捷键

    一般快捷键 F4   打开检查模型窗口,检查模型 F5   如果图窗口内的图改变过大小,恢复为原有大小即正常大小 F6   放大图窗口内的图 F7   缩小图窗口内的图 F8   在图窗口内中查看全部 ...

  9. AD各种布线方法总结

    1.常规布线:不详细说了,是个人就知道怎么弄.需要说明的是在布线过程中,可按小键盘的*键或大键盘的数字2键添加一个过孔:按L键可以切换布线层:按数字3可设定最小线宽.典型线宽.最大线宽的值进行切换. ...

随机推荐

  1. NoSQL-Redis【1】-控制台配置密码

    1.设置密码为123456 CONFIG SET requirepass 123456 2.验证密码 AUTH 123456 3.redis-cli连接 @ECHO OFF redis-cli.exe ...

  2. COGS1752 [BOI2007]摩基亚Mokia(CDQ分治 + 二维前缀和 + 线段树)

    题目这么说的: 摩尔瓦多的移动电话公司摩基亚(Mokia)设计出了一种新的用户定位系统.和其他的定位系统一样,它能够迅速回答任何形如“用户C的位置在哪?”的问题,精确到毫米.但其真正高科技之处在于,它 ...

  3. Js提示框

    百度搜索 1.artDialog 2.ymPrompt 以下网站提供资料参考 http://www.17sucai.com/ http://www.juheweb.com/ http://www.5i ...

  4. HDU5709 : Claris Loves Painting

    对于每个点维护两棵线段树$T1[x],T2[x]$: $T1[x]$维护$x$子树内,深度在$[l,r]$内的点数,同种颜色有多个的话,保留深度最小的那个. $T2[x]$维护$x$子树内每种颜色的最 ...

  5. Redis内存缓存系统入门

    网站:http://redis.io/ key-value cache and store    data structure server 1. 服务器端 1.1 安装 下载安装包:http://r ...

  6. Android 读取蓝牙设备信息开发

    (1)Android手机一般以客户端的角色主动连接SPP协议设备(接上蓝牙模块的数字传感器),连接流程是: 1.使用registerReceiver注册BroadcastReceiver来获取蓝牙状态 ...

  7. Android --时间控件的使用

    1. mian.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns: ...

  8. 配置1000条ACE的脚本

    配置1000条ACE的脚本 测试 python 引言 在路由器或者交换机产品中,手工配置大量shell命令时,难免繁琐且效率低下,鉴于CRT中支持多种脚本语言,因此可通过脚本执行大量重复的shell配 ...

  9. Controller 通信 发布接收广播

    在Angularjs开发一些经验总结随笔中提到我们需要按照业务却分angular controller,避免过大无所不能的上帝controller,我们把controller分离开了,但是有时候我们需 ...

  10. nginx和tomcat实现反向代理、负载均衡和session共享

    这类的文章很多,nginx和tomcat实现反向代理.负载均衡实现很容易,可以参照http://blog.csdn.net/liuzhigang1237/article/details/8880752 ...