vs多項目模板及add-in開發


本文分2部分 第一為自定義多項目模板 第二為vs add-in開發


效果圖

1.自定義模板 

2. 工具菜單

3.窗口

4.工程

5.文件

 ...

 


 

一. 多項目模板

單項目模板做起來很簡單 選中一個項目在文件一欄中選中導出模板

然后選擇項目模板

在最后一項向導會給出你的輸出路徑,一般都是系統的用戶文檔路徑+\Visual Studio 2010\My Exported Templates

在對應目錄下會生成你對應的項目模板壓縮包

我們生成2個項目的模板文件 然后做一個多項目模板

我們解壓2個模板文件並且放進一個新建的名稱為MaoyaTemplates的文件夾 剪切到Visual Studio 2010\Templates\ProjectTemplates路徑下

新建模板文件MyTemplate.vstemplate

根據要定義的模板內容 修改文件

然后將整個文件夾壓縮成zip文件即可 在TemplateData可以定義一些自己需要的信息 例如icon定義你的模板圖標 把圖標文件放在相對路徑即可

然后重新打開vs 即可看到剛才作成的模板

打開以后就是定義的2個demo工程 相當簡單

這樣就不用每次來新項目都去copy代碼了 


二 vs插件

概念性的東西可以參考 http://msdn.microsoft.com/zh-cn/library/bb384200.aspx

vs插件可以幫助或者優化你在vs開發過程的大部分窗口 它可以針對文件 針對項目 針對窗口 甚至針對不同的后綴做不同的處理

下面圖文+代碼介紹開發步驟(vs2010)

選擇插件項目 進入向導根據自己的場景選擇即可

中間向導過程略過 最后一步

完成向導后 默認工程框架如下

最關鍵的就是connect.cs文件

Connect 繼承了2個類 IDTExtensibility2, IDTCommandTarget

IDTExtensibility2 包含在實現接口時用作事件的方法。 每當發生影響某個外接程序的事件時(如加載或卸載該外接程序時)以及對該外接程序進行任何更改時,Visual Studio 都會調用這些方法。

IDTCommandTarget 接口使開發者得以在環境中實現命名命令。 並且以定義命令狀態或執行命令。

每個方法的描述 

中文版可以參考msdn

http://msdn.microsoft.com/zh-cn/library/extensibility.idtextensibility2.aspx

http://msdn.microsoft.com/zh-cn/library/envdte.idtcommandtarget.aspx

其中我們作為入門開發 需要關注得的是

OnConnection 為IDTExtensibility2的 main 方法,這是因為每次加載外接程序時都會調用該方法。 該方法為外接程序在加載時的入口點,因此可以將要在外接程序啟動時運行的任何代碼放置在此處(或調用任何其他函數)。

void OnConnection(
	Object Application,
	ext_ConnectMode ConnectMode,
	Object AddInInst,
	ref Array custom
)

參數
Application
類型:System.Object
對集成開發環境 (IDE) 的一個實例 (DTE) 的引用,該實例是 Visual Studio 自動化模型的根對象。
ConnectMode
類型:Extensibility.ext_ConnectMode
一個 ext_ConnectMode 枚舉值,指示向 Visual Studio 中加載外接程序的方式。
AddInInst
類型:System.Object
一個對外接程序自己的實例的 AddIn 引用。 此引用存儲起來以供以后使用(如用於確定外接程序的父集合)。
custom
類型:System.Array
一個空數組,可用來傳遞在外接程序中使用的特定於主機的數據。

 

下面我們開始建一個工具欄(Tools)下的菜單

 首先判斷加載方式

if (connectMode == ext_ConnectMode.ext_cm_UISetup || connectMode == ext_ConnectMode.ext_cm_Startup ||
                connectMode == ext_ConnectMode.ext_cm_AfterStartup)

  這里的ConnectMode來自一個枚舉 參考msdn http://msdn.microsoft.com/zh-cn/library/extensibility.ext_connectmode.aspx

