Форум: "Основная";
Текущий архив: 2003.07.17;
Скачать: [xml.tar.bz2];
ВнизБаг 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;
Скачать: [xml.tar.bz2];
Память: 0.46 MB
Время: 0.008 c