Excel插件快捷键弹窗事件(VSTO+键盘钩子实现)

Office如何通过VSTO进行EXCEL插件开发? VSTO(Visual Studio Tools for Office )是VBA的替代,是一套用于创建自定义Office应用程序的Visual Studio工具包。VSTO可以用Visual Basic 或者Visual C#扩展Office应用程序(例如Word、Excel、PPT)。本文通过VSTO进行Excel插件开发总结,并进行记录。 阅读详情

插件功能 在excel里面按快捷键(Alt+Shift+O)可以弹窗进行搜索文件,效果图如下
这里写图片描述
选择文件可以进行跳转,类似于Visual Studio助手的搜索文件功能一样 好的 闲话不多说 代码放上
Search.cs

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
using System.Collections;
using Microsoft.Office.Tools.Excel;
using Excel = Microsoft.Office.Interop.Excel;
using System.IO;

namespace excel_search_file
{
    public partial class Search : Form
    {
        public Dictionary<string, bool> dictionary = new Dictionary<string, bool>();
        public Search()
        {
            InitializeComponent();
        }

        private void textBox1_TextChanged(object sender, EventArgs e)
        {
            Microsoft.Office.Tools.Excel.Workbook workbook = Globals.Factory.GetVstoObject(
            Globals.ThisAddIn.Application.ActiveWorkbook);
            string WorkbookFullName = workbook.FullName.Replace('\\', '/');
            string selectedpanfu = "";
            ExcelTool exceltool = new ExcelTool();
            bool bRet = exceltool.InitExcelTool(WorkbookFullName);
            if (!bRet)
            {
                return;
            }
            IniFile manageIniFile = exceltool.ManageIniFile;
            string section = "SkipableFolder", keyname = "skipfolder";
            for (int i = 1; i < 21; ++i)
            {
                string szkeyname = keyname + i.ToString();
                string retstring = null;
                if (manageIniFile.IsKeyExist(section, szkeyname))
                {
                    manageIniFile.GetString(section, szkeyname, out retstring);
                    dictionary[retstring] = true;
                }
                else
                    break;
            }
            selectedpanfu = exceltool.ParentFolder;
            string targetfile = textBox1.Text;

            listView1.Items.Clear();
            ListViewItem item;
            foreach (var si in SearchFile(selectedpanfu, targetfile))
            {
                string filename = System.IO.Path.GetFileName(si.szPath);
                item = listView1.Items.Add(si.szPath);
                item.SubItems.Add(filename);
            }
        }

