-
Не смотря на то, что третий вопрос я решил через перехват сообщения WM_MDIREFRESHMENU, этот вариант меня не очень устраивает. я набросал небольной демонстрационный пример, в котором есть компонент и приложение, которое его использует. скачать можно тут: http://slil.ru/26014035http://webfile.ru/2119137Компонент ставит хук, и имеет процедуру procedure TextChanged(var Message: TMessage); message CM_TEXTCHANGED;. Но ни тот ни другой метод это сообщение не отлавливают. В примере - в заголовке MDIChild формы с определенной переодичностью меняестя текст заголовка. Именно это событие и должен перехватить компонент. Если не сложно, посмотрите компонент, и подскажите, что не так сделано?
-
Вот откуда прилетает WM_MDIREFRESHMENU
procedure TCustomForm.CMTextChanged(var Message: TMessage);
begin
inherited;
if (FormStyle = fsMDIChild) and (Application.MainForm <> nil) and
(Application.MainForm.ClientHandle <> 0) then
SendMessage(Application.MainForm.ClientHandle, WM_MDIREFRESHMENU, 0, 0);
end;
-
А хук вы вешаете на главное окно (точнее на окно где лежит TDemoPanel)
-
Да это понятно, видел я это... Оно мне не совсем подходит, т.к. lParam и wParam нулевые, и я не знаю у какого именно окна произошли изменения. Приходится делать цикл, и пробегаться по всем окнам, проверяя, в каком именно изменился Caption. Это неэффективно при большом количестве окон, особенно если Caption при этом меняется только у одного... Вот почему мне нужно перехватывать именно CM_TEXTCHANGED или WM_SETTEXT. Но до MDI формы они не доходят (проверял через Spy++). Можно ли это как то обойти (может есть другое сообщение), чтобы отказаться от цикла? Чтобы сразу знать, у какого именно дочернего MDI окна произошло изменение...
Да и вообще странно, что эти сообщения не доходят (с MDI окнами вообще много странностей, как выяснилось во время работы над компонентом...), на фоне например того, что сообщение WM_SETICON приходит (и перехватывается) нормально...
-
> А хук вы вешаете на главное окно (точнее на окно где лежит > TDemoPanel)
WndProcHook := SetWindowsHookEx( WH_CALLWNDPROC, @CallWndHook, 0, GetCurrentThreadID ); хук вроде бы вешается на весь поток, а не на конкретное окно... и опять же повторюсь, проверял какие сообщения получает и главное окно, и то, на котором лежит панель, при помощи утилитки Spy++. Не приходят сообщения CM_TEXTCHANGED и WM_SETTEXT приложению...
-
Полная чушь ! Поставьте BreakPoint в procedure TCustomForm.CMTextChanged(var Message: TMessage); В WitchList введите Name и увидите что изменение текста происходит в Form2, которая и является MDIChild
-
И что мне от этого факта? До хука это сообщение не доходит... А WM_MDIREFRESHMENU приходит без параметров... Вопрос не в том, что в TCustomForm это срабатывает нормально, а в том, как мне эти сообщения получить...
-
Вы хотите перехватить в компоенете изменения в другом окне ?
-
Именно так. Если уточнить задачу, то: перехватывать компонентом изменение Caption в MDIChild форме.
-
Ваша задача решается просто. Пишется наследник от TForm, в котором реализуются все ваши примбабасы, от которого в последствии и наследуются все MDIChild формы приложения. И не нужно засорять программу хуками.
-
Еще вопросик возник. Как в момент создания компонента (runtime) определить, был ли он брошен на форму как компонент, или создается динамически? Дело в том, что часть важного для работы компонента кода находится в процедуре Loaded. А она не отрабатывает при динамическом создании компонента... Не предлагайте перенести код из Loaded в Create. Если знаете, как определить, каким образом создается компонент, подскажите.
-
Никак, когда компонент создаётся он ещё никуда не брошен. Loaded возникает после окончания чтения из ресурса, так что при первой заброске никакого Loaded нет, поскольку читать нечего. Design-Time от Run-Time можно отлечить проверив свойство ComponentState if csDesigning in ComponentState then
-
> Как в момент создания компонента (runtime) определить, был > ли он брошен на форму как компонент, или создается динамически? >
Срабатывает Loaded или нет
-
Многоуважаемый Игорь, у компонента брошеного на форму тоже не срабатывает Loaded (в момент заброски).
-
DimaBr © (05.08.08 08:41) [53]
Насколько я понял автора, ему нужно определить (в компоненте) загружен ли он из ресурсов или создан в коде. Причем, определить ему надо в run-time, а не в desing-time. Насколько мне известно, это определяется срабатыванием метода TComponent.Loaded
Во время работы в design-time этот вопрос попросту не имеет смысла - так как компонент может быть только "брошен на форму" но никак не создан. Если только в каком-то хитром эксперте компонент будет создан, как побочное действие, но это уже настолько отдает странным, что мне с трудом представляется, что автор имеет в виду эту ситуацию.
По сабжу - определять, каким путем заполнены свойства компонента есть нонсенс и ламерство.
-
-
> Также мне было бы интересно узнать ваше мнение об этом компоненте
Слишком сложно и непонятно. Собственно, непонятны цели и задачи, каковые должен решать этот компонент - если аналог таскбара для окон MDI то есть масса готовых решений (даже я когда-то пример делал), но оно без хуков как-то работало.
-
Ну вот пример. У нас открыта MDIChild форма, на ней есть мемо, которое имеет фокус. При этом, когда форма окажется свернутой, нужно подавлять ввод с клавиатуры (чтобы м мемо ничего не печаталось, что логично при свернутой форме). Каким образом реализовать это без хуков?
Цели и задачи. Сделать работу с компонентом как можно более прозрачной для разработчика. Я встречал подобные компоненты, и там например разработчик должен был сам позаботиться о создании кнопки на панели, при создании формы. В этом нет ничего плохого, от одной лишней строки никому плохо не будет. тем не менее меня такой подход не устроил, и я, в своем компоненте избавил разработчика от этого (на мой взгляд ненужного) действия.
это только один из примеров, но думаю он достаточно наглядный.
-
"У нас открыта MDIChild форма, на ней есть мемо, которое имеет фокус. При этом, когда форма окажется свернутой, нужно подавлять ввод с клавиатуры (чтобы м мемо ничего не печаталось, что логично при свернутой форме). Каким образом реализовать это без хуков? "
Поведение ввода в компоненты на свернутой форме определяет система, как она позволяет (вводить или нет), так оно и должно быть и вмешиваться в ее работу - это только изумлять пользователя.
Насколько я видел исходники этого компонента, я не увидел подмены ClientWindowProc у главной MDI-формы, а через эту подмену можно многие вещи реализовать довольно просто. Это в качестве подсказки.
-
> Это в качестве подсказки
Спасибо. Будет свободное время, проработаю и этот вариант.
>Поведение ввода в компоненты на свернутой форме определяет система, как она позволяет (вводить или нет), так оно и должно быть и вмешиваться в ее работу - это только изумлять пользователя.
Утверждение отнюдь не лишено смысла. Однако в каждом правиле бывают исключения. Если провести аналогию, то врятли вы адекватно отреагируете на то, что минимизированный блокнот продолжает реагировать на ввод с клавиатуры. И врятли вы обрадуетесь, развернув блокнот, увидев там "левый" текст. Не вижу причин, по которым в MDI должно быть по-другому. Спорить на эту тему можно долго... И каждое мнение имеет право на существование... Я посчитал, что так будет правильнее...
|