
![]() |
Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
|
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[18.97.14.86] |
![]() |
|
Страницы: (2) [1] 2 все ( Перейти к последнему сообщению ) |
Сообщ.
#1
,
|
|
|
Здравствуйте. У меня такой вопрос - как "воздействовать" на стандартное меню, которое появляется при нажатии правой кнопки мыши в поле для ввода текста ("отменить","вырезать","копировать" и т.д.), например, в TEdit, TF1Book. В смысле, запретить/разрешить 1 из пуктов. По идее, надо ловить какое-то сообщение, но не знаю, какое. Думал - WM_CONTEXTMENU, WM_INITMENUPOPUP, нет, не то
|
Сообщ.
#2
,
|
|
|
Цитата The EnableMenuItem function enables, disables, or grays the specified menu item. BOOL EnableMenuItem( HMENU hMenu, // handle to menu UINT uIDEnableItem, // menu item to enable, disable, or gray UINT uEnable // menu item flags ); |
Сообщ.
#3
,
|
|
|
Эта функция получает хэндл меню и разрешает/запрещает его пункты. Как мне получить HMENU, если это не моё меню, т. е. в программе я его не создаю?
|
![]() |
Сообщ.
#4
,
|
|
vet, HMENU родного меню EDIT'а, имхо ты никак не получишь. Можешь просто задать свое PopupMenu для TEdit'а
![]() ![]() Edit1.PopupMenu:=PopupMenu1; и делать с ним все, что душа пожелает. |
![]() |
Сообщ.
#5
,
|
|
Цитата Krid @ vet, HMENU родного меню EDIT'а, имхо ты никак не получишь. Да ну брось ты, нет ничего не возможного ![]() ![]() ![]() unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, Menus; type TForm1 = class(TForm) Edit1: TEdit; private procedure WMContextMenu(var Message: TWMContextMenu); message WM_CONTEXTMENU; end; var Form1: TForm1; implementation var HookHandle: DWORD = 0; {$R *.dfm} function MsgProc(Code: Integer; WParam: Integer; LParam: PCWPStruct): Integer; stdcall; var Menu: HMENU; ItemCount, I: Integer; begin if (Code = HC_ACTION) then case LPARAM.message of WM_MENUSELECT: begin Menu := LParam^.lParam; // Вот он хэндл меню ItemCount := GetMenuItemCount(Menu); for I := 0 to ItemCount - 1 do EnableMenuItem(Menu, GetMenuItemID(Menu, I), MF_DISABLED or MF_GRAYED); UnhookWindowsHookEx(HookHandle); HookHandle := 0; end; $01E2: // это типа заставляем реагировать на WM_MENUSELECT до появления окна... SendMessage(LPARAM.HWND, $1E5, 0, 0); end; MsgProc := CallNextHookEx(HookHandle, Code, WPARAM, DWORD(LPARAM)); end; procedure TForm1.WMContextMenu(var Message: TWMContextMenu); begin if HookHandle <> 0 then UnhookWindowsHookEx(HookHandle); HookHandle := SetWindowsHookEx(WH_CALLWNDPROC, @MsgProc, 0, GetCurrentThreadId); end; end. |
![]() |
Сообщ.
#6
,
|
|
![]() Я и сам потом понял, что поспешил с выводами. Все-таки не надо забывать про подпись Song'а ![]() Вот еще вариант ![]() ![]() unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TForm1 = class(TForm) Edit1: TEdit; procedure FormCreate(Sender: TObject); private { Private declarations } public { Public declarations } end; var Form1: TForm1; implementation {$R *.dfm} var fb:boolean=true; function NewEditProc(wnd:HWND; uMsg:UINT; wParam:WPARAM; lParam:LPARAM):integer; stdcall; const MN_SELECTITEM = $1E5; begin case uMsg of WM_ENTERIDLE: if (wParam=MSGF_MENU) and fb then begin SendMessage(lParam, MN_SELECTITEM, 0, 0); fb:=false end; WM_MENUSELECT: begin if (lParam=0) and (HIWORD(DWORD(wParam))=word(-1)) then fb:=true else if fb then begin // извращаемся над меню EnableMenuItem(lParam, GetMenuItemID(lParam, 2), MF_DISABLED or MF_GRAYED); DeleteMenu(lParam,1,MF_BYPOSITION); DeleteMenu(lParam,5,MF_BYPOSITION); end end; end; result:=CallWindowProc(Pointer(GetWindowLong(wnd,GWL_USERDATA)),wnd,uMsg,wParam,lParam) end; procedure TForm1.FormCreate(Sender: TObject); begin SetWindowLong(Edit1.Handle,GWL_USERDATA,SetWindowLong(Edit1.Handle, GWL_WNDPROC, LPARAM(@NewEditProc))) end; end. |
Сообщ.
#7
,
|
|
|
Цитата Krid @ WM_ENTERIDLE: if (wParam=MSGF_MENU) and fb then begin SendMessage(lParam, MN_SELECTITEM, 0, 0); fb:=false end; во-во, это как раз та ж, о которой я так недавно говорил ![]() |
![]() |
Сообщ.
#8
,
|
|
Она самая
![]() Это окно можно еще WinEventHook'ом достать, но это еще бОльшая ж. ![]() |
Сообщ.
#9
,
|
|
|
Спасибо за помощь, значит, я в правильном направлении думал (WM_CONTEXTMENU). Работает, второй вариант ещё не пробовал. Ещё вопрос насчёт $01E2 - что это, в Messages такого нет?
|
Сообщ.
#10
,
|
|
|
А не подскажите как отследить движение мышки на компоненте PopupMenu? Интересует именно то, что нужно узнать над каким Item' ом он находится, т.к. у Item' ов нет свойства OnMouseMove.
|
Сообщ.
#11
,
|
|
|
Перехват сообщения WM_MENUSELECT (проще через хук как в #5), плюс код определения MenuItem по ItemID - можно взять из исходника TPopupList.WndProc в модуле menus.pas
|
Сообщ.
#12
,
|
|
|
Цитата leo @ Перехват сообщения WM_MENUSELECT (проще через хук как в #5), плюс код определения MenuItem по ItemID - можно взять из исходника TPopupList.WndProc в модуле menus.pas Есть небольшой опыт, но он почему-то работает только с MainMenu, В чём проблема может быть? ![]() ![]() unit main; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, Menus, StdCtrls; type TForm1 = class(TForm) lbl1: TLabel; suiPopupMenu1: TsuiPopupMenu; private procedure WmMenuSelect (var Message: TMessage); message WM_MENUSELECT; end; var Form1: TForm1; implementation {$R *.dfm} { TForm1 } procedure TForm1.WmMenuSelect(var Message: TMessage); var Item: TMenuItem; I: Integer; begin Item := suiPopyupMenu1.FindItem(Message.LParam, fkHandle); if Assigned(Item) then for I := 0 to Item.Count - 1 do if Item.Items[I].Command = Message.WParamLo then lbl1.Caption:= Item.Items[I].Caption); //Записываем выбранный Item end; end. |
Сообщ.
#13
,
|
|
|
Цитата eclipse_99 @ В чём проблема может быть? В том, что родительским окном для всех PopupMenu является не форма, а PopupList.Window. Поэтому нужно либо подменять его WndProc через SetWindowLong, либо проще - использовать хук SetWindowHookEx |
Сообщ.
#14
,
|
|
|
Код в #5\WM_CONTEXTMENU не работает при первом ПКМ на TEdit.
Но работает при ПКМ на самой форме. Delphi XE3... |
Сообщ.
#15
,
|
|
|
Цитата BugMeNot @ Код в #5\WM_CONTEXTMENU Зачем тебе вообще WM_CONTEXTMENU? С ним такая же проблема, как и WM_MENUSELECT - шлется родительскому окну меню, которое не обязано быть именно формой. Можно просто установить хук в FormCreate и снять в FormDestroy, а "включать\выключать" его установкой доп.глобальной переменной HookOn:boolean - если установлена, то что-то делаешь в процедуре хука, если нет, то сразу вызываешь CallNextHookEx |