本文分2部分 第一爲自定義多項目模板 第二爲vs add-in開發設計模式
效果圖數組
1.自定義模板 app
2. 工具菜單框架
3.窗口函數
4.工程工具
5.文件優化
...ui
一. 多項目模板spa
單項目模板作起來很簡單 選中一個項目在文件一欄中選中導出模板插件
而後選擇項目模板
在最後一項嚮導會給出你的輸出路徑,通常都是系統的用戶文檔路徑+\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; } }
但願對你們有幫助