Author: Yoganand Aiyadurai
How can I store values in a DFM file during design Time, so that it can be used
during run time?
Answer:
Most of use a table or some kind of files to store the data for the application to
pick up the data during run time. Actually we can store the data in the form file (
dfm ). In the following example I have created a component derived from the
TPersistent class. It uses the TReader and TWriter class to Read and write to the
respective streams. The TComponentEditor allows to define the design time editors
to work with the component class. The TPropertyEditor class allows to define a
property editor for a specialized property in a component class.
In the following example I have given the component's source code. The design time
property editor has a source file code(pas) and source form code for the form
(dfm). copy the dfm code to create a dfm file, name it as "propdlg.dfm" and assign
it's Name property to "fmpropdlg" and the source file code to create a pas file,
name it as "propdlg.pas". Install the component TMyComponent, include the file
"propdlg.pas" of the property editor in the the package.
The component will then allow you to invoke the design time editor by clicking on
the object inspector for the specified property or by right clicking on the
component itself and then selecting the respective verb in the menu context. You
can store the fields of the class Tmydata in the form file ( dfm ) during design
time.
1
2 //**********************************************************************
3 //***** Component source (pas) *****************************************
4 //**********************************************************************
5 unit Test;
6
7 interface
8
9 uses
10 Windows, Forms, Classes, StdCtrls, SysUtils, ComCtrls, Messages, Controls,
11 {DB, DBCtrls, CommCtrl, OCIH, OCI, OCL, ExtVCs,} dsgnintf;
12
13 type
14 TMyPropertyEditor = class(TPropertyEditor)
15 private
16 { Private declarations }
17 public
18 { Public declarations }
19 function GetAttributes: TPropertyAttributes; override;
20 procedure Edit; override;
21 function GetValue: string; override;
22 end;
23
24 TMyEditorPopup = class(TComponentEditor)
25 private
26 { Private declarations }
27 public
28 { Public declarations }
29 procedure Edit; override;
30 procedure ExecuteVerb(Index: Integer); override;
31 function GetVerb(Index: Integer): string; override;
32 function GetVerbCount: Integer; override;
33 end;
34
35 TMyData = class
36 private
37 Fstr: string;
38 FInt: Integer;
39 public
40 property StringValue: string read Fstr write FStr;
41 property IntegerValue: Integer read FInt write FInt;
42 end;
43
44 TMyTable = class(TPersistent)
45 private
46 FList: TList;
47 function GetCount: Integer;
48 function GetItem(Index: Integer): TMyData;
49
50 procedure SetItem(Index: Integer; vItem: TMyData);
51 procedure ReadProperties(Reader: TReader);
52 procedure WriteProperties(Writer: TWriter);
53 protected
54 procedure DefineProperties(Filer: TFiler); override;
55 public
56 constructor Create;
57 destructor Destroy; override;
58 procedure AddItem;
59 procedure DeleteItem(Index: Integer);
60 property ItemCount: Integer read GetCount;
61 property Items[Index: Integer]: TMyData read GetItem write SetItem; default;
62 end;
63
64 TMyComponent = class(TComponent)
65 private
66 FMyTable: TMyTable;
67 procedure SetTables(Value: TMyTable);
68 public
69 constructor Create(AOwner: TComponent); override;
70 destructor Destroy; override;
71 published
72 property MyTables: TMyTable read FMyTable write SetTables;
73 end;
74
75 procedure register;
76
77 implementation
78
79 uses PropDlg;
80 { TMyTable }
81
82 constructor TMyTable.Create;
83 begin
84 FList := TList.Create;
85 FList.Clear;
86 end;
87
88 destructor TMyTable.Destroy;
89 begin
90 FList.Free;
91 FList := nil;
92 inherited destroy;
93 end;
94
95 procedure TMyTable.DefineProperties(Filer: TFiler);
96 begin
97 Filer.DefineProperty('Tables', ReadProperties, WriteProperties, True);
98 end;
99
100 procedure TMyTable.ReadProperties(Reader: TReader);
101 begin
102 Reader.ReadListBegin;
103 while (not Reader.EndOfList) do
104 begin
105 AddItem;
106 with Items[itemCount - 1] do
107 begin
108 Fstr := Reader.ReadString;
109 FInt := Reader.ReadInteger;
110 end;
111 end;
112 Reader.ReadListEnd;
113 end;
114
115 procedure TMyTable.WriteProperties(Writer: TWriter);
116 var
117 I: Integer;
118 begin
119 Writer.WriteListBegin;
120 for I := 0 to (ItemCount - 1) do
121 begin
122 with Items[I] do
123 begin
124 Writer.WriteString(Fstr);
125 Writer.WriteInteger(FInt);
126 end;
127 end;
128 Writer.WriteListEnd;
129 end;
130
131 procedure TMyTable.AddItem;
132 var
133 vData: TMyData;
134 begin
135 vData := TMyData.Create;
136 FList.Add(vData);
137 end;
138
139 function TMyTable.GetCount: Integer;
140 begin
141 Result := FList.Count;
142 end;
143
144 function TMyTable.GetItem(Index: Integer): TMyData;
145 begin
146 Result := TMyData(FList[Index]);
147 end;
148
149 procedure TMyTable.SetItem(Index: Integer; vItem: TMyData);
150 begin
151 Flist[Index] := vItem;
152 end;
153
154 procedure TMyTable.DeleteItem(Index: Integer);
155 begin
156 FList.Delete(Index);
157 end;
158
159 { TMyComponent }
160
161 constructor TMyComponent.Create(AOwner: TComponent);
162 begin
163 inherited Create(AOwner);
164 FMyTable := TMyTable.Create;
165 end;
166
167 destructor TMyComponent.Destroy;
168 begin
169 FMyTable.Free;
170 FMyTable := nil;
171 inherited Destroy;
172 end;
173
174 procedure TMyComponent.SetTables(Value: TMyTable);
175 begin
176 {}
177 end;
178
179 function TMyPropertyEditor.GetAttributes: TPropertyAttributes;
180 begin
181 Result := [paDialog, paReadOnly, paRevertable];
182 end;
183
184 procedure TMyPropertyEditor.Edit;
185 var
186 MyComponent: TPersistent;
187 FMyComponent: TMyComponent;
188 MyDialog: TfmPropDlg;
189 begin
190 MyComponent := GetComponent(0);
191 if MyComponent is TMyComponent then
192 begin
193 FMyComponent := TMyComponent(MyComponent);
194
195 MyDialog := TfmPropDlg.Create(Application);
196 try
197 MyDialog.FMyComponent := FMyComponent;
198 MyDialog.FmyPropertyEditor := Self;
199 MyDialog.ShowModal;
200 finally
201 MyDialog.Free;
202 MyDialog := nil
203 end;
204 end;
205 end;
206
207 function TMyPropertyEditor.GetValue: string;
208 begin
209 FmtStr(Result, '(%s)', [GetPropType^.Name]);
210 end;
211
212 procedure register;
213 begin
214 RegisterComponents('YOGI', [TMyComponent]);
215 RegisterPropertyEditor(TypeInfo(TMyTable), TMyComponent, 'MyTables',
216 TMyPropertyEditor);
217 RegisterComponentEditor(TMyComponent, TMyEditorPopup);
218 end;
219
220 { TMyEditorPopup }
221
222 procedure TMyEditorPopup.Edit;
223 var
224 // MyComponent : TPersistent;
225 FMyComponent: TMyComponent;
226 MyDialog: TfmPropDlg;
227 begin
228 if Component is TMyComponent then
229 begin
230 FMyComponent := TMyComponent(Component);
231 MyDialog := TfmPropDlg.Create(Application);
232 try
233 MyDialog.FMyComponent := FMyComponent;
234 MyDialog.FMyEditorPopup := Self;
235 MyDialog.ShowModal;
236 finally
237 MyDialog.Free;
238 MyDialog := nil;
239 end;
240 end;
241 end;
242
243 procedure TMyEditorPopup.ExecuteVerb(Index: Integer);
244 begin
245 if (Index = 0) then
246 Edit;
247 end;
248
249 function TMyEditorPopup.GetVerb(Index: Integer): string;
250 begin
251 if Index = 0 then
252 Result := 'Yoganand''s Editor';
253 end;
254
255 function TMyEditorPopup.GetVerbCount: Integer;
256 begin
257 Result := 1;
258 end;
259
260 { TMyTest }
261
262 end.
263
264 //**********************************************************************
265 //***** Property Editor's source file (pas) code *******************
266 //**********************************************************************
267
268 unit propDlg;
269
270 interface
271
272 uses
273 Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
274 Buttons, StdCtrls, Test, dsgnintf;
275
276 type
277 TfmPropDlg = class(TForm)
278 Label1: TLabel;
279 Label2: TLabel;
280 edtStr: TEdit;
281 edtInt: TEdit;
282 sbAdd: TSpeedButton;
283 sbDelete: TSpeedButton;
284 sbOk: TSpeedButton;
285 sbCancel: TSpeedButton;
286 sbup: TSpeedButton;
287 sbDown: TSpeedButton;
288 procedure sbAddClick(Sender: TObject);
289 procedure sbOkClick(Sender: TObject);
290 procedure sbupClick(Sender: TObject);
291 procedure FormCreate(Sender: TObject);
292 procedure FormShow(Sender: TObject);
293 procedure sbDownClick(Sender: TObject);
294 procedure sbDeleteClick(Sender: TObject);
295 private
296 { Private declarations }
297 FCurrentIndex: Integer;
298 public
299 { Public declarations }
300 FMyComponent: TMyComponent;
301 FMyPropertyEditor: TPropertyEditor;
302 FMyEditorPopup: TComponentEditor;
303 FPageIndex: Integer;
304 end;
305
306 var
307 fmPropDlg: TfmPropDlg;
308
309 implementation
310
311 {$R *.DFM}
312
313 procedure TfmPropDlg.sbAddClick(Sender: TObject);
314 begin
315 FMyComponent.MyTables.AddItem;
316 edtStr.Text := '';
317 edtInt.Text := '';
318 edtStr.SetFocus;
319 end;
320
321 procedure TfmPropDlg.sbOkClick(Sender: TObject);
322 begin
323 FMyComponent.MyTables[FMyComponent.MyTables.ItemCount - 1].StringValue :=
324 edtStr.Text;
325 FMyComponent.MyTables[FMyComponent.MyTables.ItemCount - 1].IntegerValue :=
326 StrtoInt(edtInt.Text);
327 end;
328
329 procedure TfmPropDlg.sbupClick(Sender: TObject);
330 var
331 I: Integer;
332 begin
333 if (FCurrentIndex > 0) then
334 begin
335 Dec(FCurrentIndex);
336 edtStr.Text := FMyComponent.MyTables[FCurrentIndex].StringValue;
337 edtInt.Text := Inttostr(FMyComponent.MyTables[FCurrentIndex].IntegerValue);
338 end;
339 end;
340
341 procedure TfmPropDlg.FormCreate(Sender: TObject);
342 begin
343 FCurrentIndex := 0;
344 end;
345
346 procedure TfmPropDlg.FormShow(Sender: TObject);
347 begin
348 if (FMyComponent.MyTables.ItemCount > 0) then
349 begin
350 FCurrentIndex := 0;
351 edtStr.Text := FMyComponent.MyTables[FCurrentIndex].StringValue;
352 edtInt.Text := Inttostr(FMyComponent.MyTables[FCurrentIndex].IntegerValue);
353 end;
354 end;
355
356 procedure TfmPropDlg.sbDownClick(Sender: TObject);
357 begin
358 if (FCurrentIndex < (FMyComponent.MyTables.ItemCount - 1)) then
359 begin
360 Inc(FCurrentIndex);
361 edtStr.Text := FMyComponent.MyTables[FCurrentIndex].StringValue;
362 edtInt.Text := Inttostr(FMyComponent.MyTables[FCurrentIndex].IntegerValue);
363 end;
364 end;
365
366 procedure TfmPropDlg.sbDeleteClick(Sender: TObject);
367 begin
368 if (FMyComponent.MyTables.ItemCount > 0) then
369 begin
370 FMyComponent.MyTables.DeleteItem(FCurrentIndex);
371 FCurrentIndex := 0;
372 edtStr.Text := FMyComponent.MyTables[FCurrentIndex].StringValue;
373 edtInt.Text := Inttostr(FMyComponent.MyTables[FCurrentIndex].IntegerValue);
374 end;
375 end;
376
377 end.
378
379 //**********************************************************************
380 //****** Property Editor's form file (dfm) Code **************************
381 //**********************************************************************
382
383 object fmPropDlg: TfmPropDlg
384 Left = 263
385 Top = 371
386 BorderStyle = bsDialog
387 Caption = 'Editor Dlg'
388 ClientHeight = 103
389 ClientWidth = 218
390 Color = clBtnFace
391 Font.Charset = DEFAULT_CHARSET
392 Font.Color = clWindowText
393 Font.Height = -11
394 Font.Name = 'MS Sans Serif'
395 Font.Style = []
396 OldCreateOrder = False
397 Position = poScreenCenter
398 OnCreate = FormCreate
399 OnShow = FormShow
400 PixelsPerInch = 96
401 TextHeight = 13
402 object Label1: TLabel
403 Left = 16
404 Top = 24
405 Width = 36
406 Height = 13
407 Caption = 'Value 1'
408 end
409 object Label2: TLabel
410 Left = 17
411 Top = 51
412 Width = 33
413 Height = 13
414 Caption = 'Value2'
415 end
416 object sbAdd: TSpeedButton
417 Left = 26
418 Top = 77
419 Width = 23
420 Height = 22
421 Glyph.Data = {
422 76010000424D7601000000000000760000002800000020000000100000000100
423 04000000000000010000130B0000130B00001000000000000000000000000000
424 800000800000008080008000000080008000808000007F7F7F00BFBFBF000000
425 FF0000FF000000FFFF00FF000000FF00FF00FFFF0000FFFFFF00333333333333
426 33333333FF33333333FF333993333333300033377F3333333777333993333333
427 300033F77FFF3333377739999993333333333777777F3333333F399999933333
428 33003777777333333377333993333333330033377F3333333377333993333333
429 3333333773333333333F333333333333330033333333F33333773333333C3333
430 330033333337FF3333773333333CC333333333FFFFF77FFF3FF33CCCCCCCCCC3
431 993337777777777F77F33CCCCCCCCCC3993337777777777377333333333CC333
432 333333333337733333FF3333333C333330003333333733333777333333333333
433 3000333333333333377733333333333333333333333333333333}
434 NumGlyphs = 2
435 OnClick = sbAddClick
436 end
437 object sbDelete: TSpeedButton
438 Left = 62
439 Top = 76
440 Width = 23
441 Height = 22
442 Glyph.Data = {
443 76010000424D7601000000000000760000002800000020000000100000000100
444 04000000000000010000130B0000130B00001000000000000000000000000000
445 800000800000008080008000000080008000808000007F7F7F00BFBFBF000000
446 FF0000FF000000FFFF00FF000000FF00FF00FFFF0000FFFFFF00333333333333
447 333333333333333333FF33333333333330003333333333333777333333333333
448 300033FFFFFF3333377739999993333333333777777F3333333F399999933333
449 3300377777733333337733333333333333003333333333333377333333333333
450 3333333333333333333F333333333333330033333F33333333773333C3333333
451 330033337F3333333377333CC3333333333333F77FFFFFFF3FF33CCCCCCCCCC3
452 993337777777777F77F33CCCCCCCCCC399333777777777737733333CC3333333
453 333333377F33333333FF3333C333333330003333733333333777333333333333
454 3000333333333333377733333333333333333333333333333333}
455 NumGlyphs = 2
456 OnClick = sbDeleteClick
457 end
458 object sbOk: TSpeedButton
459 Left = 100
460 Top = 76
461 Width = 23
462 Height = 22
463 Glyph.Data = {
464 76010000424D7601000000000000760000002800000020000000100000000100
465 04000000000000010000120B0000120B00001000000000000000000000000000
466 800000800000008080008000000080008000808000007F7F7F00BFBFBF000000
467 FF0000FF000000FFFF00FF000000FF00FF00FFFF0000FFFFFF00555555555555
468 555555555555555555555555555555555555555555FF55555555555559055555
469 55555555577FF5555555555599905555555555557777F5555555555599905555
470 555555557777FF5555555559999905555555555777777F555555559999990555
471 5555557777777FF5555557990599905555555777757777F55555790555599055
472 55557775555777FF5555555555599905555555555557777F5555555555559905
473 555555555555777FF5555555555559905555555555555777FF55555555555579
474 05555555555555777FF5555555555557905555555555555777FF555555555555
475 5990555555555555577755555555555555555555555555555555}
476 NumGlyphs = 2
477 OnClick = sbOkClick
478 end
479 object sbCancel: TSpeedButton
480 Left = 144
481 Top = 76
482 Width = 23
483 Height = 22
484 Glyph.Data = {
485 76010000424D7601000000000000760000002800000020000000100000000100
486 04000000000000010000130B0000130B00001000000000000000000000000000
487 800000800000008080008000000080008000808000007F7F7F00BFBFBF000000
488 FF0000FF000000FFFF00FF000000FF00FF00FFFF0000FFFFFF00333333333333
489 333333333333333333333333333333333333333FFF33FF333FFF339993370733
490 999333777FF37FF377733339993000399933333777F777F77733333399970799
491 93333333777F7377733333333999399933333333377737773333333333990993
492 3333333333737F73333333333331013333333333333777FF3333333333910193
493 333333333337773FF3333333399000993333333337377737FF33333399900099
494 93333333773777377FF333399930003999333337773777F777FF339993370733
495 9993337773337333777333333333333333333333333333333333333333333333
496 3333333333333333333333333333333333333333333333333333}
497 NumGlyphs = 2
498 end
499 object sbup: TSpeedButton
500 Left = 192
501 Top = 16
502 Width = 23
503 Height = 22
504 Glyph.Data = {
505 76010000424D7601000000000000760000002800000020000000100000000100
506 04000000000000010000120B0000120B00001000000000000000000000000000
507 800000800000008080008000000080008000808000007F7F7F00BFBFBF000000
508 FF0000FF000000FFFF00FF000000FF00FF00FFFF0000FFFFFF00333333000333
509 3333333333777F33333333333309033333333333337F7F333333333333090333
510 33333333337F7F33333333333309033333333333337F7F333333333333090333
511 33333333337F7F33333333333309033333333333FF7F7FFFF333333000090000
512 3333333777737777F333333099999990333333373F3333373333333309999903
513 333333337F33337F33333333099999033333333373F333733333333330999033
514 3333333337F337F3333333333099903333333333373F37333333333333090333
515 33333333337F7F33333333333309033333333333337373333333333333303333
516 333333333337F333333333333330333333333333333733333333}
517 NumGlyphs = 2
518 OnClick = sbupClick
519 end
520 object sbDown: TSpeedButton
521 Left = 192
522 Top = 64
523 Width = 23
524 Height = 22
525 Glyph.Data = {
526 76010000424D7601000000000000760000002800000020000000100000000100
527 04000000000000010000120B0000120B00001000000000000000000000000000
528 800000800000008080008000000080008000808000007F7F7F00BFBFBF000000
529 FF0000FF000000FFFF00FF000000FF00FF00FFFF0000FFFFFF00333333303333
530 333333333337F33333333333333033333333333333373F333333333333090333
531 33333333337F7F33333333333309033333333333337373F33333333330999033
532 3333333337F337F33333333330999033333333333733373F3333333309999903
533 333333337F33337F33333333099999033333333373333373F333333099999990
534 33333337FFFF3FF7F33333300009000033333337777F77773333333333090333
535 33333333337F7F33333333333309033333333333337F7F333333333333090333
536 33333333337F7F33333333333309033333333333337F7F333333333333090333
537 33333333337F7F33333333333300033333333333337773333333}
538 NumGlyphs = 2
539 OnClick = sbDownClick
540 end
541 object edtStr: TEdit
542 Left = 56
543 Top = 21
544 Width = 121
545 Height = 21
546 TabOrder = 0
547 end
548 object edtInt: TEdit
549 Left = 56
550 Top = 48
551 Width = 121
552 Height = 21
553 TabOrder = 1
554 end
555 end
556
557 //******************************************************
|