Конференция "Компоненты" » Создание компонента. MDI приложение.
 
  • Decoding (28.07.08 10:35) [40]
    Не смотря на то, что третий вопрос я решил через перехват сообщения WM_MDIREFRESHMENU, этот вариант меня не очень устраивает.

    я набросал небольной демонстрационный пример, в котором есть компонент и приложение, которое его использует. скачать можно тут:
    http://slil.ru/26014035
    http://webfile.ru/2119137
    Компонент ставит хук, и имеет процедуру procedure TextChanged(var Message: TMessage); message CM_TEXTCHANGED;. Но ни тот ни другой метод это сообщение не отлавливают.

    В примере - в заголовке MDIChild формы с определенной переодичностью меняестя текст заголовка. Именно это событие и должен перехватить компонент.

    Если не сложно, посмотрите компонент, и подскажите, что не так сделано?
  • DimaBr © (28.07.08 12:44) [41]
    Вот откуда прилетает 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;

  • DimaBr © (28.07.08 12:46) [42]
    А хук вы вешаете на главное окно (точнее на окно где лежит TDemoPanel)
  • Decoding (28.07.08 13:17) [43]
    Да это понятно, видел я это... Оно мне не совсем подходит, т.к. lParam и wParam нулевые, и я не знаю у какого именно окна произошли изменения. Приходится делать цикл, и пробегаться по всем окнам, проверяя, в каком именно изменился Caption. Это неэффективно при большом количестве окон, особенно если Caption при этом меняется только у одного... Вот почему мне нужно перехватывать именно CM_TEXTCHANGED или WM_SETTEXT. Но до MDI формы они не доходят (проверял через Spy++). Можно ли это как то обойти (может есть другое сообщение), чтобы отказаться от цикла? Чтобы сразу знать, у какого именно дочернего MDI окна произошло изменение...

    Да и вообще странно, что эти сообщения не доходят (с MDI окнами вообще много странностей, как выяснилось во время работы над компонентом...), на фоне например того, что сообщение WM_SETICON приходит (и перехватывается) нормально...
  • Decoding (28.07.08 13:21) [44]

    > А хук вы вешаете на главное окно (точнее на окно где лежит
    > TDemoPanel)

    WndProcHook := SetWindowsHookEx( WH_CALLWNDPROC, @CallWndHook, 0, GetCurrentThreadID );
    хук вроде бы вешается на весь поток, а не на конкретное окно... и опять же повторюсь, проверял какие сообщения получает и главное окно, и то, на котором лежит панель, при помощи утилитки Spy++. Не приходят сообщения CM_TEXTCHANGED и WM_SETTEXT приложению...
  • DimaBr © (28.07.08 13:24) [45]
    Полная чушь !
    Поставьте BreakPoint в
    procedure TCustomForm.CMTextChanged(var Message: TMessage);


    В WitchList введите Name и увидите что изменение текста происходит в Form2, которая и является MDIChild
  • Decoding (28.07.08 13:33) [46]
    И что мне от этого факта? До хука это сообщение не доходит... А WM_MDIREFRESHMENU приходит без параметров... Вопрос не в том, что в TCustomForm это срабатывает нормально, а в том, как мне эти сообщения получить...
  • DimaBr © (28.07.08 15:10) [47]
    Вы хотите перехватить в компоенете изменения в другом окне ?
  • Decoding (28.07.08 15:38) [48]
    Именно так. Если уточнить задачу, то: перехватывать компонентом изменение Caption в MDIChild форме.
  • DimaBr © (29.07.08 08:39) [49]
    Ваша задача решается просто. Пишется наследник от TForm, в котором реализуются все ваши примбабасы, от которого в последствии и наследуются все MDIChild формы приложения. И не нужно засорять программу хуками.
  • Decoding (31.07.08 22:53) [50]
    Еще вопросик возник. Как в момент создания компонента (runtime) определить, был ли он брошен на форму как компонент, или создается динамически? Дело в том, что часть важного для работы компонента кода находится в процедуре Loaded. А она не отрабатывает при динамическом создании компонента... Не предлагайте перенести код из Loaded в Create. Если знаете, как определить, каким образом создается компонент, подскажите.
  • DimaBr © (01.08.08 10:31) [51]
    Никак, когда компонент создаётся он ещё никуда не брошен.
    Loaded возникает после окончания чтения из ресурса, так что при первой заброске никакого Loaded нет, поскольку читать нечего.
    Design-Time от Run-Time можно отлечить проверив свойство ComponentState
    if csDesigning in ComponentState then

  • Игорь Шевченко © (04.08.08 17:48) [52]

    > Как в момент создания компонента (runtime) определить, был
    > ли он брошен на форму как компонент, или создается динамически?
    >  


    Срабатывает Loaded или нет
  • DimaBr © (05.08.08 08:41) [53]
    Многоуважаемый Игорь, у компонента брошеного на форму тоже не срабатывает Loaded (в момент заброски).
  • Игорь Шевченко © (05.08.08 10:23) [54]
    DimaBr ©   (05.08.08 08:41) [53]

    Насколько я понял автора, ему нужно определить (в компоненте) загружен ли он из ресурсов или создан в коде. Причем, определить ему надо в run-time, а не в desing-time. Насколько мне известно, это определяется срабатыванием метода TComponent.Loaded

    Во время работы в design-time этот вопрос попросту не имеет смысла - так как компонент может быть только "брошен на форму" но никак не создан. Если только в каком-то хитром эксперте компонент будет создан, как побочное действие, но это уже настолько отдает странным, что мне с трудом представляется, что автор имеет в виду эту ситуацию.

    По сабжу - определять, каким путем заполнены свойства компонента есть нонсенс и ламерство.
  • Decoding (18.09.08 12:03) [55]
    По поводу ламерства можно было бы и воздержаться. Меня не интересовало, каким образом заполняются свойства компонента, меня интересовало каким образом компонент создавался.

    Однако это уже в прошлом, компонент уже написан. Все, кому интересно, могут скачать его и протестировать.
    exe - http://decoding.narod.ru/download/mycomponent/mdipanel_exe.zip
    source - http://decoding.narod.ru/download/mycomponent/mdipanel.zip

    Также мне было бы интересно узнать ваше мнение об этом компоненте. Можете писать здесь, или мне на почту (адрес смотрите на сайте).
  • Игорь Шевченко © (18.09.08 23:32) [56]

    > Также мне было бы интересно узнать ваше мнение об этом компоненте


    Слишком сложно и непонятно. Собственно, непонятны цели и задачи, каковые должен решать этот компонент - если аналог таскбара для окон MDI то есть масса готовых решений (даже я когда-то пример делал), но оно без хуков как-то работало.
  • Decoding (19.09.08 09:47) [57]
    Ну вот пример. У нас открыта MDIChild форма, на ней есть мемо, которое имеет фокус. При этом, когда форма окажется свернутой, нужно подавлять ввод с клавиатуры (чтобы м мемо ничего не печаталось, что логично при свернутой форме). Каким образом реализовать это без хуков?

    Цели и задачи. Сделать работу с компонентом как можно более прозрачной для разработчика. Я встречал подобные компоненты, и там например разработчик должен был сам позаботиться о создании кнопки на панели, при создании формы. В этом нет ничего плохого, от одной лишней строки никому плохо не будет. тем не менее меня такой подход не устроил, и я, в своем компоненте избавил разработчика от этого (на мой взгляд ненужного) действия.

    это только один из примеров, но думаю он достаточно наглядный.
  • Игорь Шевченко © (22.09.08 16:35) [58]
    "У нас открыта MDIChild форма, на ней есть мемо, которое имеет фокус. При этом, когда форма окажется свернутой, нужно подавлять ввод с клавиатуры (чтобы м мемо ничего не печаталось, что логично при свернутой форме). Каким образом реализовать это без хуков?
    "

    Поведение ввода в компоненты на свернутой форме определяет система, как она позволяет (вводить или нет), так оно и должно быть и вмешиваться в ее работу - это только изумлять пользователя.

    Насколько я видел исходники этого компонента, я не увидел подмены ClientWindowProc у главной MDI-формы, а через эту подмену можно многие вещи реализовать довольно просто.
    Это в качестве подсказки.
  • Decoding (22.09.08 23:57) [59]
    > Это в качестве подсказки

    Спасибо. Будет свободное время, проработаю и этот вариант.

    >Поведение ввода в компоненты на свернутой форме определяет система, как она позволяет (вводить или нет), так оно и должно быть и вмешиваться в ее работу - это только изумлять пользователя.

    Утверждение отнюдь не лишено смысла. Однако в каждом правиле бывают исключения. Если провести аналогию, то врятли вы адекватно отреагируете на то, что минимизированный блокнот продолжает реагировать на ввод с клавиатуры. И врятли вы обрадуетесь, развернув блокнот, увидев там "левый" текст. Не вижу причин, по которым в MDI должно быть по-другому. Спорить на эту тему можно долго... И каждое мнение имеет право на существование... Я посчитал, что так будет правильнее...
 
Конференция "Компоненты" » Создание компонента. MDI приложение.
Есть новые Нет новых   [134464   +62][b:0][p:0.001]