ExcelHome技术论坛

 找回密码
 免费注册

QQ登录

只需一步,快速开始

快捷登录

搜索
EH技术汇-专业的职场技能充电站 妙哉!函数段子手趣味讲函数 Excel服务器-会Excel,做管理系统 Excel Home精品图文教程库
HR薪酬管理数字化实战 Excel 2021函数公式学习大典 Excel数据透视表实战秘技 打造核心竞争力的职场宝典
300集Office 2010微视频教程 数据工作者的案头书 免费直播课集锦 ExcelHome出品 - VBA代码宝免费下载
用ChatGPT与VBA一键搞定Excel WPS表格从入门到精通 Excel VBA经典代码实践指南
查看: 695|回复: 5

[求助] C#开发office插件,如何设置插件快捷键

[复制链接]

TA的精华主题

TA的得分主题

发表于 2023-4-17 11:48 | 显示全部楼层 |阅读模式
如题,现在用C#开发office的VSTO格式插件,如何实现按下F3重复上一次命令?


重复上一次我实现了,但是快捷键设置不成功,用的hook技术,

经过调试,hook回调经常失败,不知道啥原因。

后来查了一下,这个是office的bug,从2017年就有人提出,结果微软到现在都没修复。

想请问下有没有大神实现了这个功能?能否给段代码学习一下?

TA的精华主题

TA的得分主题

发表于 2023-4-18 08:37 | 显示全部楼层
你写的全局钩子还是线程钩子?

TA的精华主题

TA的得分主题

发表于 2023-4-22 13:30 | 显示全部楼层
我在VB6中用的hook,在hook中任何可能出错的函数尽量用settimer之类的,比如application.run,也不要有sleep之类的,不要中断hook过程。

TA的精华主题

TA的得分主题

 楼主| 发表于 2023-4-29 16:27 | 显示全部楼层
临沂-枸杞 发表于 2023-4-18 08:37
你写的全局钩子还是线程钩子?

