Версия для печати темы

Нажмите сюда для просмотра этой темы в обычном формате

Форум «Всё о Паскале» _ Делфи _ Компонент

Автор: sheka 17.11.2009 22:43

С помощью инета сделал свой компонент. Подскажите, как

unit component1;

interface

{uses
SysUtils, Classes, ExtCtrls;}
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, ExtCtrls;

var Timer: TTimer;

type
tcomponent1 = class(TComponent)

private
{ Private declarations }
FShowType:boolean;
protected
{ Protected declarations }
procedure OnTimer(Sender: TObject);
public
{ Public declarations }
constructor Create(AOwner:TComponent);override;
published
{ Published declarations }
property ShowType: boolean read FshowType write FShowType;
end;



procedure Register;

implementation

procedure Register;
begin
RegisterComponents('Samples', [tcomponent1]);
end;

constructor tcomponent1.Create(aowner:Tcomponent);
begin
Timer:=TTimer.Create(self);
Timer.Enabled:=true;
Timer.OnTimer:=OnTimer;
Timer.Interval:=1000;
end;

procedure tcomponent1.OnTimer(Sender: TObject);
begin
FShowType:=not FShowType; <<----------------------------------------вот здесь
end;

end.

изменять, например, свойство Visible формы, на которую этот компонент установлен.

Автор: volvo 17.11.2009 22:50

Свойство Owner тебе поможет.

Автор: sheka 17.11.2009 22:58

Цитата(volvo @ 17.11.2009 19:50) *

Свойство Owner тебе поможет.

owner.visible?

Автор: volvo 17.11.2009 23:23

На самом деле лучше бы так сделать:

type
TComponent1 = class(TComponent)
protected
// ...
procedure SetShowType(value: Boolean);
published
{ Published declarations }
property ShowType: boolean read FshowType write SetShowType;
end;

Procedure TComponent1.SetShowType(value: Boolean);
begin
FShowType := value;
(Self.Owner as TForm).Visible := value;
end;
. Кстати, почему таймер - глобальная переменная?

Автор: sheka 18.11.2009 0:55

Цитата
Кстати, почему таймер - глобальная переменная?
это я с сайта списывал.
Цитата
property ShowType: boolean read FshowType write SetShowType;

Насколько я понял, то что стоит после read - процедура считывания информации с поля; после write - записи в поле. Только в чем прикол этих процедур - я не понял.

А где у вас таймер на выполнение процедуры SetShowType? или потом в OnTimer вызывать эту процедуру?

Автор: volvo 18.11.2009 3:35

Нет, мне не удалось добиться того, что ты хочешь (регулировать видимость невидимость формы). Таймер - работает, для проверки я сделал наследника от TEdit, и по таймеру каждую секунду выводил текущее время. С этим проблема нет, даже в Design-Time. А вот с видимостью формы - проблема, даже тогда, когда таймер запускался по нажатию дополнительной кнопки уже после старта приложения. С чем это связано - не знаю.

Автор: sheka 18.11.2009 5:36

Выложите пожалуйста свой компонент. не могу понять в чем проблема. ни то что я пишу, ни то что копирую уже готовое с нета - ничего не работает mad.gif
Видимость- это я взял с неба - для наглядности)не думал что с этим могут быть какие-то проблемы.

Автор: volvo 18.11.2009 6:47

Вот сам компонент:
Прикрепленный файл  Component2.pas ( 1.22 килобайт ) Кол-во скачиваний: 473


В основном приложении на форме лежит этот компонент и кнопка. Кнопка делает следующее:

procedure TForm1.Button1Click(Sender: TObject);
begin
MyComponent1.Start;
end;
, после чего в MyComponent1 начинает выводиться текущее время.

Автор: sheka 18.11.2009 23:10

Спасибо, уже кое-что стало понятно,но еще вопросы остались:
хочу сделать событие 'OnChange' например, при каждом изменении Text чтобы Timer.Enabled:=not Timer.Enabled но его и остальные поля и методы предка - НЕТ! т.е. их не видит.
почему?
и еще, что вот это за проверка:if Assigned(FOnTimer) then FOnTimer(Self); выполнилось ли событие OnTimer или нет?

Автор: volvo 18.11.2009 23:43

Цитата
но его и остальные поля и методы предка - НЕТ! т.е. их не видит.
wacko.gif Чего кто там не видит? Ты скриншоты показывай что-ли, что и где ты хочешь увидеть, а не видишь...

Цитата
и еще, что вот это за проверка:if Assigned(FOnTimer) then FOnTimer(Self);
А если у тебя за время между тиками таймера (т.е. за эту самую секунду) произошли изменения, ты (ну, или кто-то другой, неважно) сбросил FOnTimer в nil? Что будет на следующем тике? Попытка разыменовать нулевой указатель будет, а это приведет только к аварийному вылету. Вот поэтому сначала проверяем, есть ли собственно обработчик, и если есть - то вызываем его.

