Форум: "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.045 c