Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "WinAPI";
Текущий архив: 2007.07.15;
Скачать: [xml.tar.bz2];

Вниз

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

 
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 вся ветка

Форум: "WinAPI";
Текущий архив: 2007.07.15;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.48 MB
Время: 0.042 c
2-1182207062
matt
2007-06-19 02:51
2007.07.15
текстовые файлы


15-1181846635
ММК
2007-06-14 22:43
2007.07.15
Symbian


2-1182517334
harisma
2007-06-22 17:02
2007.07.15
В чем разница?


6-1165509778
kernel
2006-12-07 19:42
2007.07.15
IdIcmpClient&amp;exception


2-1182084487
Knob
2007-06-17 16:48
2007.07.15
Смещение компонентов Image





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский