Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Потрепаться";
Текущий архив: 2003.06.12;
Скачать: [xml.tar.bz2];

Вниз

Перехват сообщений.   Найти похожие ветки 

 
Style   (2003-05-27 10:20) [0]

Вот придумал как можно сообщения у Controlов перехватывать не кто так не делал? Помоему красиво :)

type
TForm1 = class(TForm)
Memo1: TMemo;
Memo2: TMemo;
procedure FormCreate(Sender: TObject);
private
ControlProc: TWndMethod;
procedure OnWindowProc(var Message: TMessage);

{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.FormCreate(Sender: TObject);
begin
ControlProc := memo1.WindowProc;
memo1.WindowProc := OnWindowProc;

end;

procedure TForm1.OnWindowProc(var Message: TMessage);
begin
if(Message.Msg = WM_VSCROLL) then
begin
Memo2.Perform(Message.Msg,Message.wParam,Message.lParam);
end;

ControlProc(Message);
end;


 
Жук   (2003-05-27 10:38) [1]

Красиво. Но хотелось бы услышать мастеров...


 
Юрий Зотов   (2003-05-27 11:00) [2]

Из справки по TControl.WindowProc:

"Use the WindowProc property to temporarily replace or subclass the window procedure of the control. Component writers that are customizing the window procedure for a descendant class should override the WndProc method instead.

Before assigning a new value to WindowProc, store the original value. WindowProc is initially set to the WndProc method, so if the value has not been changed since then, the original value need not be stored. Within the procedure that is used as the new value for WindowProc, pass any unhandled messages to the original procedure that was the value of WindowProc. After completing any specialized message handling, restore the value of WindowProc to the original procedure".

Согласитесь, что после этого слово "придумал" звучит как-то не вполне уместно - придумали этот способ все же разработчики VCL. Поэтому точнее было бы сказать не "придумал", а "использовал свойство, специально для того и предназначенное". Причем использовал точно так, как это рекомендовано в документации.


 
Style   (2003-05-27 11:28) [3]

Юрий Зотов>>
:))) >> ну в общем я хелп не вчитывался.. Можно сказать для себя я придумал.. Честно говоря я бы и не понял сразу по хелпу что так можно делать. Вот если бы они пример показали я бы и не кидал сюды САБЖ..
В любом случае спасибо за критику ;)


А если взять такое это тоже я придумал в хелпе тогда тоже ничего не нашел:

Мне нужно было перехватить события динамически созданных объектов. Причем если событие TNotifyEvent; то замена события делается легко. Но если это к примеру TMouseMoveEvent то при присвоении этому событию своей процедуры Delphi выдает ошибку.. Я обошел ее так Если FTree создан динамически

TreeMouseMove := TreeMouseMoveProc;
FTree.OnMouseMove := TreeMouseMove;

type

Создал еще одно Property TreeMouseMove и процедуру

TGridTreeView = class(TCustomPanel)
private
FTreeMouseMove: TMouseMoveEvent;

procedure TreeMouseMoveProc(Sender: TObject; Shift: TShiftState; X, Y: Integer);

protected

property TreeMouseMove: TMouseMoveEvent read FTreeMouseMove write FTreeMouseMove;

public

end;

Можно считать что это я придумал или я тут тоже не прав??? :)



 
han_malign   (2003-05-27 11:29) [4]

Причем перекрыть WndProc будет намного симпатичнее...


 
Style   (2003-05-27 11:36) [5]

>>Причем перекрыть WndProc будет намного симпатичнее...

А это зачем?



 
Style   (2003-05-27 11:51) [6]

