命令實作
若要在 VSPackage 中實作命令,您必須執行下列工作:
在 .vsct 檔案中,設定命令群組,然後將命令新增至其中。 如需詳細資訊,請參閱 Visual Studio 命令資料表 (.vsct) 檔案。
向 Visual Studio 註冊命令。
實作命令。
下列各節說明如何註冊和實作命令。
使用 Visual Studio 註冊命令
如果您的命令要出現在功能表上,您必須將 ProvideMenuResourceAttribute 新增至 VSPackage,並用來做為功能表名稱或其資源識別碼的值。
[ProvideMenuResource("Menus.ctmenu", 1)]
public sealed class MyPackage : Package
{
// ...
}
此外,您必須使用 OleMenuCommandService 註冊命令。 如果您的 VSPackage 衍生自 Package,您可以使用 GetService 方法取得此服務。
OleMenuCommandService mcs = GetService(typeof(IMenuCommandService)) as OleMenuCommandService;
if (mcs is not null)
{
// Create the command for the menu item.
CommandID menuCommandID = new CommandID(guidCommandGroup, myCommandID);
MenuCommand menuItem = new MenuCommand(MenuItemCallback, menuCommandID);
mcs.AddCommand(menuItem);
}
實作命令
有數種方式可以實作命令。 如果您想要靜態功能表命令,這是一律以相同方式和相同功能表上顯示的命令,請使用 MenuCommand 建立命令,如上一節的範例所示。 若要建立靜態命令,您必須提供負責執行命令的事件處理常式。 因為命令一律已啟用且可見,因此您不需要將其狀態提供給 Visual Studio。 如果您想要根據特定條件變更命令的狀態,您可以將命令建立為 OleMenuCommand 類別的執行個體,並在其建構函式中提供事件處理常式來執行命令,並在命令狀態變更時透過 QueryStatus
處理常式通知 Visual Studio。 您也可以實作 IOleCommandTarget 以做為命令類別的一部分,或者,如果您在專案中提供命令,則可以實作 IVsHierarchy。 這兩個介面和 OleMenuCommand 類別都有方法可通知 Visual Studio 命令的狀態變更,以及提供命令執行的其他方法。
當命令新增至命令服務時,它會變成其中一個命令鏈結。 當您實作命令的狀態通知和執行方法時,請小心只針對該特定命令提供,並將所有其他案例傳遞給鏈結中的其他命令。 如果您無法傳遞命令 (通常是傳回 OLECMDERR_E_NOTSUPPORTED),Visual Studio 可能會停止正常運作。
QueryStatus 方法
如果您要實作 QueryStatus 方法或 QueryStatusCommand 方法,請檢查命令集的 GUID,以及命令的識別碼。 請遵循這些方針:
如果無法辨識 GUID,則任一方法的實作必須傳回 OLECMDERR_E_UNKNOWNGROUP。
如果您的任一方法實作可辨識 GUID 但尚未實作命令,則方法應該會傳回 OLECMDERR_E_NOTSUPPORTED。
如果您的任一方法實作會同時辨識 GUID 和命令,則方法應該使用下列 OLECMDF 旗標來設定每個命令的命令旗標欄位 (在
prgCmds
參數中):OLECMDF_SUPPORTED
:可支援命令。OLECMDF_INVISIBLE
:不應該顯示命令。OLECMDF_LATCHED
:命令切換為開,而且似乎已被選取。OLECMDF_ENABLED
:命令已啟用。OLECMDF_DEFHIDEONCTXTMENU
:如果命令出現在快速鍵功能表上,應該隱藏它。OLECMDF_NINCHED
:命令是功能表控制器,而且未啟用,但其下拉功能表清單不是空的,仍然可供使用。 (使用者很少用到這個旗標。)
如果使用
TextChanges
旗標在 .vsct 中定義命令,請設定下列參數:將
pCmdText
參數的rgwz
元素設定為命令的新文字。將
pCmdText
參數的cwActual
元素設定為命令字串的大小。
此外,請確定目前的內容不是自動化函式,除非您的命令專門用來處理自動化函式。
若要指出您支援特定命令,請傳回 S_OK。 針對所有其他命令,傳回 OLECMDERR_E_NOTSUPPORTED。
在下列範例中,QueryStatus
方法會先確定內容不是自動化函式,然後尋找正確的命令集 GUID 和命令識別碼。 命令本身會設定為啟用和支援。 不支援任何其他命令。
public int QueryStatus(ref Guid pguidCmdGroup, uint cCmds, OLECMD[] prgCmds, IntPtr pCmdText)
{
if (!VsShellUtilities.IsInAutomationFunction(m_provider.ServiceProvider))
{
if (pguidCmdGroup == VSConstants.VSStd2K && cCmds > 0)
{
// make the Right command visible
if ((uint)prgCmds[0].cmdID == (uint)VSConstants.VSStd2KCmdID.RIGHT)
{
prgCmds[0].cmdf = (int)Microsoft.VisualStudio.OLE.Interop.Constants.MSOCMDF_ENABLED | (int)Microsoft.VisualStudio.OLE.Interop.Constants.MSOCMDF_SUPPORTED;
return VSConstants.S_OK;
}
}
}
return Constants.OLECMDERR_E_NOTSUPPORTED;
}
執行方法
Exec
方法的實作類似於 QueryStatus
方法的實作。 首先,請確定內容不是自動化函式。 然後,測試 GUID 和命令識別碼。 如果無法辨識 GUID 或指令識別碼,則傳回 OLECMDERR_E_NOTSUPPORTED。
若要處理命令,請執行指令,並在執行成功時傳回 S_OK。 您的命令負責錯誤偵測和通知;因此,如果執行失敗,則傳回錯誤碼。 下列範例旨在示範應如何實作執行方法。
public int Exec(ref Guid pguidCmdGroup, uint nCmdID, uint nCmdexecopt, IntPtr pvaIn, IntPtr pvaOut)
{
if (!VsShellUtilities.IsInAutomationFunction(m_provider.ServiceProvider))
{
if (pguidCmdGroup == VSConstants.GUID_VSStandardCommandSet97)
{
if (nCmdID == (uint)VSConstants.VSStd2KCmdID.RIGHT)
{
// execute the command
return VSConstants.S_OK;
}
}
}
return Constants.OLECMDERR_E_NOTSUPPORTED;
}