IVsTextManager::GetActiveView(true, null, ...) возвращает не сфокусированное представление

Я играю с созданием команды редактирования текста Visual Studio. Я дошел до создания пакета, связывания команды, помещения ее в меню. Но что я не могу сделать рекомендованным Microsoft способом, так это выяснить, существует ли активное текстовое представление, к которому должна применяться команда.

Я следую инструкциям в руководстве VSSDK (прокрутите вниз до Использование команды меню, чтобы добавить украшение комментария). После выбора команды из меню, обработчик команд mt вызывается нормально. однако, когда выполняется следующий точный учебный код, полученные результаты противоречивы.

IVsTextManager txtMgr = (IVsTextManager)GetService(typeof(SVsTextManager));
IVsTextView vTextView = null;
int mustHaveFocus = 1;
txtMgr.GetActiveView(mustHaveFocus, null, out vTextView);

Теперь, если есть только текстовые представления, все работает так, как вы ожидаете: возвращается активное текстовое представление. Но добавьте другой вид на картинке (я использую редактор растровых изображений), и вид, возвращенный GetActiveView Похоже, что последний активный просмотр текста. Т.е., если я переключаю вкладки, чтобы отобразить растровое представление поверх ранее активного представления в fileA, то возвращается такое же представление для fileA. Другими словами, я не могу понять, фокусируется ли текстовое представление или нет.

Теперь, это кажется несовместимым с (хотя и плохой) документацией IVsTextManager::GetActiveView(), Он должен сказать о первом аргументе функции: если true, тогда возвращается текущее активное представление пользовательского интерфейса. Я правильно читаю? Поведение, которое я наблюдаю, похоже, соответствует другому случаю: если false, то возвращается последнее активное представление, независимо от того, является ли это представление активным в настоящее время пользовательским интерфейсом.

Я могу найти другой способ привязки команд к представлениям, а именно путем подключения создания представления. Что меня здесь беспокоит, так это то, что я не могу обработать команду рекомендованным Microsoft способом.

3 ответа

Решение

Что ж, извините за запутанную документацию, но это пошаговое руководство я бы не рекомендовал для вашего случая (я разработчик в команде редактора VS).

Как вы указали, вы можете обрабатывать команды намного проще, подключив фильтр команд через IVsTextViewCreationListener, на самом деле это более распространенный и лучший способ, см. Пошаговое руководство. Использование сочетания клавиш с расширением редактора (это также своего рода запутанный заголовок:()

Ответ от команды разработчиков VS на использование другого метода может сработать для человека, который задал исходный вопрос, но для нас, которые хотят использовать GetActiveView по другим причинам, остается вопрос: как получить только текстовые окна с фокусом а не последнее текстовое окно с фокусом? Ненадежная документация (которая предполагает, что mustHaveFocus является логическим значением, даже если это int), кажется, вводит в заблуждение, так как установка значения в 0 или 1 (или -1) приводит к тому, что последнее текстовое окно возвращается с фокусом.

GetActiveView(fMustHaveFocus, pBuffer, out ppView) видимо игнорирует fMustHaveFocus если pBuffer является null, Если это не так nullработает как документировано.

Таким образом, вы можете получить представление "активный и должен иметь фокус", позвонив GetActiveView второй раз с буфером представления, которое он возвратил в первый раз.

IVsTextView vsTextView;
IVsTextLines vsTextLines;
// `GetActiveView` apparently ignores `fMustHaveFocus` if `pBuffer` is null, so call
// it a second time with the buffer from the view it returned the first time to find
// out if the view actually has focus.
if (textManager.GetActiveView(1, null, out vsTextView) == VSConstants.S_OK &&
    vsTextView.GetBuffer(out vsTextLines) == VSConstants.S_OK &&
    textManager.GetActiveView(1, vsTextLines, out vsTextView) == VSConstants.S_OK)
{
    // vsTextView has focus.
}
Другие вопросы по тегам