![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Как правильно написать свой компонент? [D7, XP]
Alex_C © (2006-10-18 11:17:00)Суть проблемы: как правильно написать свой компонент, чтобы он наследовал все св-ва своего предшественника и добавлял новые. Вот например - хочу сделать свой компонент TMemo, чтобы добраться до метода Paint.
Делаю так:
TMyMemo = class(TMemo)
private
{ Private declarations }
protected
{ Protected declarations }
procedure WMPaint(var message: TWMPaint); message WM_PAINT;
public
{ Public declarations }
published
{ Published declarations }
end;
Сам WMPaint для примера - просто вывожу строки, пока даже с ними ничего не делаю, в конце вызываю inherited. Вроде все работает, но вот проблема - в отличии он TMemo мой компонент перестает понимать допустим
SendMessage(Memo1.Handle, EM_SCROLL, SB_LINEDOWN, 0); - при этом дочерний TMemo перемещается на последнюю строчку, а мой нет. Выделение мышкой тоже не так работает. Как этого избежать?
Loginov Dmitry (2006-10-20 09:13:00) [1]> Озвучте источник, давно такого бреда не читал
Источник был озвучен выше.
Плохиш (2006-10-19 11:17:00) [2]
> Замечание
> Как правило, перехватчики сообщений для повышения надежности
> работы приложения описываются в блоке protected.
Озвучте источник, давно такого бреда не читал :-)
Alex_C (2006-10-19 11:17:00) [3]Ребята, вы немного увлеклись дискуссией :) , а на мой вопрос то так ответа и нет :(
Ketmar (2006-10-19 11:06:00) [4]>[15] Loginov Dmitry(c) 18-Oct-2006, 19:29
>wm_LButtonDblClk;
расстрелять без права переписки.
>Как правило, перехватчики сообщений для повышения
>надежности работы приложения описываются в блоке protected.
посмертно вывесить для всеобщего обозрения с табличкой "врать некрасиво".
Игорь Шевченко (2006-10-19 10:43:00) [5]
> Как правило, перехватчики сообщений для повышения надежности
> работы приложения описываются в блоке protected.
Пусть лучше занимается своим OpenGL и не лезет в дебри неизведанного. Потому как на надежность место объявления обработчиков сообщений влияет столько же, сколько указание в верхнем или в нижнем регистре писать ключевые слова языка.
Loginov Dmitry (2006-10-18 19:29:00) [6]Игорь Шевченко © (18.10.06 18:20) [13]
Чем аргументируют ? Краснова посмотреть не могу, но цитата была бы желательной.
Пожалуйста:
... Описание класса формы я дополнил разделом protected, в который поместил forward-описание соответствующей процедуры:
procedure MesDblClick (var MyMessage : TWMMouse) ; message wm_LButtonDblClk;
Замечание
Как правило, перехватчики сообщений для повышения надежности работы приложения описываются в блоке protected.
Имя процедуры я задал таким, чтобы не появлялось предупреждение компилятора о том, что я перекрываю соответствующее событие формы. Служебное слово message указывает на то, что процедура будет перехватывать сооб-щение, мнемонику которого указывают за этим словом. Тип аргумента процедуры-перехватчика индивидуален для каждого сообщения. Имя аргумента произвольно, но, конечно, нельзя брать в качестве имени служебное СЛОВО message.
Ketmar (2006-10-18 18:55:00) [7]-- скажи, Ходжа Насреддин, где мусульманину правильней идти во время похорон? впереди гроба, или же позади?
-- главное -- не в самом гробу.
Игорь Шевченко (2006-10-18 18:20:00) [8]Loginov Dmitry © (18.10.06 18:18) [12]
Чем аргументируют ? Краснова посмотреть не могу, но цитата была бы желательной.
Loginov Dmitry (2006-10-18 18:18:00) [9]Я о том, что некоторые авторы делают акцент на том, что процедуры-обработчики сообщений "правильнее" располагать именно в секции protected.
Известный мне пример - Краснов. (OpenGL в Delphi).
Игорь Шевченко (2006-10-18 17:43:00) [10]Loginov Dmitry © (18.10.06 17:36) [10]
> Есть. Причем принципиальная.
И в чем же принцип, если не секрет ? Мне именно принцип интересен, если не затруднит.
> Секция protected задумана для того, чтобы методы, объявленные
> в ней, могли использоваться только в этом же классе или
> в его потомках (ну или в пределах одного модуля).
И чего ?
> - это процедура-обработчик сообщения, которая никогда (по
> крайней мере мне это еще не приходилось видеть) не вызывается
> из потомков (это, имхо, просто бессмысленно).
Процедура-обработчик сообщения не вызывается явно ВООБЩЕ НИОТКУДА. Процедуре-обработчику сообщений ВООБЩЕ ПОФИГ в какой секции быть объявленной, она видна извне отовсюду.
Loginov Dmitry (2006-10-18 17:36:00) [11]Игорь Шевченко © (18.10.06 15:43) [8]
А что, есть принципиальная разница ?
Есть. Причем принципиальная.
Секция protected задумана для того, чтобы методы, объявленные в ней, могли использоваться только в этом же классе или в его потомках (ну или в пределах одного модуля).
procedure WMPaint(var message: TWMPaint); message WM_PAINT;
- это процедура-обработчик сообщения, которая никогда (по крайней мере мне это еще не приходилось видеть) не вызывается из потомков (это, имхо, просто бессмысленно).
Потом. Покажите хоть одно место в VCL, где подобные процедуры объявляются в секции protected.
А если для вас принципиальной разницы нет, то почему вы не объявляете подобные процедуры в секции public (угадал? :))
Сергей М. (2006-10-18 15:44:00) [12]
> inherited вообще можно убрать, он тут не влияет
ты с дуба упал ?)
Игорь Шевченко (2006-10-18 15:43:00) [13]Loginov Dmitry © (18.10.06 15:36) [7]
А что, есть принципиальная разница ?
Loginov Dmitry (2006-10-18 15:36:00) [14]Alex_C © (18.10.06 11:17)
protected
{ Protected declarations }
procedure WMPaint(var message: TWMPaint); message WM_PAINT;
Интересно, кто такому учит - обработчики сообщений пихать в секцию protected? Далеко не первый раз с подобным явлением сталкиваюсь.
Alex_C (2006-10-18 14:33:00) [15]Нет. Не выводит по старинке. Все работает. Вот если его в начале поставить - то да, не выделяется, а в конце - все работает. Да inherited вообще можно убрать, он тут не влияет.
Да не об этом речь - еще раз спрашиваю: почему
SendMessage(Memo1.Handle, EM_SCROLL, SB_LINEDOWN, 0);
не работает? Ведь в самом TMemo он прекрасно работает?
Сергей М. (2006-10-18 14:08:00) [16]
> Т.е. здесь я всего лишь вывожу текст
.. а inherited-метод, будучи вызванный тобой после твоих "хитрых манипуляций" чихает на это (ибо ничего не знает об этом) и выводит текст "по-старинке".
?
Alex_C (2006-10-18 14:00:00) [17]Ок, привожу как у меня реализован WMPaint (выделяет определенные слова красным цветом):
procedure THxMemo.WMPaint(var Message: TWMPaint);
var
i, j, dy, dx: Integer;
PS: TPaintStruct;
DC: HDC;
aCanvas: TCanvas;
str, StrWord: String;
IsKeyWord: Boolean;
BitMap: TBitMap;
begin
DC:= Message.DC;
if DC= 0 then
DC:= BeginPaint(Handle, PS);
aCanvas:=TCanvas.Create;
BitMap := TBitMap.Create;
try
aCanvas.Handle:= DC;
aCanvas.Font:= Font;
BitMap.Height := Height;
BitMap.Width := Width;
BitMap.Canvas.FillRect(ClientRect);
with BitMap.Canvas do
begin
dy := 1;
for i:= 0 to Lines.Count-1 do //Перебираем строки Memo
begin
str:= Lines[i];
StrWord := '';
dx := 1;
j := 1;
While j <= Length(str) do
begin
// Если не пробел и не окончание строки - добавляем в слово
While (str[j] <> ' ') and (j <= Length(str)) do
begin
StrWord := StrWord + str[j];
Inc(j)
end;
// Проверка на ключевое слово
FOnKeyWord(Self, StrWord, IsKeyWord);
if IsKeyWord then
begin
Font.Color:= clRed
else
Font.Color:= clBlack;
// Выводим слово
TextOut(dx, dy, StrWord);
// Перемещаемся на следующую позицию
dx := dx + TextWidth( StrWord );
// Восстанавливаем основной цвет
Font.Color:= clBlack;
StrWord := '';
// Если символ - пробел, выводим его
if (str[j] = ' ') and (j <= Length(str)) then
begin
TextOut(dx, dy, ' ');
dx := dx + TextWidth( ' ' );
Inc(j);
end;
end;
// Перемещаемся на следующую строку
dy:= dy + TextHeight('X');
end;
end;
BitBlt( aCanvas.Handle, 0, 0, BitMap.Width, BitMap.Height, BitMap.Canvas.Handle, 0, 0, SRCCOPY );
finally
if Message.DC = 0 then EndPaint(Handle, PS);
aCanvas.Free;
BitMap.Free;
end;
inherited;
end;
Т.е. здесь я всего лишь вывожу текст, выделяя нужные мне слова. Все выделяется, а вот допустим
SendMessage(Memo1.Handle, EM_SCROLL, SB_LINEDOWN, 0);
уже не работает. Почему?
Сергей М. (2006-10-18 13:50:00) [18]
> В том-то и дело, что ничего не добавлено
Значит и вопрос твой в корне неверно сформулирован.
> почему? Ведь я только метод WMPaint переопределяю
Значит логика обработки WM_PAINT не верна.
Alex_C (2006-10-18 13:38:00) [19]В том-то и дело, что ничего не добавлено, а как я уже выше писал, не работает, как предшественник. Вопрос: почему? Ведь я только метод WMPaint переопределяю.
Сергей М. (2006-10-18 11:20:00) [20]
> чтобы он наследовал все св-ва своего предшественника и добавлял
> новые
А где в твоем классе вновь добавленные свойства ? В упор не вижу их ...