Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2007.07.15;
Скачать: CL | DM;

Вниз

Как добавить подменю в системное контекстное меню   Найти похожие ветки 

 
Lucky13   (2007-02-08 13:40) [0]

Добавил пункт в системное контекстное меню. Теперь нужно, чтобы у него было подменю. Добавить подменю не проблема, вопрос как узнать что пользователь выбрал некоторый пункт подменю, ведь InvokeCommand для подменю не вызывается?


 
Lucky13   (2007-02-08 15:53) [1]

Добавил пункт в системное контекстное меню. Теперь нужно, чтобы у него было подменю. Добавить подменю не проблема, вопрос как узнать что пользователь выбрал некоторый пункт подменю, ведь InvokeCommand для подменю не вызывается?


 
Rouse_ ©   (2007-02-08 15:58) [2]

IContextMenu3 -> HandleMenuMsg2()


 
Lucky13   (2007-02-08 17:36) [3]

Я пробовал перекрывать IContextMenu3 -> HandleMenuMsg2(), но это ничего не дало (у меня WinXP). Можете привести пример использования этой функции.


 
DiamondShark ©   (2007-02-08 19:18) [4]


> ведь InvokeCommand для подменю не вызывается

Ложь. Вызывается.

Вот модифицированный фрагмент демонстационного проекта
\Demos\Activex\Shellext\contmenu


function TContextMenu.QueryContextMenu(Menu: HMENU; indexMenu, idCmdFirst, idCmdLast, uFlags: UINT): HResult;
// added by DiamondShark
var
 SubMenu: HMENU;
// added by DiamondShark \\
begin
 Result := 0; // or use MakeResult(SEVERITY_SUCCESS, FACILITY_NULL, 0);

 if ((uFlags and $0000000F) = CMF_NORMAL) or
    ((uFlags and CMF_EXPLORE) <> 0) then begin

   // added by DiamondShark
   SubMenu := CreatePopupMenu;
   InsertMenu(Menu, indexMenu, MF_STRING or MF_POPUP or MF_BYPOSITION, SubMenu, "Qwuqweqwo");
   // added by DiamondShark \\

   // Add one menu item to context menu

   // commented out by DiamondShark
   //InsertMenu(Menu, indexMenu, MF_STRING or MF_BYPOSITION, idCmdFirst,
   //  "Compile...");
   // commented out by DiamondShark \\

   // added by DiamondShark
   InsertMenu(SubMenu, 0, MF_STRING or MF_BYPOSITION, idCmdFirst,
     "Compile...");
   // added by DiamondShark \\

   // Return number of menu items added
   Result := 1; // or use MakeResult(SEVERITY_SUCCESS, FACILITY_NULL, 1)
 end;
end;


Очень даже прекрасно всё вызывается.
А вы, видимо, что-то где-то не туда добавляете.


 
Lucky13   (2007-02-09 09:14) [5]


> Очень даже прекрасно всё вызывается.А вы, видимо, что-то
> где-то не туда добавляете.

Да, Вы правы, вчера покопал, действительно вызывается, но только как-то не так как хотелось бы. Я неправильно создавал меню.

MSDN:
32-bit value that contains zero in the high-order word and a menu-identifier offset of the command to carry out in the low-order word. The shell specifies this value (using the MAKEINTRESOURCE macro) when the user chooses a menu command.

Т.е. LOWORD(lpVerb) содержит идентификатор выбранного пункта меню, а HIWORD(lpVerb) должно быть = 0. Но как выяснилось этого мало, при таких условиях команда выполняется, когда пункт меню еще даже не успел появиться. Видимо нужно проверять что-то еще.

Как по вашему должен выглядить метод InvokeCommand для меню, приведенного выше?


 
DiamondShark ©   (2007-02-09 11:57) [6]


> Т.е. LOWORD(lpVerb) содержит идентификатор выбранного пункта
> меню

А слово offset только для красоты написано?

Если в QueryContextMenu(Menu: HMENU; indexMenu, idCmdFirst, idCmdLast, uFlags: UINT) создаются пункты с uIDNewItem равными idCmdFirst, idCmdFirst+1,..,idCmdFirst+n, то в InvokeCommand LOWORD(lpVerb) будет равно 0, 1,...,n.


> Как по вашему должен выглядить метод InvokeCommand для меню,
>  приведенного выше?

В примере, который я приводил (в подменю только один пункт, тот, что раньше был самостоятельным), код InvokeCommand абсолютно без изменений.

