Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2003.07.17;
Скачать: CL | DM;

Вниз

Баг VCL?   Найти похожие ветки 

 
Толик   (2003-07-04 13:50) [0]

Уважаемые мастера!
Столкнулся со следующей проблемой. Необходимо управлять объектом Application посредством отсылки ему неких своих сообщений, типа WM_USER + XXX. Поскольку объект Application ничего не знает о подобных сообщениях, то, в качестве возможного решения, необходимо подменить его оконную процедуру. Например:
(1)

var
DefProc: longword;
const
MM_MYMESSAGE = WM_USER + 1;
procedure MyWndProc(Handle: hWnd; Msg: longword; WParam, LParam: longint); stdcall;

procedure TForm1.Button1Click(Sender: TObject);
begin
//запоминаем старый обработчик
DefProc := GetWindowLong(Application.Handle, GWL_WNDPROC);
//подсовываем новый
SetWindowLong(Application.Handle, GWL_WNDPROC, longword(@MyWndProc));
end;

procedure MyWndProc(Handle: hWnd; Msg: longword; WParam, LParam: longint); stdcall;
begin
case Msg of
MM_MYMESSAGE: //моё сообщение, обрабатываем его
ShowMessage("my message");
else
//другие сообщения обрабатываем по умолчанию
Windows.CallWindowProc(pointer(DefProc), Handle, Msg, WParam, LParam);
end;
end;

Здесь всё работает замечательно. НО! Зачастую бывает полезно в качестве оконных процедур использовать члены класса. Для этих случаев VCL предоставляет пару функций: MakeObjectInstance и FreeObjectInstance. Вот здесь и начинаются проблемы:
(2)

var
DefProc: longword;
const
MM_MYMESSAGE = WM_USER + 1;

procedure TForm1.Button1Click(Sender: TObject);
begin
DefProc := GetWindowLong(Application.Handle, GWL_WNDPROC);
SetWindowLong(Application.Handle, GWL_WNDPROC, longword(MakeObjectInstance(NewAppWndProc)));
end;

procedure TForm1.NewAppWndProc(var AMessage: TMessage);
begin
with AMessage do
case Msg of
MM_MYMESSAGE:
ShowMessage("my message");
else
Windows.CallWindowProc(pointer(DefProc), Application.Handle, Msg, WParam, LParam);
end;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
Application.MessageBox("сейчас повисну", "", MB_OK);
end;

Приведённый выше фрагмент кода обрабатывает мои сообщения, но стоит только после подмены оконной процедуры вызвать в главной форме Application.MessageBox(...) или просто минимизировать главную форму, то она тут же перестаёт отвечать на сообщения от мыши или клавиатуры.
М.б. конечно во втором примере у меня где-то ошибка и я зря грешу на MakeObjectInstance? Но похоже не я первый: http://delphiplus.nagano.ru/articles/news/ObjInstFix.html
Хотелось бы узнать мнение экспертов.


 
vuk ©   (2003-07-04 13:57) [1]

А кто мешает использовать HookMainWindow?


 
Толик   (2003-07-04 14:24) [2]

to vuk © (04.07.03 13:57)
Да, это вариант. Но хотелось бы понять в чём причина проблемы, описанной в «Толик (04.07.03 13:50)». Казалось бы, вполне законный код приводит к каким-то непонятным проблемам. Или не вполне законный?
Или в Borland"е специально и ввели в класс TApplication ф-ю HookMainWindow, зная о проблемах с MakeObjectInstance???


 
ggsoft ©   (2003-07-04 15:30) [3]


> Толик (04.07.03 13:50)


> то, в качестве возможного решения, необходимо

не (1) или (2), а, как мне кажется,
компонент <ApplicationEvents> с закладки Additional палитры компонентов. Event-OnMessage().


 
Юрий Зотов ©   (2003-07-04 16:14) [4]

Зачем все это? Есть же событие Application.OnMessage. Просто и надежно.


 
vuk ©   (2003-07-04 16:29) [5]

to Юрий Зотов:
Разница все же есть. OnMessage вызывается из основного цикла обработки, а хуки основного окна - из WndProc.


 
Толик   (2003-07-04 16:54) [6]

Большое спасибо всем откликнувшимся.
Посмотрю, что из всего вышесказанного наиболее полно подойдёт к решению моей задаче.
Ещё раз спасибо и удачи всем.



Страницы: 1 вся ветка

Текущий архив: 2003.07.17;
Скачать: CL | DM;

Наверх




Память: 0.48 MB
Время: 0.012 c
3-55387
SCORPION ZP
2003-06-19 13:14
2003.07.17
Конвертация DBF из DOS в Win


3-55439
V-A-V
2003-06-24 14:12
2003.07.17
Progress для AdoQuery


14-55740
Ajax
2003-07-01 09:22
2003.07.17
НТВ+


14-55760
Vika
2003-07-03 09:36
2003.07.17
DBGrid с возможностью выделения строки, как в Excel


3-55418
AkaSaint
2003-06-21 15:36
2003.07.17
TDataSetProvider.UpdateMode = upWhereKeyOnly не действует