Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Запрет всех контекстных меню ;в системе (ловушка) [D7, Win95/98, WinME, NT4, Win2k, WinXP]


Страницы:   1 2

_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. Функцию, отменяющую это запрещение я надеюсь написать не составит труда :)

Удачи.


Страницы:   1 2

Наверх

Титульная страница Поиск, карта сайта Написать письмо