1. 程式人生 > >Excel外掛快捷鍵彈窗事件(VSTO+鍵盤鉤子實現)

Excel外掛快捷鍵彈窗事件(VSTO+鍵盤鉤子實現)

外掛功能 在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,如果沒有找到解決平臺不相容的辦法,打算使用這個來替換。
暫時先寫到這兒 附上完整專案程式碼下載地址