Вот изменённый код того же демо-проекта для нескольких пунктов меню:


function TContextMenu.QueryContextMenu(Menu: HMENU; indexMenu, idCmdFirst,
         idCmdLast, uFlags: UINT): HResult;
// added by DiamondShark
var
 SubMenu: HMENU;
// added by DiamondShark \\
begin
 Result := 0; // or use MakeResult(SEVERITY_SUCCESS, FACILITY_NULL, 0);

 if ((uFlags and $0000000F) = CMF_NORMAL) or
    ((uFlags and CMF_EXPLORE) <> 0) then begin

   // added by DiamondShark
   SubMenu := CreatePopupMenu;
   InsertMenu(Menu, indexMenu, MF_STRING or MF_POPUP or MF_BYPOSITION, SubMenu, "Qwuqweqwo");
   // added by DiamondShark \\

   // Add one menu item to context menu
   // commented out by DiamondShark
   //InsertMenu(Menu, indexMenu, MF_STRING or MF_BYPOSITION, idCmdFirst,
   //  "Compile...");
   // commented out by DiamondShark \\

   // added by DiamondShark
   InsertMenu(SubMenu, 0, MF_STRING or MF_BYPOSITION, idCmdFirst,
     "Compile...");
   InsertMenu(SubMenu, 1, MF_STRING or MF_BYPOSITION, idCmdFirst+1,
     "zzz 1");
   InsertMenu(SubMenu, 2, MF_STRING or MF_BYPOSITION, idCmdFirst+2,
     "zzz 2");
   // added by DiamondShark \\

   // Return number of menu items added
   //Result := 1; // or use MakeResult(SEVERITY_SUCCESS, FACILITY_NULL, 1)
   Result := 3; // by DiamondShark
 end;
end;

function TContextMenu.InvokeCommand(var lpici: TCMInvokeCommandInfo): HResult;
resourcestring
 sPathError = "Error setting current directory";

var
 H: THandle;
 PrevDir: string;
 
begin
 Result := E_FAIL;
 // Make sure we are not being called by an application
 if (HiWord(Integer(lpici.lpVerb)) <> 0) then
 begin
   Exit;
 end;

 // Make sure we aren"t being passed an invalid argument number
 // commented out by DiamondShark
 //if (LoWord(lpici.lpVerb) <> 0) then begin
 //  Result := E_INVALIDARG;
 //  Exit;
 //end;

 if (LoWord(lpici.lpVerb) > 2) then begin
   Result := E_INVALIDARG;
   Exit;
 end;

 // added by DiamondShark
 case LoWord(lpici.lpVerb) of
 0: begin
 // added by DiamondShark \\

 // Execute the command specified by lpici.lpVerb
 // by invoking the Delphi command line compiler.
 PrevDir := GetCurrentDir;
 try
   if not SetCurrentDir(ExtractFilePath(FFileName)) then
     raise Exception.CreateRes(@sPathError);

   H := WinExec(PChar(Format(GetCompilerPath, [FFileName])), lpici.nShow);

   if (H < 32) then
     MessageBox(lpici.hWnd, "Error executing Delphi compiler.", "Error",
       MB_ICONERROR or MB_OK);
   Result := NOERROR;
 finally
   SetCurrentDir(PrevDir);
 end;
 // added by DiamondShark
 end;
 1: ShowMessage("zzz 1");
 2: ShowMessage("zzz 2");
 end; {case}
 // added by DiamondShark \\
end;



 
Lucky13   (2007-02-09 12:11) [7]

Про offset я не забыл. Вся проблема была в том, что я не указал:
if (LoWord(lpici.lpVerb) > 2) then
begin
  Result := E_INVALIDARG;
  Exit;
end;

Спасибо DiamondShark за ответы



Страницы: 1 вся ветка

Текущий архив: 2007.07.15;
Скачать: CL | DM;

Наверх




Память: 0.49 MB
Время: 0.014 c
8-1161605495
Ketrikken
2006-10-23 16:11
2007.07.15
Настройка звука в DirectShow


2-1182271738
Тимофей
2007-06-19 20:48
2007.07.15
Формы


2-1182464746
Lokk83
2007-06-22 02:25
2007.07.15
Обновление DBGRID по таймеру


3-1176371776
Анна
2007-04-12 13:56
2007.07.15
Как обработать в приложении разрыв connect-a


15-1181582567
DillerXX
2007-06-11 21:22
2007.07.15
Вопрос к тем, кто программировал мобильники