Юрий Зотов>> Блин сколько help не смотрел пример не видел, а сейчас нашел даже пример подобный :( че так я совсем с этим придумал быкнул..

procedure TMyListBoxDescendant.SubClassWndProc(var Message: TMessage);

begin
if Message.Msg = WM_STYLEMESSAGE then
Style := TListBoxStyle(Message.WParam)
else
WndProc(Message);

end;

procedure TMyListBoxDescendant.ToggleSubClass(On: Boolean);

begin
if On then
WindowProc := SubClassWndProc;
else
WindowProc := WndProc;

end;

procedure TForm1.SubClassRadioGroup1Click(Sender: TObject);

begin
MyListBoxDescendant1.ToggleSubClass(SubClassRadioGroup1.ItemIndex = 0);
end;



 
DiamondShark   (2003-05-27 12:09) [7]


> Style © (27.05.03 11:51)


Не расстраивайся! Главное -- сам дошёл.


 
handra   (2003-05-27 12:22) [8]

procedure TForm1.OnWindowProc(var Message: TMessage);
begin
if(Message.Msg = WM_VSCROLL) then
begin
Memo2.Perform( Message.Msg,Message.wParam,Message.lParam);
end;


Вызовет бесконечный цикл - Perfrom есть вызов WindowProc


 
Style   (2003-05-27 12:27) [9]

handra-> Невызовет так как Perform от Memo2


 
Юрий Зотов   (2003-05-27 13:42) [10]

> Style © (27.05.03 11:28)

А вот то, что САМ дошел - вот это действительно ценно. Можно сказать, почти и правда придумал. Да, придумал велосипед, но придумал САМ.

Знания постепенно накапливаются и по мере их накопления необходимость в "изобретении" чего-либо возникает все реже - но это не снижает ценности и важности такого качества, как СПОСОБНОСТЬ "изобретать". Птому что в программировании (особенно, при проектировании) "изобретать" все же приходится.


 
Style   (2003-05-27 13:44) [11]

Юрий Зотов © >>

Спасибо... А как на счет перехвата событий динамически созданных компонентов..? Там можно было по другому.. Вы же смотрели мой компонент TGridTreeView???


 
Юрий Зотов   (2003-05-27 15:08) [12]

> Style © (27.05.03 13:44)

Ну, TGridTreeView я смотрел уже давно, поэтому деталей не помню. Помню только, что там как раз не гарантировалось восстановление WindowProc.

Вообще, с компонентами этот вопрос намного сложнее. Положим, я написал компонент, который в конструкторе подменяет чье-то чужое WindowProc, а в деструкторе его восстанавливает. Все работает прекрасно... но только до поры до времени. Кладем на форму два таких компонента, а затем первый удаляем. Вот и все, приплыли. И чтобы избежать таких глюков придется строить что-то типа "стека" запомненных значений WindowProc (но с возможностью удаления любого элемента, а не только последнего).

Казалось бы, в компоненте такой способ вполне приемлем либо когда построен такой "стек", либо когда подобный компонент гарантированно будет единственным. Но это только "казалось бы". Представьте, что юзер использует чьи-то еще компоненты - значит, нет никакой уверенности в том, что в них не использован этот же механизм. И тогда неизбежно получаем тот же самый глюк.

Поэтому в компонентах такие приемы, строго говоря, недопустимы. Обратите внимание на то, что сказано в хелпе:
Component writers that are customizing the window procedure for a descendant class should override the WndProc method instead ".

Это значит, что, если в каком-либо компоненте Вам нужна нестандартная обработка сообщений, то надо писать потомок ЭТОГО компонента, а не подменять его WindowProc СНАРУЖИ, из другого компонента.

Есть и другие способы подмены оконной процедуры (SetWindowLong, MakeObjectInstance). Все они несколько различаются тем, какая именно процедура подменяется (VCL"евская или системная), но при любом способе подмены надо гарантировать, что все будет корректно работать и корректно восстанавливаться. В частности, что никакой сторонний компонент вмешаться в эту цепочку никак не сможет.


 
Style   (2003-05-27 15:18) [13]

2 Ю.З.
Я там и не использовал замену WndProc..

Я просто на Create создавал Динамический Грид и Дерево.. причем грид мне нужен был только из-за его ColumnTitlов... Сам же грид рисовался на Дереве по событию OnCustomDraw;

Поэтому я там перехватывал события вышеуказанным способом..

Сам компонент теперь лежит в Кладовке..


 
Юрий Зотов   (2003-05-27 15:26) [14]

> Style © (27.05.03 15:18)

Дык... а какая разница, что конкретно подменяется - WndProc или другой метод? В общем - никакой, все остается в силе. Плюс, если речь идет о подмене доступного юзеру события, то все становится еще сложнее.


 
Style   (2003-05-27 15:32) [15]

Юрий Зотов..>>

Но я проблеммы там не увидел в подмене.. Т.е. я могу создать хоть десять таких компонентов и все работает!

И первый я и второй и третий удалял и т.д.


 
handra   (2003-05-27 15:34) [16]

Style © (27.05.03 12:27)
handra-> Невызовет так как Perform от Memo2

ups, пропустил... 8(


 
Style   (2003-05-27 15:44) [17]

Юрий Зотов>> Странно все работает... :) Можеть я чего не понимаю. ???


 
Юрий Зотов   (2003-05-27 16:06) [18]

Так. Старая версия компонента была написана некорректно, это совершенно точно. Что и как Вы подменяете в новой версии - не знаю, не видел. Если событие, недоступное юзеру - то все нормально, а если доступное - возможны глюки. Это тоже точно.


 
Style   (2003-05-27 16:12) [19]

Посмотрю в любом случае Спасибо :)



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

Форум: "Потрепаться";
Текущий архив: 2003.06.12;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.5 MB
Время: 0.007 c
14-35002
Belkova
2003-05-24 21:40
2003.06.12
Инсталятор


14-35034
Vlad Oshin
2003-05-27 12:12
2003.06.12
А не сделать ли на сайте тест, подобно brainbench у?


6-34962
han
2003-04-07 21:18
2003.06.12
UDP


1-34854
Екатерина
2003-05-29 12:58
2003.06.12
Утечка памяти


3-34720
Rafik
2003-05-23 14:01
2003.06.12
Не соедениться с MSSQL





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский