Sign in Join
Wiki copytemporary

Streaming components/pt: what changed

Revision 1 to 2. Removed lines have a minus sign; added lines have a plus sign.

OldNewLine
11## Introdução
22
33Normalmente, quando você necessita armazenar dados em disco ou rede, você deve escrever código para carregamento e o salvamento de cada propriedade. Este tutorial descreve como escrever classes, estas podem ter carregado de e conservado para os streams(fluxos) sem código extra da escrita ler/salvar usando o RTTI.
44
55Aqui tem um exemplo nos fontes do lazarus, demonstrando como salvar um TGroupBox com um TCheckBox filho para uma stream(fluxo) e ler uma stream de volta para criar uma cópia de ambos os componentes.
66
7-` Veja <lazaruspath>/examples/componentstreaming/`
7+```text
8+ Veja <lazaruspath>/examples/componentstreaming/
9+```
810
911Na combinação com [[RTTI controls]] você pode reduzir o tamanho de código necessário para conectar os dados do programa com a GUI e o Disco/Rede para um minímo.
1012
1113## TComponent / TPersistent
1214
1315A classe **TPersistent** é definida na unidade Classes e estão utilizando a diretiva de compilação **{\$M+}**. Esta diretiva diz ao compilado para criar o Tipo de Informação em Tempo de Execução (**RTTI**). Isto significa que e todos seus descendentes começam uma nova seção **published** da classe . Propriedades da 'Published'(difundida) são visíveis como a 'public'(pública), mas adicionalmente sua estrutura é acessível em tempo de execução. O que significa que toda propriedade difundida pode ser lida e escrita em tempo de execução. A IDE por exemplo usa este para trabalhar com componentes que nunca se ouviu.
1416
1517**TComponent** extende a habilidade de TPersistent para ter componentes filhos. Isto é importante para streaming, onde um componente é o **root component**(raiz) também chamado de **lookup root** com uma lista de componentes filho.
1618
1719## TReader / TWriter
1820
1921Aqui estão as classes que iremos trabalhar, que le/escreve um componente para/de um stream (Veja CreateLRSReader e CreateLRSWriter). Eles usam um **Driver** para ler/escrever um especial formato. No momento aqui temos um leitor (TLRSObjectReader) e um escritor (TLRSObjectWriter) de formato binário do objeto definido na unidade LResources e um escritor (TXMLObjectWriter) para TDOMDocument definido no Laz_XMLStreaming. A unidade LResources também contém funções para converter do formato binário par textual e vice-versa (LRSObjectBinaryToText, LRSObjectTextToBinary). A LCL prefere UTF8 para strings, enquanto o Delphi prefere Widestrings. Assim há algumas funções da conversão também.
2022
2123## Escrevendo seu próprio componente - Parte 1
2224
2325Um componente próprio pode ser um simples como: type
2426
25-` TMyComponent = class(TComponent)`\
26-` private`\
27-`   FID: integer;`\
28-` published`\
29-`   property ID: integer read FID write FID;`\
30-` end;`
27+``` pascal
28+ TMyComponent = class(TComponent)
29+ private
30+ FID: integer;
31+ published
32+ property ID: integer read FID write FID;
33+ end;
34+```
3135
3236## Escrevendo um componente para uma stream
3337
3438A unidade [[doc:lcl/lresources|LResources]] tem a seguinte função:
3539
36-` procedure WriteComponentAsBinaryToStream(AStream: TStream; AComponent: TComponent);`
40+``` pascal
41+ procedure WriteComponentAsBinaryToStream(AStream: TStream; AComponent: TComponent);
42+```
3743
3844Ela escreve um componente no formato binário num stream. Por exemplo:
3945
4046 procedure TForm1.Button1Click(Sender: TObject);
4147 var
4248 AStream: TMemoryStream;
4349 begin
4450 AStream:=TMemoryStream.Create;
4551 try
4652 WriteComponentAsBinaryToStream(AStream,AGroupBox);
4753 ... salvar a stream em algum lugar ...
4854 finally
4955 AStream.Free;
5056 end;
5157 end;
5258
5359## Lendo um componente de um stream
5460
5561A unidade LResources tem a seguinte função:
5662
57-` procedure ReadComponentFromBinaryStream(AStream: TStream;`\
58-`   var RootComponent: TComponent; OnFindComponentClass: TFindComponentClassEvent; TheOwner: TComponent = nil);`
63+``` pascal
64+ procedure ReadComponentFromBinaryStream(AStream: TStream;
65+ var RootComponent: TComponent; OnFindComponentClass: TFindComponentClassEvent; TheOwner: TComponent = nil);
66+```
5967
6068- AStream é a stream contendo um componente no formato binário.
6169- RootComponent é qualquer componente existente, cujo os dados serão sobre-escritos, ou esse é nil(valor vazio) um componente novo será criado.
6270- OnFindComponentClass é uma função, que é usada pelo TReader para pegar a classe a partir de classnames na stream. Por exemplo:
6371
6472 procedure TCompStreamDemoForm.OnFindClass(Reader: TReader;
6573 const AClassName: string; var ComponentClass: TComponentClass);
6674 begin
6775 if CompareText(AClassName,'TGroupBox')=0 then
6876 ComponentClass:=TGroupBox
6977 else if CompareText(AClassName,'TCheckBox')=0 then
7078 ComponentClass:=TCheckBox;
7179 end;
7280
7381- TheOwner é o componente raiz ou dono, quando criando um novo componente.
7482
7583## Propriedades que podem ser guardadas num Stream
7684
7785Há algumas limitações, que tipos TReader/TWriter podem colocar no stream:
7886
7987- Tipos básicos podem ser armazenados na stream: string, integer, char, single, double, extended, byte, word, cardinal, shortint, method pointers, etc. .
8088- TPersistent e seus descendentes podem ser armazenados na stream
8189- records, objects e classes não descendendo de TPersistent não podem ser guardadas. Para armazená-los você precisa dizer como no TReader/TWriter. Veja a seguir em armazenando dados customizados - DefineProperties.
8290
8391## Armazenadno Dados Customizados - DefineProperties
8492
8593Você pode guardar arbitrariamente dados sobrescrevendo(overriding) DefineProperties. Isto habilita a guardar qualquer dado na stream, que não tem tipos básico. Por exemplo para armazenar uma variável *FMyRect: TRect*' de seu componente, adicione os seguintes três métodos:
8694
8795 procedure DefineProperties(Filer: TFiler); override;
8896 procedure ReadMyRect(Reader: TReader);
8997 procedure WriteMyRect(Writer: TWriter);
9098
9199Com o seguinte código:
92100
93101 procedure TMyComponent.DefineProperties(Filer: TFiler);
94102 var
95103 MyRectMustBeSaved: Boolean;
96104 begin
97105 inherited DefineProperties(Filer);
98106 MyRectMustBeSaved:=(MyRect.Left<>0)
99107 or (MyRect.Top<>0)
100108 or (MyRect.Right<>0)
101109 or (MyRect.Bottom<>0);
102110 Filer.DefineProperty('MyRect',@ReadMyRect,@WriteMyRect,MyRectMustBeSaved);
103111 end;
104112
105113 procedure TMyComponent.ReadMyRect(Reader: TReader);
106114 begin
107115 with Reader do begin
108116 ReadListBegin;
109117 FMyRect.Left:=ReadInteger;
110118 FMyRect.Top:=ReadInteger;
111119 FMyRect.Right:=ReadInteger;
112120 FMyRect.Bottom:=ReadInteger;
113121 ReadListEnd;
114122 end;
115123 end;
116124
117125 procedure TMyComponent.WriteMyRect(Writer: TWriter);
118126 begin
119127 with Writer do begin
120128 WriteListBegin;
121129 WriteInteger(FMyRect.Left);
122130 WriteInteger(FMyRect.Top);
123131 WriteInteger(FMyRect.Right);
124132 WriteInteger(FMyRect.Bottom);
125133 WriteListEnd;
126134 end;
127135 end;
128136
129137Este irá salvar MyRect como uma propriedade 'MyRec'.
130138
131139Se você tem muitos objetos TRect, então você provavelmente não precisa escrever este código toda vez. A unidade LResources contém um exemplo de como escrever um procedimento para definir uma propriedade rect:
132140
133-` procedure DefineRectProperty(Filer: TFiler; const Name: string; ARect, DefaultRect: PRect);`\
141+``` pascal
142+ procedure DefineRectProperty(Filer: TFiler; const Name: string; ARect, DefaultRect: PRect);
143+```
134144
135145Desta maneira o código acima pode ser escrito de forma curta:
136146
137147 procedure TMyComponent.DefineProperties(Filer: TFiler);
138148 begin
139149 inherited DefineProperties(Filer);
140150 DefineRectProperty(Filer,'MyRect',@FMyRect,nil);
141151 end;
142152
143153## Escrevendo seu próprio componente - Parte 2
144154
145155Agora o exemplo pode ser extendido e nós podemos usar propriedades arbitrárias com somente algumas linhas de código:
146156
147157 type
148158 TMyComponent = class(TComponent)
149159 private
150160 FID: integer;
151161 FRect1: TRect;
152162 FRect2: TRect;
153163 protected
154164 procedure DefineProperties(Filer: TFiler); override;
155165 public
156166 property Rect1: TRect read FRect1 write FRect1;
157167 property Rect2: TRect read FRect2 write FRect2;
158168 published
159169 property ID: integer read FID write FID;
160170 end;
161171
162172 procedure TMyComponent.DefineProperties(Filer: TFiler);
163173 begin
164174 inherited DefineProperties(Filer);
165175 DefineRectProperty(Filer,'Rect1',@FRect1,nil);
166176 DefineRectProperty(Filer,'Rect2',@FRect2,nil);
167177 end;
168178
169179Este componente pode agora ser salvo, lido ou usado pelos [[RTTI controls]]. Você não precisa escrever algum código a mais.
170180
171181---
172182*From the Free Pascal wiki, page "Streaming components/pt", as it stood on 2007-09-19 after a change by Aliotti, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).*

Back to history