Sign in Join
Wiki copytemporary

Streaming components/pt: what changed

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

Title: Streaming components/pt

OldNewLine
1+## Introdução
2+
3+Normalmente, 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.
4+
5+Aqui 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.
6+
7+` Veja <lazaruspath>/examples/componentstreaming/`
8+
9+Na 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.
10+
11+## TComponent / TPersistent
12+
13+A 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.
14+
15+**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.
16+
17+## TReader / TWriter
18+
19+Aqui 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.
20+
21+## Escrevendo seu próprio componente - Parte 1
22+
23+Um componente próprio pode ser um simples como: type
24+
25+` TMyComponent = class(TComponent)`\
26+` private`\
27+`   FID: integer;`\
28+` published`\
29+`   property ID: integer read FID write FID;`\
30+` end;`
31+
32+## Escrevendo um componente para uma stream
33+
34+A unidade [[doc:lcl/lresources|LResources]] tem a seguinte função:
35+
36+` procedure WriteComponentAsBinaryToStream(AStream: TStream; AComponent: TComponent);`
37+
38+Ela escreve um componente no formato binário num stream. Por exemplo:
39+
40+ procedure TForm1.Button1Click(Sender: TObject);
41+ var
42+ AStream: TMemoryStream;
43+ begin
44+ AStream:=TMemoryStream.Create;
45+ try
46+ WriteComponentAsBinaryToStream(AStream,AGroupBox);
47+ ... salvar a stream em algum lugar ...
48+ finally
49+ AStream.Free;
50+ end;
51+ end;
52+
53+## Lendo um componente de um stream
54+
55+A unidade LResources tem a seguinte função:
56+
57+` procedure ReadComponentFromBinaryStream(AStream: TStream;`\
58+`   var RootComponent: TComponent; OnFindComponentClass: TFindComponentClassEvent; TheOwner: TComponent = nil);`
59+
60+- AStream é a stream contendo um componente no formato binário.
61+- RootComponent é qualquer componente existente, cujo os dados serão sobre-escritos, ou esse é nil(valor vazio) um componente novo será criado.
62+- OnFindComponentClass é uma função, que é usada pelo TReader para pegar a classe a partir de classnames na stream. Por exemplo:
63+
64+ procedure TCompStreamDemoForm.OnFindClass(Reader: TReader;
65+ const AClassName: string; var ComponentClass: TComponentClass);
66+ begin
67+ if CompareText(AClassName,'TGroupBox')=0 then
68+ ComponentClass:=TGroupBox
69+ else if CompareText(AClassName,'TCheckBox')=0 then
70+ ComponentClass:=TCheckBox;
71+ end;
72+
73+- TheOwner é o componente raiz ou dono, quando criando um novo componente.
74+
75+## Propriedades que podem ser guardadas num Stream
76+
77+Há algumas limitações, que tipos TReader/TWriter podem colocar no stream:
78+
79+- Tipos básicos podem ser armazenados na stream: string, integer, char, single, double, extended, byte, word, cardinal, shortint, method pointers, etc. .
80+- TPersistent e seus descendentes podem ser armazenados na stream
81+- 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.
82+
83+## Armazenadno Dados Customizados - DefineProperties
84+
85+Você 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:
86+
87+ procedure DefineProperties(Filer: TFiler); override;
88+ procedure ReadMyRect(Reader: TReader);
89+ procedure WriteMyRect(Writer: TWriter);
90+
91+Com o seguinte código:
92+
93+ procedure TMyComponent.DefineProperties(Filer: TFiler);
94+ var
95+ MyRectMustBeSaved: Boolean;
96+ begin
97+ inherited DefineProperties(Filer);
98+ MyRectMustBeSaved:=(MyRect.Left<>0)
99+ or (MyRect.Top<>0)
100+ or (MyRect.Right<>0)
101+ or (MyRect.Bottom<>0);
102+ Filer.DefineProperty('MyRect',@ReadMyRect,@WriteMyRect,MyRectMustBeSaved);
103+ end;
104+
105+ procedure TMyComponent.ReadMyRect(Reader: TReader);
106+ begin
107+ with Reader do begin
108+ ReadListBegin;
109+ FMyRect.Left:=ReadInteger;
110+ FMyRect.Top:=ReadInteger;
111+ FMyRect.Right:=ReadInteger;
112+ FMyRect.Bottom:=ReadInteger;
113+ ReadListEnd;
114+ end;
115+ end;
116+
117+ procedure TMyComponent.WriteMyRect(Writer: TWriter);
118+ begin
119+ with Writer do begin
120+ WriteListBegin;
121+ WriteInteger(FMyRect.Left);
122+ WriteInteger(FMyRect.Top);
123+ WriteInteger(FMyRect.Right);
124+ WriteInteger(FMyRect.Bottom);
125+ WriteListEnd;
126+ end;
127+ end;
128+
129+Este irá salvar MyRect como uma propriedade 'MyRec'.
130+
131+Se 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:
132+
133+` procedure DefineRectProperty(Filer: TFiler; const Name: string; ARect, DefaultRect: PRect);`\
134+
135+Desta maneira o código acima pode ser escrito de forma curta:
136+
137+ procedure TMyComponent.DefineProperties(Filer: TFiler);
138+ begin
139+ inherited DefineProperties(Filer);
140+ DefineRectProperty(Filer,'MyRect',@FMyRect,nil);
141+ end;
142+
143+## Escrevendo seu próprio componente - Parte 2
144+
145+Agora o exemplo pode ser extendido e nós podemos usar propriedades arbitrárias com somente algumas linhas de código:
146+
147+ type
148+ TMyComponent = class(TComponent)
149+ private
150+ FID: integer;
151+ FRect1: TRect;
152+ FRect2: TRect;
153+ protected
154+ procedure DefineProperties(Filer: TFiler); override;
155+ public
156+ property Rect1: TRect read FRect1 write FRect1;
157+ property Rect2: TRect read FRect2 write FRect2;
158+ published
159+ property ID: integer read FID write FID;
160+ end;
161+
162+ procedure TMyComponent.DefineProperties(Filer: TFiler);
163+ begin
164+ inherited DefineProperties(Filer);
165+ DefineRectProperty(Filer,'Rect1',@FRect1,nil);
166+ DefineRectProperty(Filer,'Rect2',@FRect2,nil);
167+ end;
168+
169+Este componente pode agora ser salvo, lido ou usado pelos [[RTTI controls]]. Você não precisa escrever algum código a mais.
170+
171+---
172+*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