然后添加注冊插件命令和窗口 關鍵代碼: 

                    var toolsBar = commandBars[Tools];

                    if (toolsBar != null)
                    {
                        toolsSubPopup = (CommandBarPopup)toolsBar.Controls.Add(MsoControlType.msoControlPopup, Type.Missing, Type.Missing, 1, true);
                        toolsSubPopup.Caption = MainMenuName;
                        CommandBar toolsSubBar = toolsSubPopup.CommandBar;

                        Command command = commands.AddNamedCommand2(
                            _addInInstance,
                            MenuName1,
                            MenuName1,
                            MenuName1,
                            true,
                            190,
                            ref contextGUIDS,
                            (int)vsCommandStatus.vsCommandStatusUnsupported + (int)vsCommandStatus.vsCommandStatusEnabled);
                        command.AddControl(toolsSubBar);

                        command = commands.AddNamedCommand2(
                            _addInInstance,
                            MenuName2,
                            MenuName2,
                            MenuName2,
                            true,
                            190,
                            ref contextGUIDS,
                            (int)vsCommandStatus.vsCommandStatusUnsupported + (int)vsCommandStatus.vsCommandStatusEnabled);
                        command.AddControl(toolsSubBar, 2);
                    }

  commandBars[Tools]表示命令欄中的工具欄,這里Tools實際為定義的字符串“Tools”。

  CommandBarPopup表示彈出命令條。

  _addInInstance表示當前插件實例。

  3個Menuname分別表示命令名稱的縮寫形式,UI顯示的名稱以及當用戶將鼠標指針懸停在任何綁定到新命令的控件上時所顯示的文本。

  true表示下面的190 為 Microsoft Office 位圖的 ID。

  ContextUIGUIDs表示GUID 確定哪些環境上下文 (即調試模式,設計模式,等等) 顯示命令。

  vsCommandStatusValue確定命令的禁用條件是不可見或禁用,當您提供一個 ContextUIGUIDs 參數,並且都不是當前活動的。

  AddNamedCommand2 創建命名命令,該命令由環境保存,並且在下次環境啟動時(無論是否加載外接程序)可用。 外接程序以后可以通過響應 QueryStatus 方法來更改 ButtonText 名稱。 如果文本以 # 開頭,則該字符串的其余部分是一個整數,該整數表示外接程序已注冊的附屬 DLL 中的資源 ID。有兩個默認值順序狀態:該默認值啟用了狀態和默認值可見性狀態。 這些默認狀態很重要,如果找不到命令處理程序 (因為該元素未加載或不實現 IDTCommandTarget)。 如果您的組件加載並實現 IDTCommandTarget,默認值不適用。

  Command.AddControl創建此命令的持久性命令欄控件。后面的數字表示菜單位置。

  詳細參考http://msdn.microsoft.com/zh-cn/library/envdte80.commands2.addnamedcommand2.aspx

  這樣基本上就完成了下圖所示的效果

  但是我們需要對2個菜單進行功能型的開發

  QueryStatus方法返回指定的已命名命令的當前狀態(啟用、禁用、隱藏等)。

  在此方法添加片段

  if (neededText == vsCommandStatusTextWanted.vsCommandStatusTextWantedNone)
            {
                if (commandName == GetCommandName(MainMenuName))
                {
                    status = vsCommandStatus.vsCommandStatusSupported | vsCommandStatus.vsCommandStatusEnabled;
                    return;
                }
        }

  vsCommandStatusSupported表示命令在此上下文中受支持,vsCommandStatusEnabled表示命令當前處於啟用狀態。

  Exec方法執行指定的命名命令。

            if (executeOption == vsCommandExecOption.vsCommandExecOptionDoDefault)
            {
                if (commandName == GetCommandName(MainMenuName))
                {
                    MessageBox.Show("This is maoya test");
                    handled = true;
                    return;
                }

                if (commandName == GetCommandName(MenuName1))
                {
                    MessageBox.Show("This is maoya Test1 test");
                    handled = true;
                    return;
                }

                if (commandName == GetCommandName(MenuName2))
                {
                    MessageBox.Show("This is maoya Test2 test");
                    handled = true;
                    return;
                }

            }

  這里實現的很簡單就是彈出個winform。你可以在這里實現很豐富的功能。

 


 

