共用方式為


命令實作

若要在 VSPackage 中實作命令,您必須執行下列工作:

  1. .vsct 檔案中,設定命令群組,然後將命令新增至其中。 如需詳細資訊,請參閱 Visual Studio 命令資料表 (.vsct) 檔案

  2. 向 Visual Studio 註冊命令。

  3. 實作命令。

下列各節說明如何註冊和實作命令。

使用 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;
}