среда, 12 августа 2009 г.

Как управлять IContextMenu, часть 8 - оптимизируем вызов команды по-умолчанию

Это перевод How to host an IContextMenu, part 8 - Optimizing for the default command. Автор: Реймонд Чен.

В программе, что мы написали прошлый раз, можно сделать небольшое улучшение.

Оно заключается в использовании последнего параметра метода IContextMenu.QueryContextMenu:

CMF_DEFAULTONLY
Этот флаг устанавливается, когда пользователь активирует действие по-умолчанию, обычно с помощью двойного щелчка мышью. Этот флаг подсказывает расширению меню ничего не добавлять, если оно не изменяет пункт меню по-умолчанию в меню. Например, расширители всплывающих меню или обработчики drag-and-drop не должны добавлять своих пунктов меню, если этот флаг включён. Расширитель пространства имён (namespace) должен добавлять в меню только пункт по-умолчанию (если таковой есть).

Как следует из этого текста из MSDN, этот флаг указывает реализации IContextMenu, что она должна волноваться только о команде по-умолчанию.

procedure TForm1.FormContextPopup(Sender: TObject; MousePos: TPoint;
var Handled: Boolean);
var
pcm: IContextMenu;
Menu: HMENU;
Info: TCMInvokeCommandInfo;
Id: UINT;
begin
Handled := True;

if SUCCEEDED(GetUIObjectOfFile(Handle, 'C:\Windows\clock.avi', IID_IContextMenu, pcm)) then
try
Menu := CreatePopupMenu;
if Menu <> 0 then
try
if SUCCEEDED(pcm.QueryContextMenu(Menu, 0, SCRATCH_QCM_FIRST, SCRATCH_QCM_LAST, CMF_DEFAULTONLY)) then
begin
Id := GetMenuDefaultItem(Menu, 0, 0);
if Id <> UINT(-1) then
begin
FillChar(Info, SizeOf(Info), 0);
Info.cbSize := SizeOf(info);
Info.hwnd := Handle;
Info.lpVerb := MAKEINTRESOURCEA(Id - SCRATCH_QCM_FIRST);
SetLastError(pcm.InvokeCommand(Info));
if GetLastError <> 0 then
RaiseLastOSError;
end;
end;
finally
DestroyMenu(Menu);
end;
finally
pcm := nil;
end;
end;

С этим изменением на моей машине время выполнения вызова IContextMenu.QueryContextMenu сократилось со 100 мс до 50 мс. Выигрыш на вашей машине может быть иным. Это сильно зависит от того, сколько расширителей меню установлено на вашей машине и сколько из них действительно учитывают флаг CMF_DEFAULTONLY.

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

1 комментарий:

  1. Спасибо,
    Статьи полезные. Запуск через команду по умолчанию устраивает (пока?).

    ОтветитьУдалить

Можно использовать некоторые HTML-теги, например:

<b>Жирный</b>
<i>Курсив</i>
<a href="http://www.example.com/">Ссылка</a>

Вам необязательно регистрироваться для комментирования - для этого просто выберите из списка "Анонимный" (для анонимного комментария) или "Имя/URL" (для указания вашего имени и ссылки на сайт). Все прочие варианты потребуют от вас входа в вашу учётку (поддерживается OpenID).

Пожалуйста, по возможности используйте "Имя/URL" вместо "Анонимный". URL можно просто не указывать.

Ваше сообщение может быть помечено как спам спам-фильтром - не волнуйтесь, оно появится после проверки администратором.