        private void textBox1_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Up || e.KeyCode == Keys.Down)
            {
                this.listView1.Focus();
                this.listView1.Items[0].Focused = true;
            }
        }

        private void listView1_DoubleClick(object sender, EventArgs e)
        {
            this.Close();
            if (listView1.SelectedItems.Count == 0)
            {
                return;
            }
            string fileFullPath = listView1.SelectedItems[0].Text;
            Excel_Universal_Tools.SwitchWindow(fileFullPath, Globals.ThisAddIn.Application.Workbooks);
        }

        private void listView1_SelectedIndexChanged(object sender, EventArgs e)
        {

        }

        private void listView1_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Enter)
            {
                this.listView1_DoubleClick(sender, e);
            }
        }

        private void Search_KeyDown(object sender, KeyEventArgs e)
        {

        }

        private void Search_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (e.KeyChar == (char)27)
            {
                this.Close();
                return;
            }
        }

        private void Search_Load(object sender, EventArgs e)
        {
            this.KeyPreview = true;
            textBox1_TextChanged(sender, e);
        }

        private void Search_Activated(object sender, EventArgs e)
        {
            this.Focus();
            this.textBox1.Focus();
        }

        public class ShowInfo
        {
            public int nValue;
            public string szPath;
        }

        List<FileInfo> s_lstFile = new List<FileInfo>();
        private void InitFileList(string szRootPath)
        {
            DirectoryInfo dir = new DirectoryInfo(szRootPath);

            foreach (FileInfo file in dir.GetFiles("*.*", SearchOption.TopDirectoryOnly))
            {
                s_lstFile.Add(file);
            }

            foreach (DirectoryInfo subDir in dir.GetDirectories())
            {
                if (subDir.Name.StartsWith("."))
                    continue;
                if (!dictionary.Keys.Contains(subDir.Name))
                {
                    FileInfo[] files = subDir.GetFiles("*.*", SearchOption.AllDirectories);
                    s_lstFile.AddRange(files);
                }
            }
        }

        public List<ShowInfo> SearchFile(string onedrive, string targetFile)
        {
            if (s_lstFile.Count <= 0)
                InitFileList(onedrive);

            List<ShowInfo> directorys = new List<ShowInfo>();
            foreach (FileInfo item in s_lstFile)
            {
                if (!item.FullName.Contains(targetFile))
                    continue;
                ShowInfo si = new ShowInfo();
                si.nValue = GetValue(item.Name, item.FullName, targetFile);
                si.szPath = string.Format("{0}\\{1}", item.DirectoryName, item.Name);
                directorys.Add(si);
            }

            List<ShowInfo> lstResult = (from a in directorys orderby a.nValue descending select a).Take(30).ToList();

            return lstResult;
        }

        public int GetValue(string szFileName, string szFullPath, string szTarget)
        {
            if (szFileName.Contains(szTarget))
            {
                return 10000000 - szFileName.IndexOf(szTarget); ;
            }

            if (szFullPath.Contains(szTarget))
            {
                return 10000 - szFullPath.IndexOf(szTarget);
            }

            return 0;
        }
    }
}

ThisAddIn.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using Excel = Microsoft.Office.Interop.Excel;
using Office = Microsoft.Office.Core;
using Microsoft.Office.Tools.Excel;
using System.Windows.Forms;

namespace excel_search_file
{
    public partial class ThisAddIn
    {
        private static Search m_search = null;
        public void ResponseFunction()
        {
            if (m_search == null)
            {
                m_search = new Search();

                Microsoft.Office.Interop.Excel.Application application = Globals.ThisAddIn.Application;
                double x = application.Left + application.Width * 0.5;
                double y = application.Top + application.Height * 0.5;
                m_search.Location = new System.Drawing.Point((int)x, (int)y);

                m_search.FormClosing += form_FormClosing;
                Win32WindowImpl win32WindowImpl = new Win32WindowImpl(Globals.ThisAddIn.Application.Hwnd);
                m_search.Show(win32WindowImpl);
                m_search.Focus();
            }
            else
            {
                m_search.Activate();
            }
        }

        void form_FormClosing(object sender, System.Windows.Forms.FormClosingEventArgs e)
        {
            m_search = null;
        }

        ShortcutManagement shortcutmanagement = new ShortcutManagement();
        private void ThisAddIn_Startup(object sender, System.EventArgs e)
        {
            Keys[] Shortcutlist = new Keys[] { Keys.O, Keys.Alt, Keys.Shift };

            shortcutmanagement.InitShortManagement(Shortcutlist, ResponseFunction);
            shortcutmanagement.startListen();
        }

        private void ThisAddIn_Shutdown(object sender, System.EventArgs e)
        {
            //shortcutmanagement.stopListen();
        }
        #region VSTO 生成的代码

        /// <summary>
        /// 设计器支持所需的方法 - 不要
        /// 使用代码编辑器修改此方法的内容。
        /// </summary>
        private void InternalStartup()
        {
            this.Startup += new System.EventHandler(ThisAddIn_Startup);
            this.Shutdown += new System.EventHandler(ThisAddIn_Shutdown);
        }
        #endregion
    }
}