老哥你好,能帮忙看看我写的代码吗?
  1. ```cs
  2. //private FontFormat lastFontFormat;

  3. private delegate int LowLevelKeyboardProc(int nCode, int wParam, IntPtr lParam);

  4. private const int WH_KEYBOARD_LL = 13;
  5. private const int WM_KEYDOWN = 0x0100;
  6. private LowLevelKeyboardProc hookProc;
  7. private int hookId = 0; //声明键盘钩子处理的初始值
  8. private IntPtr ModuleHandle = IntPtr.Zero;

  9. public void RegPPTHook()
  10. {
  11.     if (hookId == 0)
  12.     {
  13.         //创建钩子回调函数对象
  14.         hookProc = new LowLevelKeyboardProc(HookCallback);

  15.         using(Process process = Process.GetCurrentProcess())
  16.         using(ProcessModule module = process.MainModule)
  17.         {
  18.             hookId = SetWindowsHookEx(WH_KEYBOARD_LL, hookProc, GetModuleHandle(module.ModuleName), 0);
  19.         }

  20.         // 如果设置钩子失败
  21.         if (hookId == 0)
  22.         {
  23.             Unhook();
  24.             throw new Exception("安装键盘钩子失败");
  25.         }

  26.         //hKeyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL, KeyboardHookProcedure, Marshal.GetHINSTANCE(Assembly.GetExecutingAssembly().GetModules()[0]), 0);
  27.     }
  28. }

  29. //回调
  30. private int HookCallback(int nCode, int wParam, IntPtr lParam)

  31. {
  32.     if (nCode >= 0 && wParam == (int)WM_KEYDOWN)
  33.     {
  34.         int vkCode = Marshal.ReadInt32(lParam);
  35.         if (vkCode == (int)Keys.F3)
  36.         {
  37.             //MessageBox.Show("用户按下了 F3");
  38.             //Process Test_proc = Process.GetCurrentProcess();
  39.             //ProcessModule Test_processModule = Test_proc.MainModule;
  40.             //string Test_modulename = Test_processModule.ModuleName;
  41.             //IntPtr Test_ModuleHandle = GetModuleHandle(Test_modulename);

  42.             //MessageBox.Show(
  43.             //    "当前进程是:" + Test_proc.ToString() + Environment.NewLine +
  44.             //    "当前主模块是:" + Test_processModule.ToString() + Environment.NewLine +
  45.             //    "当前主模块名称是:" + Test_modulename.ToString() + Environment.NewLine +
  46.             //    "当前主模块句柄是:" + Test_ModuleHandle.ToString()
  47.             //    );

  48.             RepeatAction.RepeatLastAction();//重复上一次操作,功能已实现,正常使用
  49.         }
  50.     }
  51.     return CallNextHookEx(IntPtr.Zero, nCode, wParam, lParam);
  52. }

  53. //卸载钩子
  54. private void Unhook()
  55. {
  56.     bool retKeyboard = true;
  57.     if (hookId != 0)
  58.     {
  59.         retKeyboard = UnhookWindowsHookEx(hookId);
  60.         hookId = 0;
  61.     }
  62.     if (!(retKeyboard))
  63.         throw new Exception("卸载钩子失败!");
  64. }

  65. /// <summary>
  66. /// 安装钩子
  67. /// </summary>
  68. /// //键盘线程钩子
  69. /// SetWindowsHookEx( 2,KeyboardHookProcedure, IntPtr.Zero, GetCurrentThreadId());//指定要监听的线程idGetCurrentThreadId(),
  70. //键盘全局钩子,需要引用空间(using System.Reflection;)
  71. //SetWindowsHookEx( 13,MouseHookProcedure,Marshal.GetHINSTANCE(Assembly.GetExecutingAssembly().GetModules()[0]),0);
  72. /// <param name="idHook">钩子类型,鼠标\键盘\巨集等10几种,即确定钩子监听何种消息,
  73. /// 监听键盘消息并且是线程钩子,消息应设为2,
  74. /// 如果是全局钩子监听键盘消息应设为13,
  75. /// 线程钩子监听鼠标消息设为7,
  76. /// 全局钩子监听鼠标消息设为14</param>
  77. /// <param name="lpfn">挂钩的函数,用来处理拦截消息的函数,全局函数。
  78. /// 如果dwThreadId参数为0 或是一个由别的进程创建的线程的标识,lpfn必须指向DLL中的钩子子程。 除此以外,lpfn可以指向当前进程的一段钩子子程代码。钩子函数的入口地址,当钩子钩到任何消息后便调用这个函数</param>
  79. /// <param name="hMod">当前进程的句柄,
  80. /// 为NULL:当前进程创建的一个线程,子程位于当前进程;
  81. /// 为0(IntPtr.Zero):钩子子程与所有的线程关联,即为全局钩子。
  82. /// 标识包含lpfn所指的子程的DLL。如果threadId 标识当前进程创建的一个线程,而且子程代码位于当前进程,hInstance必须为0。可以很简单的设定其为本应用程序的实例句柄。</param>
  83. /// <param name="dwThreadId">设置要挂接的线程ID.为0则为全局钩子</param>
  84. /// <returns></returns>
  85. [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
  86. private static extern int SetWindowsHookEx(int idHook, LowLevelKeyboardProc lpfn, IntPtr hMod, uint dwThreadId);

  87. //卸载钩子
  88. [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
  89. private static extern bool UnhookWindowsHookEx(int hhk);

  90. //继续下一个钩子
  91. [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
  92. private static extern int CallNextHookEx(IntPtr hhk, int nCode, int wParam, IntPtr lParam);

  93. //获取模块句柄
  94. [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
  95. private static extern IntPtr GetModuleHandle(string lpModuleName);

  96. // 取得当前线程编号
  97. [DllImport("kernel32.dll")]
  98. private static extern int GetCurrentThreadId();
  99. ```
复制代码


TA的精华主题

TA的得分主题

发表于 2023-4-30 17:49 | 显示全部楼层
Gma.System.MouseKeyHook你可以试下这个库

TA的精华主题

TA的得分主题

发表于 2023-5-10 00:58 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
zixuan203344 发表于 2023-4-29 16:27
老哥你好,能帮忙看看我写的代码吗?

别用WH_KEYBOARD_LL用WH_KEYBOARD
我本来用的WH_KEYBOARD,曾试图改为WH_KEYBOARD_LL失败了,具体啥问题我不记得了。
另外,逻辑应该是:
  1. if F3 then
  2.     if keydown then 重复XXX
  3.     return -1 //这里不应再callnext了
  4. endif
复制代码

CallNextHookEx第一个参数也不能写0吧,应该是你的hookId
您需要登录后才可以回帖 登录 | 免费注册

本版积分规则

手机版|关于我们|联系我们|ExcelHome

GMT+8, 2024-6-15 12:30 , Processed in 0.041948 second(s), 9 queries , Gzip On, MemCache On.

Powered by Discuz! X3.4

© 1999-2023 Wooffice Inc.

沪公网安备 31011702000001号 沪ICP备11019229号-2

本论坛言论纯属发表者个人意见,任何违反国家相关法律的言论,本站将协助国家相关部门追究发言者责任!     本站特聘法律顾问:李志群律师

快速回复 返回顶部 返回列表