Автор: sheka 19.11.2009 1:58

Вот смотрите: если на форме стоит только один Edit1 и прописать:

procedure TForm1.Edit1Change(Sender: TObject);
begin
form1.Caption:=edit1.Text;
end;

тогда в Run-Time будет при изменении Edit1.Text будет меняться form1.Caption.
как мне сделать чтобы при изменении текста моего компонента происходило то же самое, без предварительной прописки в новоп проекте:
procedure TForm1.MyComponent1Change(Sender: TObject);
begin
form1.Caption:=edit1.Text;
end;


Что собой представляет TNotifyEvent? указатель на какое-то событие? если да, то ним могут быть все(OnClick,OnCreate..итд)?

Автор: volvo 19.11.2009 2:31

Цитата
как мне сделать чтобы при изменении текста моего компонента происходило то же самое, без предварительной прописки в новоп проекте:
Ну, так в чем проблема? Проверяй, что компонент лежит на форме, а не на каком-нибудь другом компоненте, и изменяй заголовок владельца:
procedure TMyComponent.MyOnTimer(Sender: TObject);
begin
Caption := TimeToStr(Now);
if Owner is TCustomForm then
begin
TCustomForm(Owner).Caption := Caption; // Копируем содержимое Caption-а компонента в заголовок формы
end;

if Assigned(FOnTimer) then FOnTimer(Self);
end;
Только что проверил - работает... Только ты должен перерегистрировать компонент, и только потом его использовать в проекте.

Цитата
Что собой представляет TNotifyEvent? указатель на какое-то событие? если да, то ним могут быть все(OnClick,OnCreate..итд)?

Цитата(Исходники VCL)
type TNotifyEvent = procedure(Sender : TObject) of object;
, то есть, любой метод класса, принимающий один параметр типа TObject, подходит под эту сигнатуру.

Автор: sheka 19.11.2009 4:26

Цитата(volvo @ 18.11.2009 21:31) *

Ну, так в чем проблема?

Вы меня не правильно поняли: проблема у меня с тем, чтобы создать событие OnChange для моего компонента. Т.е. сделать все тоже самое, только не на MyOnTimer, а на СОБСТВЕННЫЙ OnChange НОВОГО компонента.
Цитата
TCustomForm(Owner).Caption := Caption;
а у Edita вроде Text,а не Caption wacko.gif

Цитата
Только ты должен перерегистрировать компонент, и только потом его использовать в проекте.

Да, с этим я уже намучался yes2.gif, что удалил какойто файл .drkt или как-то так и потом делфи переустанавливал lol.gif

Автор: sheka 19.11.2009 6:19

Я сделал то что хотел!!!

procedure TMyComponent.Change;
begin
inherited Change;
// ...
end;

У меня были такие ошибки:
1. procedure TMyComponent.OnChange; - поэтому и говорило, что такого метода нет!
2. где-то нашел, что надо писать inherited Change; для унаследования всех свойств предка.

good.gif Большое спасибо за внимание и уделенное время!

Автор: volvo 19.11.2009 6:27

Нет, по-моему мы друг друга не понимаем... Какая проблема перенести то же самое в обработчик события OnChange? Смотри:

type
TMyComponent = class(TEdit)
// ...
protected
{ Protected declarations }
procedure MyOnTimer(Sender: TObject);
procedure MyOnChange(Sender: TObject); // <--- Добавляешь это ...

constructor TMyComponent.Create(AOwner: TComponent);
begin
inherited;
FTimer := TTimer.Create(Self);
FTimer.OnTimer := MyOnTimer;
FTimer.Enabled := False;

Self.OnChange := MyOnChange; // <--- Добавляешь это, чтобы компонент знал, как реагировать
end;

// Ну, и сам метод:
procedure TMyComponent.MyOnChange(Sender: TObject);
begin
if Owner is TCustomForm then
begin
TCustomForm(Owner).Caption := Caption;
end;
end;


И опять же все работает: забросил я свой компонент на форму, запустил программу, но таймер не активизировал. И изменяю содержимое Эдита. Тут же обновляется заголовок формы. Что-то не так?

Цитата
а у Edita вроде Text,а не Caption
У TControl есть свойство Caption, и если ты внутри потомка TControl, то у тебя есть к нему доступ (TEdit - потомок TControl, так что все в порядке). Если то же самое попытаться сделать из основной программы - то будет ошибка при попытке обращения к защищенному члену класса TControl. Можешь использовать Text, если тебе удобнее...

Добавлено через 3 мин.
Бррр... Так ты хочешь, чтобы твой метод Change был доступен извне, или все-таки:
Цитата(sheka)
как мне сделать чтобы при изменении текста моего компонента происходило то же самое, без предварительной прописки в новоп проекте:
? Ты ж для себя реши, что тебе надо?

