Отправляет email-рассылки с помощью сервиса Sendsay

Программирование. Форум !!!

Перехват MessageBox-сообщений

Здравствуйте, коллеги.

Хочу написать свой компонент, что бы перехватывать все диалоговые
сообщения функций MessageBox, ShowMessage и другие, и вместо
стандартных этих окон рисовать свои.
Кто-нибудь может подсказать, как можно перехватить такие функции и
выполнить свои действия ?

Ответить   Feniks Fri, 13 May 2005 12:29:49 +0300 (#366968)

 

Ответы:

Здравствуйте !


Перехват API, однако (если надо сделать на уровневсей системы).
Где то встречал примеры именно для перезвата MessageBox.
На RSDN были, кажется, статьи:
http://rsdn.ru/?summary/1383.xml

На codeguru также:
перехват API:
http://codeguru.com/Cpp/W-P/system/misc/article.php/c5667/
использование хука для того, чтобы поймать окно бокса
и расположить его относительно родителя по центру:
http://codeguru.com/Cpp/W-P/win32/messagebox/article.php/c4541/

Вообще это дело неблагодарное, т.к. API кроме всего прочего призвано
создавать некоторый уровень абстракции для разработчика.
В MSDN, например MessageBox описывается так:

The MessageBox function creates, displays, and operates a message box.
The message box contains an application-defined message and title,
plus any combination of predefined icons and push buttons.

И ничего не сказано про то, какого цвета, размера, формы этот самый бокс
будет. Меняется версия ОС, меняется вид пользовательского интерфейса.
А интерфейс программный остается неизменным. Старые приложения работают
как надо. Разработчики могут не боясь использовать старые методы.

Кстати, некоторые приложения сами "кустомизируют" свои окна сообщений
(та же опера). Возможно, она не использует ::MessageBox.
И еще. Как будешь поступать со скинами XP ? Не учитывать скин ?

--
С уважением, Вахтуров Виктор.

Номер выпуска : 4482
Возраст листа : 601 (дней)
Количество подписчиков : 519
Адрес в архиве : http://subscribe.ru/archive/comp.soft.prog.prog/msg/367704
Получить правила : mailto:comp.soft.prog.prog-rules@subscribe.ru
Формат "дайджест" : mailto:comp.soft.prog.prog-digest@subscribe.ru
Формат "каждое письмо" : mailto:comp.soft.prog.prog-normal@subscribe.ru
Формат "читать с веба" : mailto:comp.soft.prog.prog-webonly@subscribe.ru

Ответить   Sat, 14 May 2005 22:52:50 +0400 (#367704)

 

Здравствуйте, Victor.

В письме mid:20050514225219.3677***@c*****.subscribe
Вы писали 14 мая 2005 г. в 21:52:50 [GMT +2:00]:








За ссылки большое спасибо.
Обязательно их посмотрю. :))
Пример перехвата MessageBox я тоже где-то видел...

Мне нужна нарисовать свое окно с контролами. И оно не будет зависеть
от темы и скинов Винды. Мне это не надо да и не важно...
Я делаю аналог окон Балонов, на подобие тех, которые показывает Агент
(Помощник) в Офисе.

Ответить   Feniks Mon, 16 May 2005 11:30:35 +0300 (#368292)

 

Здравствуйте !


Так может, тогда обычным тултипом и воспользоваться ?
Задать ему регион, расположить на нем контролы.
Можно, конечно, и свое такое сделать.

--
С уважением, Вахтуров Виктор.

Номер выпуска : 4493
Возраст листа : 603 (дней)
Количество подписчиков : 518
Адрес в архиве : http://subscribe.ru/archive/comp.soft.prog.prog/msg/368589
Получить правила : mailto:comp.soft.prog.prog-rules@subscribe.ru
Формат "дайджест" : mailto:comp.soft.prog.prog-digest@subscribe.ru
Формат "каждое письмо" : mailto:comp.soft.prog.prog-normal@subscribe.ru
Формат "читать с веба" : mailto:comp.soft.prog.prog-webonly@subscribe.ru

Ответить   Mon, 16 May 2005 20:58:49 +0400 (#368589)

 

Здравствуйте, Victor.

В письме mid:20050516210408.3685***@c*****.subscribe
Вы писали 16 мая 2005 г. в 19:58:49 [GMT +2:00]:


Я все-таки нашел, как перехватывать API функции.
Если кому интересно, ниже код для перехвата MessageBoxA.
В примере берется Блокнот для перехвата, он он почему у меня отказался
работать. Но если вместо Блокнота использовать другую прогу, то все
ОК. Одно только "но", здесь перехватывается вся функция, т.е. вместо
вызова MessageBoxA можно подставить любую другую свою функцию.
А мне бы еще как-то узнать передаваемые параметра в MessageBoxA и их
потом юзать. Может кто-нибудь знает как это делается ?

library MyMessageBoxDLL;

uses
SysUtils, Windows, Messages, Classes;

{$R *.RES}
type
TImageImportDescriptor=packed record
OriginalFirstThunk : DWORD;
TimeDateStamp : DWORD;
ForwarderChain : DWORD;
Name : DWORD;
FirstThunk : DWORD;
end;
PImageImportDescriptor=^TImageImportDescriptor;

PPointer = ^Pointer;

var filename:array[0..max_path-1] of char;
hook:HHook=0;
PEHeader:PImageNtHeaders;
ImageBase:cardinal;

function MyHookProcedure(hWnd: HWND; lpText, lpCaption: PWideChar; uType: UINT):
Integer;
stdcall;
begin
result:=MessageBoxA(0, 'Notepad', 'my hook', 0);
//Но уже через нашу табл. импорта
end;

procedure ProcessImports(PImports:PImageImportDescriptor);
Var
PImport:PImageImportDescriptor;
PRVA_Import:LPDWORD;
ProcAddress:pointer;
Temp_Cardinal:cardinal;

begin{1}
ProcAddress:=GetProcAddress(GetModuleHandle('USER32.DLL'), 'MessageBoxA');
PImport:=PImports;
while PImport.Name<>0 do
begin{2}
PRVA_Import:=LPDWORD(pImport.FirstThunk+ImageBase);
while PRVA_Import^<>0 do
begin{3}
if PPointer(PRVA_Import)^=ProcAddress
then
begin{4}
VirtualProtect(PPointer(PRVA_Import),4,PAGE_READWRITE,Temp_Cardinal);
PPointer(PRVA_Import)^:=@MyHookProcedure; //пишем свою...
VirtualProtect(PPointer(PRVA_Import),4,Temp_Cardinal,Temp_Cardinal);
end;{1}
Inc(PRVA_Import);
end;{2}
Inc(PImport);
end;{3}
end;{4}

procedure DllEntryPoint(reson:longint);stdcall;
begin
case reson of
DLL_PROCESS_ATTACH:
begin
DisableThreadLibraryCalls(hInstance);
ZeroMemory(@FileName, SizeOf(FileName));
GetModuleFileName(GetModuleHandle(nil), @FileName, SizeOf(FileName));
if Pos('MSAGENT.EXE',AnsiUpper(FileName))<>0 then //сейчас я хочу попробовать
все это дело надо нотепадом
begin
ImageBase:=GetModuleHandle(nil);
PEHeader:=pointer(int64(ImageBase)+PImageDosHeader(ImageBase)._lfanew);//pe
header
ProcessImports(pointer(PEHeader.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress+ImageBase));
end;
end;
end;
end;

function nexthook(code:integer;wParam,lParam:longint):longint;stdcall;
begin
result:=callnexthookex(hook,code,wParam,lParam);
end;

procedure sethook(flag:bool);export; stdcall;
begin
if flag then
hook:=setwindowshookex(wh_getmessage,@nexthook,hInstance,0)
else
begin
unhookwindowshookex(hook);
hook:=0;
end;
end;

exports sethook;

begin
DLLProc:=@DllEntryPoint;
DllEntryPoint(DLL_PROCESS_ATTACH);
end.

Вызов хука из проекта:

var
sethook:procedure(flag:bool)stdcall;
hDll:hModule;

begin
hDll:=LoadLibrary('MyMessageBoxDLL.dll');
@sethook:=GetProcAddress(hDll, 'sethook');
sethook(true);
messagebox(0,'Не закрывай, пока идет работа','MyMessageBox Test',0);
sethook(false);
FreeLibrary(hDll);
end;

Ответить   Feniks Tue, 17 May 2005 11:17:00 +0300 (#368909)

 

Хаю ду ю ду Feniks?

Смотрю и вижу, как ты печатаешь умные вещи и дай-ка, думаю,
тоже что-нибудь напечатаю:

Ибо MessageBoxW (скорее всего)

Ответить   Wed, 18 May 2005 01:28:05 +0500 (#369348)

 

Здравствуйте Feniks,

Вы писали Tuesday, May 17, 2005, 2:17:00 PM:

Точно не помню, но, кажется в 75 выпуске "Хакера" что-то про перехват
и инжектирование сказано...

Ответить   [Алексей] Sat, 21 May 2005 00:05:12 +0600 (#371152)

 

Приветствую!

темы и скинов Винды. Мне это не надо да и не важно... Я >делаю аналог
окон Балонов, на подобие тех, которые показывает Агент


А зачем вообще перехватывать сообщения? Не проще ли:
1) переопределить AfxMessageBox, задав новую функцию, например,
MyMessageBox - и вызывать именно ее?
2) ловить и обрабатывать исключения, выдавая опять-таки сообщения через
MyMessageBox?

С уважением, Ольга.

Номер выпуска : 4499
Возраст листа : 604 (дней)
Количество подписчиков : 517
Адрес в архиве : http://subscribe.ru/archive/comp.soft.prog.prog/msg/369258
Получить правила : mailto:comp.soft.prog.prog-rules@subscribe.ru
Формат "дайджест" : mailto:comp.soft.prog.prog-digest@subscribe.ru
Формат "каждое письмо" : mailto:comp.soft.prog.prog-normal@subscribe.ru
Формат "читать с веба" : mailto:comp.soft.prog.prog-webonly@subscribe.ru

Ответить   Tue, 17 May 2005 11:16:39 +0400 (#369258)

 

Хаю ду ю ду Feniks?

Смотрю и вижу, как ты печатаешь умные вещи и дай-ка, думаю,
тоже что-нибудь напечатаю:

Короче я из этого понял только одно:

1) Создаешь unit с таким содержимым:
unit Unit2;

interface

uses Windows;

function MessageBox(hWnd: HWND; lpText, lpCaption: PChar; uType: UINT): Integer;
stdcall;
procedure ShowMessage(const Msg: string);

implementation

function MessageBox(hWnd: HWND; lpText, lpCaption: PChar; uType: UINT): Integer;
stdcall;
begin
// код типа
end;

procedure ShowMessage(const Msg: string);
begin
// типа код
end;

end.

2) Добавляешь в код формы
uses ..... Unit2;

PS: Больше ничего в голову не пришло после прочтения словосочетания

Ответить   Wed, 18 May 2005 01:06:27 +0500 (#369346)