核心的代码就是上面这些,但是在发布的时候却遇到了一个问题,在win7上面运行好好地,但是在移植到win10上面的时候,发现一弹框就会出现假死的现象。经过排查发现是因为windows api SetWindowsHookEx函数所导致的,
原文如下:原文链接如下
这里写图片描述
翻译过来就是
这里写图片描述
此坑先占位 等待后续解决
不过也发现了另外一个制作快捷键的方法,就是使用excel中this.Application.OnKey,如果没有找到解决平台不兼容的办法,打算使用这个来替换。
暂时先写到这儿 附上完整项目代码下载地址

VSTO和Ribbon界面的快速二次开发指南 本文还有配套的精品资源,点击获取 简介:本文详细介绍使用VSTO工具集和Ribbon界面进行快速二次开发的流程,为开发者提供在.NET环境中扩展和定制Microsoft Office应用程序的有效方法。内容涵盖VSTO开发基础、Ribbon UI的组成与设计、二次开发的具体步骤、以及如何通过动态加载和自定义UI元素来增强Office插件。本文旨在帮助读者通过实践任务,快速提... 阅读详情

相关推荐

VBA鼠标键盘钩子类.xlsm

VBA鼠标键盘钩子类.xlsm

Excel VSTO开发7 -可视化界面开发

前面的代码都是基于插件启动或者退出时,以及Excel Application的相关事件,在用户实际操作中并不会显示相应的界面,当然也不需要显示相关界面。但是,这对于用户显然不是那么友好,而且也不利于正常的在Excel中的操作。该显示的应该使用UI显示出来,而且还有部分操作是基于UI控件的。可以看到设计区域类似Excel工具栏上的功能区,默认已经有一个Tab1(选项卡)和一个Group1(组控件)左侧[工具箱]中相比普通开发多了[Office功能区控件]。此时就可以通过控件摆放及添加相应代码进行开发了。

学习微软 .net 技术开发 2027

生成式深度学习(第二版)-第一章-Conda环境下TensorFlow和Keras的安装和配置

按照书籍中的代码运行提示,需要配置Docker。个人的机器上正好有 conda4.14.0,索性就在本地环境进行配置。

GarryWang1248的博客 398

VBA学习(12):制作动态模糊匹配的下拉菜单

选中目标工作表,在【开发工具】→【插入】→【ActiveX控件】,先后插入一个文本框和一个列表框。控件的大小和存放的位置都随意,反正这事你说了也不算,后面代码会自己做调整。需要注意的是,如果你不会调整VBA代码,那么此处文本框的名字必须为TextBox1,列表框的名字必须为ListBox1——正常而言,这俩名字也都是系统默认的。当在文本框中输入数据时,列表框的数据会随之动态更新。保持目标工作表选中状态不变,按快捷键打开VBE编辑器,将以下代码粘贴到当前工作表的代码窗口。

nianfen的博客 2322

基于ESP32-C3的便携式血氧仪硬件与算法实现

血氧饱和度(SpO₂)监测是生理参数无创检测的核心技术之一,其原理基于光电容积脉搏波(PPG)信号中红光与红外光吸收比值的动态变化。该技术依赖高精度模拟前端、稳定光学激励及实时数字信号处理能力,在消费级健康设备中面临功耗、体积与测量鲁棒性的多重约束。ESP32-C3凭借集成LEDC、12位ADC与低功耗双核架构,成为PPG终端的理想主控平台;结合定制化指夹式光学探头与比率法血氧算法,可实现非诊断级但趋势可靠的日常健康监测。本文围绕硬件电路设计、电源管理策略与嵌入式信号处理流程展开,覆盖从LED驱动、跨阻放大

weixin_29025501的博客 132

OpenFOAM-v2006重叠网格挖洞问题实战:如何手动修复overset代码中的边缘识别缺陷

本文深入探讨了OpenFOAM-v2006中重叠网格挖洞问题的实战解决方案,重点修复overset代码中的边缘识别缺陷。通过逆向工程解析挖洞决策机制,设计最小侵入式的函数override方案,并建立多级验证体系,有效解决了网格挖洞区域覆盖不全的问题,提升了计算流体动力学模拟的准确性和可靠性。

