Поделиться через


Реализация команд

Чтобы реализовать команду в VSPackage, необходимо выполнить следующие задачи:

  1. В VSCT-файле настройте группу команд и добавьте в нее команду. Дополнительные сведения см. в файлах командной таблицы Visual Studio (VSCT).

  2. Зарегистрируйте команду в Visual Studio.

  3. Реализуйте команду.

В следующих разделах объясняется, как зарегистрировать и реализовать команды.

Регистрация команд в Visual Studio

Если команда должна появиться в меню, необходимо добавить ProvideMenuResourceAttribute ее в VSPackage и использовать в качестве значения имя меню или идентификатор ресурса.

[ProvideMenuResource("Menus.ctmenu", 1)]
public sealed class MyPackage : Package
{
    // ...
}

Кроме того, необходимо зарегистрировать команду с помощью .OleMenuCommandService Эту службу можно получить с помощью GetService метода, если VSPackage является производным от Package.

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 и команду, метод должен задать поле флагов команд для каждой команды (в prgCmds параметре) с помощью следующих OLECMDF флагов:

    • OLECMDF_SUPPORTED: поддерживается команда.

    • OLECMDF_INVISIBLE: команда не должна отображаться.

    • OLECMDF_LATCHED: команда включена и, как представляется, была проверка.

    • OLECMDF_ENABLED: включена команда.

    • OLECMDF_DEFHIDEONCTXTMENU: команда должна быть скрыта, если она отображается в контекстном меню.

    • OLECMDF_NINCHED: команда является контроллером меню и не включена, но его раскрывающийся список меню не пуст и по-прежнему доступен. (Этот флаг редко используется.)

  • Если команда была определена в VSCT-файле с флагом TextChanges, задайте следующие параметры:

    • rgwz Задайте для элемента pCmdText параметра новый текст команды.

    • cwActual Задайте для элемента pCmdText параметра размер командной строки.

Кроме того, убедитесь, что текущий контекст не является функцией автоматизации, если только ваша команда не предназначена для обработки функций автоматизации.

Чтобы указать, что поддерживается определенная команда, вернитесь 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;
}