上面是工具欄的實現,下面介紹個操作窗口的

  Onconnection:

                    CommandBar mdiCommandBar = commandBars["Easy MDI Document Window"];
                    if (mdiCommandBar != null)
                    {
                        Command mdiCmd = commands.AddNamedCommand2(_addInInstance, MenuName3,
                                                                            MenuName3,
                                                                            MenuName3, false, 0,
                                                                            ref contextGUIDS);

                        mdiCmd.AddControl(mdiCommandBar);
                    }

  QueryStatus:

            if (commandName == GetCommandName(MenuName3) || commandName == GetCommandName(MenuName4) || commandName == GetCommandName(MenuName5))
            {
                status = vsCommandStatus.vsCommandStatusSupported | vsCommandStatus.vsCommandStatusEnabled;
                return;
            }

  Exec 功能是新建一個文件

            if (commandName == GetCommandName(MenuName3))
            {
                _applicationObject.ExecuteCommand("File.NewFile", string.Empty);
                handled = true;
                return;
            }

  


 

  下面我們在做一個針對項目工程的自定義按鈕

  OnConnection:

 CommandBar projectBar = commandBars["Project"];
                    if (projectBar != null)
                    {
                        projectSubPopup = (CommandBarPopup)projectBar.Controls.Add(MsoControlType.msoControlPopup, Type.Missing, Type.Missing, 1, true);
                        projectSubPopup.Caption = MainMenuName;
                        CommandBar projectSubBar = projectSubPopup.CommandBar;
                        Command projectCommand = commands.AddNamedCommand2(
                                                   _addInInstance,
                                                   MenuName4,
                                                   MenuName4,
                                                   MenuName4,
                                                   true,
                                                   190,
                                                   ref contextGUIDS,
                                                   (int)vsCommandStatus.vsCommandStatusUnsupported + (int)vsCommandStatus.vsCommandStatusEnabled);

                        if (projectSubBar != null)
                        {
                            projectCommand.AddControl(projectSubBar, 1);
                        }

                    }

  QueryStatus:

            if (commandName == GetCommandName(MenuName3) || commandName == GetCommandName(MenuName4) || commandName == GetCommandName(MenuName5))
            {
                status = vsCommandStatus.vsCommandStatusSupported | vsCommandStatus.vsCommandStatusEnabled;
                return;
            }

  Exec 這里可以抓到你選擇的是哪一個項目 包括名稱 路徑等等 根據具體的需求再來處理對應的邏輯

  if (commandName == GetCommandName(MenuName4))
            {
                MessageBox.Show(string.Format("This is maoya {0} test,/r/n該項目名稱為{1}", MenuName4, _applicationObject.SelectedItems.Item(1).Name));
                handled = true;
                return;
            }

  

  

 

類似的還有操作文件,代碼就不貼了 直接上圖

值得一提你可以利用文件后綴等做一些特殊操作

在QueryStatus方法中添加

            if (commandName == GetCommandName(MenuName6))
            {
                var uiHierarchy = (UIHierarchy)_applicationObject.Windows.Item(
                        Constants.vsWindowKindSolutionExplorer).Object;
                if ((from UIHierarchyItem item in (Array)uiHierarchy.SelectedItems select item.Name).Any(itemName => itemName.IndexOf(".config") > -1))
                {
                    status = vsCommandStatus.vsCommandStatusEnabled | vsCommandStatus.vsCommandStatusSupported;
                }
            }

  


 

希望對大家有幫助 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM