Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Как правильно написать свой компонент? [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]


> чтобы он наследовал все св-ва своего предшественника и добавлял
> новые


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


Наверх

Титульная страница Поиск, карта сайта Написать письмо