weixin_29216049的博客 430

VSTO创建的Excel文档中序列型下拉列表造成文档无法打开的问题

由于工作并不是在手头这台机器上做的,所以只简单文字记录一下,希望能说得清楚。     最近在搞一个Excel扩展的东西,用VSTO自动设计并且填写电子表格。……这是个对于个人休闲作品来说略显复杂的工程,仅C#代码量约达到3000行,还要设计十几个页面模板,并融合约千行VBA代码……。在调试环境中一切正常,一上到实际环境就出问题了……而且我完全不知道问题出在什么地方……可以想象其时我有多么沮丧

lhyzws的专栏 2119

.ipynb文件深度解析:从JSON结构到Jupyter Notebook高效使用指南

在Python开发与数据处理领域,交互式编程正成为探索数据与验证思路的高效方式。Jupyter Notebook作为最流行的交互式环境之一,其默认文件格式.ipynb本质是一个基于JSON的文本文件,内部通过单元格组织代码、说明文字与运行结果。理解其JSON结构,不仅有助于掌握Notebook的存储原理,更能为文件损坏修复、版本控制与自动化转换提供基础。依托对单元格类型、魔法命令及输出可视化的熟练运用,数据分析和数据可视化流程可以变得更为流畅。同时,借助VS Code、nbconvert等工具,开发者能将.

weixin_28839629的博客 349

excel设置下拉框选项?【图文详解】excel怎么设置下拉框选项?数据验证?下拉框选项格式?

本文围绕 Excel 设置下拉框选项问题展开,先阐述日常使用 Excel 时遇到相关困扰的问题背景,接着详细介绍了通过数据有效性和下拉框控件两种方法设置下拉框选项的步骤,旨在帮助读者轻松掌握 Excel 下拉框设置技能,提升数据处理效率 。

分享技术解决方案,助力小伙伴们高效办公。 6128

告别手写代码!用Simulink给TI F28335 DSP自动生成C代码(保姆级环境配置)

本文详细介绍了如何利用Simulink为TI F28335 DSP自动生成C代码,告别传统手写代码的低效与错误。通过保姆级环境配置指南和实战案例,帮助开发者快速掌握模型驱动开发方法,大幅提升嵌入式开发效率,特别适合需要频繁修改算法参数或团队协作的工程师。

weixin_30388677的博客 416

PCL CSF布料模拟算法【2026最新版】

CSF布料模拟地面滤波算法的PCL实现,博客长期更新,本文最近更新时间为:2026年10月26日。

点云侠的博客 3917

9.6华为OD机试真题 新系统 - 少儿爬山闯关积分游戏 (Java/Py/C/C++/Js/Go)

2026 华为OD机试真题9月6日华为OD上机新系统考试真题 100 分题型。

算法大师! 858

excel 通过vsto增加右键菜单快捷键

myCommandBarButton.Caption = "自定义命令";Temporary: true // 设置为临时菜单,不保存到自定义的工作簿模板中。myPopup.Caption = "自定义菜单";Before: 1, // 可根据需要调整菜单项的位置。Before: 1 // 可根据需要调整菜单项的位置。MessageBox.Show("自定义命令被点击了!// 点击菜单项时执行的逻辑代码。// 获取应用程序对象。// 获取主菜单栏对象。// 创建一个弹出菜单。// 创建一个菜单项。

nbspzs的专栏 1099

为什么devc++编译项目会失败?提示gcc无法正常启动...

根据你的描述,编译能正常进行时,只打开源文件并没有问题,问题主要出现在创建项目后编译失败,这通常与 Makefile 配置、环境变量、编译器路径设置等因素有关。你可以检查 Makefile 配置,验证 DevC++ 的编译器环境设置,或者尝试清理并重新配置项目。如果问题仍然存在,可以尝试重装 DevC++ 或重新配置工具链。希望如上措施及解决方案能够帮到有需要的你。

