zoukankan      html  css  js  c++  java
  • Windows 编程[23] 快捷键资源

    提示:

    1、因为加入快捷键, 本例的基础代码和以前不同了; 因为窗体初始化时要先载入快捷键资源, 还要拦截快捷键消息另作处理.

    2、关于快捷键的话题, 以前接触过不少了, 但那些都不是本质:
        注册系统级热键
        所有可选的快捷键列表
        快捷键设置控件
        快捷键的记录方式

    3、我曾经以为快捷键不过就是拦截键盘消息, 现在看来那是想得太简单了; 很容易就可以说明: 键盘消息是需要焦点的, 而快捷键是只对主窗口.

    4、使用快捷键前应该先建立一个快捷键表或建立快捷键资源, 本例使用了后者.
    快捷键一般是执行菜单的功能, 那它是怎么和菜单挂接的呢? 很简单: 给每一项快捷键和每一个菜单项指定相同的标识即可!

    5、在本例中, 窗口建立后, 先用 LoadAccelerators 载入快捷键资源并返回快捷键资源句柄 hAcc;
    GetMessage 从消息队列中取出消息后, 先用 TranslateAccelerator 检查是否是快捷键消息. 如果是, TranslateAccelerator 会把此快捷键消息转换成菜单消息(WM_COMMAND, 也可能是系统菜单消息: WM_SYSCOMMAND), 然后直接发送给窗口; 如果不是, 再继续以前的消息传递.
    其实快捷键消息的本质也是键盘消息, 不过 TranslateAccelerator 会检查键盘消息的组合是否是我们定义的快捷键. 但我们在执行快捷键时, 焦点未必就在主窗口, 它是怎么吧其他窗口的键盘消息转给主窗口的呢?
    如果 GetMessage 函数的第二个参数为 0 时, 它会检索程序中所有窗口的消息, TranslateAccelerator 接过来后, 不管消息来自那个窗口, 都把消息包中的窗口句柄换成主窗口句柄再传递.

    关于快捷键资源文件还是解释在资源文件下面吧...

    本例效果图:



    本例使用的资源文件(TestRes.rc):
    MyMenu1 MENUEX
    BEGIN
      POPUP "菜单"
      BEGIN
        MENUITEM "菜单_1\t Shift+1"           ,101
        MENUITEM "菜单_2\t Ctrl+2"            ,102
        MENUITEM "菜单_3\t Alt+3"             ,103
        MENUITEM "菜单_4\t Shift+Ctrl+Alt+4"  ,104
        MENUITEM "菜单_5\t 5"                 ,105
        MENUITEM "菜单_6\t F5"                ,106
        MENUITEM "菜单_7\t Ctrl+A"            ,107
        MENUITEM "菜单_8\t Alt+A"             ,108 
      END
    END
    
    MyAccel ACCELERATORS
    BEGIN
      "1",   101,  VIRTKEY, SHIFT,               NOINVERT
      "2",   102,  VIRTKEY, CONTROL,             NOINVERT
      "3",   103,  VIRTKEY, ALT,                 NOINVERT
      "4",   104,  VIRTKEY, SHIFT, CONTROL, ALT, NOINVERT
      "5",   105,  VIRTKEY, NOINVERT,            NOINVERT
      VK_F5, 106,  VIRTKEY, NOINVERT,            NOINVERT
      "A",   107,  VIRTKEY, CONTROL
      "a",   108,  ASCII,   ALT 
    END
    
    注释:

    1、快捷键资源文件关键字: ACCELERATORS, 需要取个名给程序中的 LoadAccelerators 使用, 这里是: MyAccel.

    2、快捷键资源文件可以有五组参数, 从后面说: NOINVERT 是让被激活的菜单的顶层菜单不闪烁(但我去掉也没看出来).
    它前面是控制键: SHIFT、CONTROL、ALT.
    再前面有两个选择: VIRTKEY、ASCII, VIRTKEY 指示快捷键要用 虚拟键码 说明; ASCII 指示用 ASCII 码说明快捷键. 譬如例子中的 VK_F5 就是典型的虚拟键码. 但常规数字键和字母键没有对应的虚拟键码, 对数字(非小键盘数字)来讲, 这两者没有区别; 特别注意: VIRTKEY 时指示的字母须大写、ASCII 指示的字母须小写.

    3、这其中最重要的就是第二个参数了, 它必须和菜单的标识相对应.

    4、另外, 菜单资源也和以前有点区别: 在 \t (Tab 的意思) 后面用文本说明了对应的快捷键, 不过这只是显示效果而已, 有没有都不影响功能.

    本例代码文件:
    program Project1;
    
    {$R 'TestRes.res' 'TestRes.rc'}
    
    uses
      Windows, Messages;
    
    {收到 WM_COMMAND 消息时需要做的工作}
    procedure OnCommand(h: HWND; wParam: Integer);
    var
      W: Word;
      arr: array[Byte] of Char;
    begin
      W := LoWord(wParam);
      case W of
        101..108: begin
          GetMenuString(GetMenu(h), W, arr, Length(arr), MF_BYCOMMAND);
          SetWindowText(h, arr);
        end;
      end;
    end;
    
    function WndProc(wnd: HWND; msg: UINT; wParam: Integer; lParam: Integer): Integer; stdcall;
    begin
      Result := 0;
      case msg of
        WM_COMMAND : OnCommand(wnd, wParam); {收到 WM_COMMAND 消息后调用 OnCommand 过程}
        WM_DESTROY : PostQuitMessage(0);
      else
        Result := DefWindowProc(wnd, msg, wParam, lParam);
      end;
    end;
    
    function RegMyWndClass: Boolean;
    var
      cls: TWndClass;
    begin
      cls.style         := CS_HREDRAW or CS_VREDRAW;
      cls.lpfnWndProc   := @WndProc;
      cls.cbClsExtra    := 0;
      cls.cbWndExtra    := 0;
      cls.hInstance     := HInstance;
      cls.hIcon         := 0;
      cls.hCursor       := LoadCursor(0, IDC_ARROW);
      cls.hbrBackground := HBRUSH(COLOR_WINDOW + 1);
      cls.lpszMenuName  := 'MyMenu1';
      cls.lpszClassName := 'MyWnd';
      Result := RegisterClass(cls) <> 0;
    end;
    
    {程序入口}
    const
      tit = 'New Form';
      ws = WS_OVERLAPPEDWINDOW;
      x = 100; y = 100; w = 300; h = 180;
    var
      hWnd: THandle;
      Msg : TMsg;
      hAcc: HACCEL; {定义快捷键资源句柄}
    begin
      RegMyWndClass;
      hWnd := CreateWindow('MyWnd', tit, ws, x, y, w, h, 0, 0, HInstance, nil);
      ShowWindow(hWnd, SW_SHOWNORMAL);
      UpdateWindow(hWnd);
    
      hAcc := LoadAccelerators(HInstance, 'MyAccel'); {载入快捷键资源}
    
      while(GetMessage(Msg, 0, 0, 0)) do
      begin
        if (TranslateAccelerator(hwnd, hAcc, Msg) = 0) then {拦截并处理快捷键消息}
        begin
          TranslateMessage(Msg);
          DispatchMessage(Msg);
        end;
      end;
    end.
    
  • 相关阅读:
    自调用匿名函数和js的Module模式
    设置一天中不同时段的倒计时,计算时针和分针的夹角
    移动端web开发中对点透的处理,以及理解fastclick如何做到去除300ms延迟
    使用Fiddler改变线上js文件的引用路径
    Linux下常用设置文件和文件夹读写权限操作
    RESTful API
    mysql之load语句
    Django学习之点赞功能
    Django学习之网站图标
    python学习之pyenv
  • 原文地址:https://www.cnblogs.com/del/p/1170027.html
Copyright © 2011-2022 走看看