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

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/ProgramVAE/article/details/80290251

插件功能 在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,如果没有找到解决平台不兼容的办法,打算使用这个来替换。
暂时先写到这儿 附上完整项目代码下载地址

猜你喜欢

转载自blog.csdn.net/ProgramVAE/article/details/80290251