![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Запрет всех контекстных меню ;в системе (ловушка) [D7, Win95/98, WinME, NT4, Win2k, WinXP]
_ALEXey_ © (2003-04-09 19:03:00)Здравствуйте, мастера и все, кто читает мой вопрос!
Вот какой вопрос меня интересует:
Есть библиотека, в ней - ловушка, которая должна запрещать показ всех всплывающих меню в системе. Запретить не удалось, а вот при выводе тут же его убрать можно. Код приведен ниже. Но вот незадача! менюшка, появляясь, и, тут же, исчезая, создает некрасивый эффект мерцания. В том-то и вопрос: как от этого избавиться ?Может посоветуете какие-нибудь иные способы решения этой задачи...
library Hooks;
uses
Windows,
Messages;
var
PopupMenuH: THandle;
{$R *.res}
function PopupMenuHook(Code, wParam, lParam: Integer): LResult; stdcall;
var
Param: ^MSG;
begin
Result:= 1;
If Code >= 0
then begin
Param:= Pointer(lParam);
If Code = MSGF_MENU
then SendMessage(Param^.hwnd, WM_CANCELMODE, 0, 0)
else Result:= CallNextHookEx(PopupMenuH, Code, wParam, lParam);
end
else
Result:= CallNextHookEx(PopupMenuH, Code, wParam, lParam);
end;
function SetPopupMenuHook: Boolean;
begin
Result:= True;
PopupMenuH:= SetWindowsHookEx(WH_SYSMSGFILTER, @PopupMenuHook, hInstance, 0);
If PopupMenuH = 0 then
Result:= False;
end;
procedure RemovePopupMenuHook;
begin
UnhookWindowsHookEx(PopupMenuH);
end;
exports
SetPopupMenuHook Name "SetPopupMenuHook",
RemovePopupMenuHook Name "RemovePopupMenuHook";
end.
Vlad Oshin (2003-04-11 08:23:00) [21]
> Almaz © (11.04.03 01:31)
Вам бы статью по этому поводу написать.
Almaz (2003-04-11 01:31:00) [22]Как вам должно быть известно, показ любого всплывающего меню в системе сводится к вызову функции
TrackPopupMenuEx. Чтобы запретить показ всплывающих меню, необходимо запретить возможность вызова этой функции.
Известно, что данная функция реализуется в системной DLL - user32.dll, поэтому получить адрес точки входа в эту функцию можно следующим образом:
var
Address: Pointer;
...
Address := GetProcAddress(GetModuleHandle("USER32.DLL"), "TrackPopupMenuEx");
А теперь, зная точку входа, необходимо просто записать по этому адресу:
asm
MOV EAX,$0 // Результат выполнения функции всегда будет 0
RET 24 // 24 - это суммарный размер передаваемых через стек параметров
end;
В переводе на машинный код, это будет выглядеть как:
$B8 00 00 00 00 C2 18 00
Обобщая вышесказанное, получаем следующий код, запрещающий вызов TrackPopupMenuEx для отдельного процесса:
function DisablePopupMenu: Boolean;
const
CmdBuffer: array [0..7] of Byte = ($B8, $00, $00, $00, $00, $C2, $18, $00);
var
Address: Pointer;
OldProtect, Protect: DWORD;
begin
Address := GetProcAddress(GetModuleHandle("USER32.DLL"), "TrackPopupMenuEx");
if (Address <> nil) and VirtualProtect(Address, sizeof(CmdBuffer),
PAGE_EXECUTE_READWRITE, @Protect) then
begin
MoveMemory(Address, @CmdBuffer, sizeof(CmdBuffer));
VirtualProtect(Address, sizeof(CmdBuffer), Protect, @Protect)
end;
end;
Но я не зря подчеркнул, что именно для отдельного процесса, т.к. из за изолированности АП, изменения вносимые одной задачей не распроcтраняются на другие :)
Таким образом, чтобы запретить всплывающие меню во всей системе достаточно вызвать эту функцию в АП каждого процесса системы. Для этого достаточно описать эту функцию в DLLEntryPoint в обработчике события DLL_PROCESS_ATTACH глобальной ловушки типа WH_GETMESSAGE.
procedure DLLEntryPoint(dwReason: DWORD);
begin
case dwReason of
DLL_PROCESS_ATTACH:
begin
...
DisablePopuMenu;
end
...
end
end;
p.s. Функцию, отменяющую это запрещение я надеюсь написать не составит труда :)
Удачи.