Автор: sheka 19.11.2009 22:34

Цитата(volvo @ 19.11.2009 1:27) *
Бррр... Так ты хочешь, чтобы твой метод Change был доступен извне?

Нет, извне мне он не нужен. Я хочу просто чтобы всегда при изменении компонента исполнялись определенные действия, но и из проекта(т.е. как обычно) можно было добавить еще что-то в Onchange.
Оба варианта(мой и Ваш) работают именно так. А какая между ними разница?

Автор: volvo 19.11.2009 23:57

Хелп читал?

Цитата
Applications do not call the Change method directly. It is triggered automatically by Windows events. Change is exposed as a protected method so that derived classes can make additional responses when the text changes beyond invoking the OnChange event handler.
(Вот http://docs.codegear.com/products/rad_studio/radstudio2007/RS2007_helpupdates/HUpdate4/EN/html/delphivclwin32/StdCtrls_TCustomEdit_Change.html)

А ты вызываешь напрямую метод Change. Кстати, как ты описал заголовок? Тебя Дельфи не предупредила, что твой Change скрывает одноименный метод из TCustomEdit? Я же метод Change не вызываю, а переопределяю реакцию компонента на срабатывание события OnChange.

Автор: sheka 20.11.2009 0:36

Я ничего не описывал.
Не предупредила.

Автор: sheka 11.12.2009 4:26

Создается компонент, картинка. при нажатии на нее изменяется цвет компонента. Но почему-то не видно дополнительной картинки...(которая находится в средине компонента). Подскажите пожалуйста.

 unit image1;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls;

type
timage1 = class(TImage)
private
{ Private declarations }
protected
{ Protected declarations }
procedure MyOnClick(Sender: TObject);
public
{ Public declarations }
constructor Create(AOwner: TComponent); override;
published
{ Published declarations }
image1: Timage; // даже сюда поместил, а не в protected, думал видно будет
end;

procedure Register;

implementation

var b:boolean;

procedure Register;
begin
RegisterComponents('Samples', [timage1]);
end;

constructor timage1.Create(AOwner: TComponent);
begin
inherited;
Self.OnClick := MyOnClick;
image1 := Timage.Create(Self); // вот эта картинка дополнительная
image1.OnClick := MyOnClick;
image1.Left:=self.Left+10;
image1.Top:=self.Top+10;
image1.Height:=self.Height-20;
image1.Width:=self.Width-20;
image1.Stretch:=true;
image1.Proportional:=true;
image1.Transparent:=true;
image1.Visible:=true;
self.Visible:=true;
image1.Picture.LoadFromFile('in.bmp');
b:=true;
end;

procedure timage1.MyOnClick(Sender: TObject);
begin
if b = true then
begin
self.Canvas.Brush.Color := clBlack;
image1.Show; //вот здесь ее по идее должно показывать...
end
else
begin
self.Canvas.Brush.Color := clred;
image1.Show;
end;
self.Canvas.FillRect(Canvas.ClipRect);
b:=not b;
end;

end.


Автор: volvo 11.12.2009 7:25

Ты забыл добавить Parent-а создаваемой картинке. А для этого тебе надо наследоваться от TWinControl-я, или его наследника. TImage как базовый класс здесь не пойдет. Возьми, например, TPanel...

Автор: sheka 16.12.2009 1:32

Покажите пожалуйста фрагмент кода, где добавляется Parent

Автор: volvo 16.12.2009 2:29

Вот так, например:

unit Component2;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls;

type
timage1 = class(TPanel)
private
{ Private declarations }
protected
{ Protected declarations }
procedure MyOnClick(Sender: TObject);
public
{ Public declarations }
constructor Create(AOwner: TComponent); override;
published
{ Published declarations }
image1: Timage; // даже сюда поместил, а не в protected, думал видно будет
end;

procedure Register;

implementation

var b: boolean;
procedure Register;
begin
RegisterComponents('Samples', [timage1]);
end;
constructor timage1.Create(AOwner: TComponent);
begin
inherited;
Self.OnClick := MyOnClick;
image1 := Timage.Create(Self);
with image1 do
begin
Parent := Self;
// OnClick := MyOnClick;
Picture.Bitmap.LoadFromFile('in.bmp');
Left := self.Left + 10;
Top := self.Top + 10;
Height := self.Height - 20;
Width := self.Width - 20;
Visible := true;
Center := true;
Stretch := true;
Transparent := true;
end;
b := true;
end;

procedure timage1.MyOnClick(Sender: TObject);
begin
if b = true then
begin
self.Canvas.Brush.Color := clBlack;
end
else
begin
self.Canvas.Brush.Color := clred;
end;

image1.Hide;
self.Canvas.FillRect(Canvas.ClipRect);
image1.Show;

b := not b;
end;

end.