**My Coding Family** 1376

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

VSTO应用程序中加入键盘钩子

在VSTO应用程序中有时为了处理一些快捷按键操作等实现一些特殊的功能,此时需要对键盘进行挂钩,此时使用P/Invoke函数实现,参考如下: VSTO加载和卸载时进行钩子的初始化和卸载 代码 KeyboardHook hook; private void ThisAddIn_Startup(object sender, System.EventArgs e) ...

weixin_34379433的博客 316

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

vsto窗体在excel内弹窗置顶

参考链接:http://yshblog.com/blog/129一般vsto打开窗体用show方法,往往会碰到窗体置顶的问题,以下两个方法都存在弊端winform有个置顶属性TopMost,当把TopMost属性设为true时,窗体置顶可以实现,但是效果是全局置顶,会呈现在所有的应用程序之上用showDialog方法打开窗体,不过该方法在打开窗体的时候无法操作Excel表格,还有就是如果你在打开窗...

enjoy_Crystal的博客 2437

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

VSTO Office二次开发键盘鼠标钩子使用整理

可能通过程序控制键盘的操作和控制鼠标的一些操作,网上提供比较多的也是比较好的就是通过钩子(Hook)的方式实现。 简单整理了一下,没有找到很好的程序示例,做了个简单的Hook测试。(对于Hook的原理和调用细则,这里不涉及了,只是简单的Hook小测试,感兴趣的查一下吧) 1.Win32API函数:(简单封装对于API函数的调用) View Code 2.HookHelper.cs:(对

狂奔之林的博客 1617

扩展Edit Box控件的功能

 用VC++6.0编程的时候,文本编辑控件Edit Box是一个经常用到的控件。如果你是用它输入一些简单的文字、数字等信息,直接拿来用就可以了,但如果你用它制作大文本的编辑软件,就会觉得不好控制,许多功能无法实现,即便用CEditView,也只会生成一个类似于记事本的东西,再想加入些自己编写的功能也很困难。下面我以CEdit为基类定义了一个CEditBox类,加入了许多文本编辑时经常要用到的接

zpf82118的专栏 1553

vsto excel 右键自定义菜单快捷键

Excel 右键自定义菜单快并且加热键

我是菜鸟 409

VBA里,workbook.path不是全名,而workbook.fullname才是。而file.path就是全名,没有file.fullname

1 VBA 和 Application--Excel下的命名系统 2.1 workbooks 工作簿有fullname属性 fullname= path+ "\" + name ThisWorkbook.FullName 文件全名 ThisWorkbook.Path 文件路径 ThisWorkbook.Name 文件名 ThisWo...

奔跑的犀牛先生 4582

vsto模拟excel快捷键

唤起excel快捷键c#

nbspzs的专栏 543

细品RibbonX(43):禁用和重利用功能区中的命令

细品RibbonX(43):禁用和重利用功能区中的命令资料整理来自于论坛完整版下载地址:http://download.youkuaiyun.com/download/nodeman/10264659  Loading ... 与以前的版本不一样,Office 2007允许全局地禁用和重利用命令。在过去,禁用命令必需禁用UI中执行该命令的控件的每一单个的实例,这显然是一项巨大的工作。禁用命令禁用Office ...

狂奔之林的博客 1124

vsto 点击表格回去实际的屏幕坐标,基于坐标弹出窗体

Point ms = Control.MousePosition; System.Drawing.Point ms = Forms.Control.MousePosition; var width = System.Windows.SystemParameters.PrimaryScreenWidth; var height = System.Windows.SystemParameters.PrimaryScreenHeight;

nbspzs的专栏 549
上一篇: 如何设置mysql远程访问及防火墙设置
下一篇: C#键盘钩子之局部钩子和全局钩子
PGEva
博客等级 码龄10年 78粉丝 129原创
评论 3
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值