Q: How do I retrieve properties from an HTML page?
-------------------------------------------------------------------
by Conrad Herrmann
24 June 97
A: Implement IPersistPropertyBag
The DAX class framework implements the standard binary persistence
interfaces, which allows most ActiveX containers to save and restore
the properties of an embedded DAX-implemented control. Internet Explorer
adds a new method to specify properties, the PARAM tag in an OBJECT statement.
Because this is a textual representation of properties rather than a binary
representation, IE defined a new interface called IPersistPropertyBag, whose
purpose is to loading properties from text. The DAX class framework does
not implement this new interface on TActiveXControl, so if you
want your ActiveX control to be able to read textual properties from
an HTML container, you will need to implement the interface.
About IPersistPropertyBag
-------------------------
IPersistPropertyBag declares the usual persistence methods, listed below.
The container calls InitNew when it wishes to create a new instance of the object,
Load when it wishes to cause an instance to retrieve properties from
a property bag, and Save when it wishes to copy the object's properties into
a property bag for writing to an HTML page.
1
2 function GetClassID(out classID: TCLSID): HResult; stdcall;
3 function InitNew: HResult; stdcall;
4 function Load(const pPropBag: IPropertyBag;
5 const pErrorLog: IErrorLog): HResult; stdcall;
6 function Save(const pPropBag: IPropertyBag; fClearDirty: BOOL;
7 fSaveAllProperties: BOOL): HResult; stdcall;
Implementing IPersistPropertyBag
--------------------------------
GetClassID and InitNew will be automatically bound to existing method
implementations from the other persistence interfaces. You will need to
bind the Load and Save interface methods to new method implementations in our
subclass. The implementations of these methods will copy the
control's properties to the property bag, and vice versa.
Because each of the other persistence interfaces defines
parameter-incompatible Load and Save methods, I follow the DAX
convention of prepending the interface name,
renaming the methods PersistPropertyBagLoad and PersistPropertyBagSave.
Example: This example is drawn from the PROPBAG example source code.
[ed: this example has not yet been published, but there's enough in here to be
helpful.]
8
9 TButtonX = class(TActiveXControl, IButtonX, IPersistPropertyBag)
10 ...
11 // IPersistPropertyBag
12 function IPersistPropertyBag.Load = PersistPropertyBagLoad;
13 function IPersistPropertyBag.Save = PersistPropertyBagSave;
14 function PersistPropertyBagLoad(const pPropBag: IPropertyBag;
15 const pErrorLog: IErrorLog): HResult; stdcall;
16 function PersistPropertyBagSave(const pPropBag: IPropertyBag; fClearDirty: BOOL;
17 fSaveAllProperties: BOOL): HResult; stdcall;
18 end;
19
20 function TButtonX.PersistPropertyBagLoad(const pPropBag: IPropertyBag;
21 const pErrorLog: IErrorLog): HResult; stdcall;
22 var v: OleVariant;
23 begin
24 if pPropBag.read( 'Cancel', v, pErrorLog) = S_OK then
25 FDelphiControl.Cancel := v;
26 if pPropBag.read( 'Caption', v, pErrorLog) = S_OK then
27 FDelphiControl.Caption := v;
28 if pPropBag.read( 'Cursor', v, pErrorLog) = S_OK then
29 FDelphiControl.Cursor := v;
30 if pPropBag.read( 'Default', v, pErrorLog) = S_OK then
31 FDelphiControl.default := v;
32 if pPropBag.read( 'DragCursor', v, pErrorLog) = S_OK then
33 FDelphiControl.DragCursor := v;
34 if pPropBag.read( 'DragMode', v, pErrorLog) = S_OK then
35 FDelphiControl.DragMode := v;
36 if pPropBag.read( 'Enabled', v, pErrorLog) = S_OK then
37 FDelphiControl.Enabled := v;
38 // Note that the font is a compound property in Delphi, but that HTML pages
39 // do not have compound properties, so we implement each part as a separate
40 // property.
41 if pPropBag.read( 'FontName', v, pErrorLog) = S_OK then
42 FDelphiControl.Font.Name := v;
43 if pPropBag.read( 'FontSize', v, pErrorLog) = S_OK then
44 FDelphiControl.Font.Size := v;
45 // we could add font special styles, too
46 if pPropBag.read( 'Visible', v, pErrorLog) = S_OK then
47 FDelphiControl.Visible := v;
48 Result := S_OK;
49 end;
50
51 function TButtonX.PersistPropertyBagSave(const pPropBag: IPropertyBag; fClearDirty:
52 BOOL;
53 fSaveAllProperties: BOOL): HResult; stdcall;
54 var v: OleVariant;
55 begin
56 v:= FDelphiControl.Cancel;
57 pPropBag.write( 'Cancel', v);
58 v:= FDelphiControl.Caption;
59 pPropBag.write( 'Caption', v);
60 v:= FDelphiControl.Cursor;
61 pPropBag.write( 'Cursor', v);
62 v:= FDelphiControl.default;
63 pPropBag.write( 'Default', v);
64 v:= FDelphiControl.DragCursor;
65 pPropBag.write( 'DragCursor', v);
66 v:= FDelphiControl.DragMode;
67 pPropBag.write( 'DragMode', v);
68 v:= FDelphiControl.Enabled;
69 pPropBag.write( 'Enabled', v);
70 v:= FDelphiControl.Font.Name;
71 pPropBag.write( 'FontName', v);
72 v:= FDelphiControl.Font.Size;
73 pPropBag.write( 'FontSize', v);
74 v:= FDelphiControl.Visible;
75 pPropBag.write( 'Visible', v);
76 Result := S_OK;
77 end;
Object Safety
-------------
Finally, in order for your control to work acceptably in a secure environment,
you will need to certify that it is "safe for scripting". A control that
is "safe for scripting", will not cause adverse effects no matter what
properties are set or methods are called on the object. Methods for
certifying that your control are safe for scripting are described in
the ActiveX SDK section entitled "Marking a control as safe".
[ed: I'll write a FAQ on this, too. These topics are all intertwined...]
|