Internet Express adds a whole new dimension to Delphi's
Internet development capabilities. By
allowing you to hook data to HTML controls, you can easily build powerful,
database-driven web pages. InternetExpress includes a large collection of classes to accomplish
this, but the base component for all of it is the TMidasPageProducer.
You can download the source code for this article from
CodeCentral.
TMidasPageProducer
TMidasPageProducer is the heart of InternetExpress, and all
InternetExpress components are embedded within it. It is the component used to manage all the custom HTML that
InternetExpress components emit. To
fully take advantage of InternetExpress, you will want to create a
TMidasPageProducer to set up the basic template for each page on your site.
This means, of course, inheriting from TMidasPageProducer. Once you have done that, you can use that
template for any or all the pages in your new site, giving it a consistent look
throughout. In addition, understanding
how TMidasPageProducer works is key to understanding how to build components
that fit into it. This article will
build a TMidasPageProducer descendent that will automatically insert
<META> tags into the <HEAD> tag of your HTML document.
Descending from TMidasPageProducer
TMidasPageProducer descends from WebBroker's TPageProducer,
with a couple of classes (TComponentPageProducer and TPageItemsProducer) in
between. TMidasPageProducer handles the
task of organizing and outputting the HTML produced by the various classes and
components installed within it. It also
does a lot of the work of managing the XML that it receives from the XMLBroker
and allows you to process that XML data if you like before it gets sent out to
the components. In addition, it manages
all the Javascript that any of the InternetExpress components might use,
allowing you to concentrate on the code and not the HTML.
Note:
TMidasPageProducer will function just like a regular TPageProducer, so
you can adjust the HTMLDoc property and use the OnHTMLTag just as always.
It is likely that you won't want to do that, but you can.
GetDefaultTemplate is a key function in TMidasPageProducer. It gets the basic
HTML code and pre-defined imbedded custom tags that let TMidasPageProducer
provide it's content. It is implemented
as follows:
Listing 1
function TCustomMidasPageProducer.GetDefaultTemplate: string;
begin
Result := Format('<HTML>'#13#10 +
'<HEAD>'#13#10 +
'</HEAD>'#13#10 +
'<BODY>'#13#10 +
'<#%0:s><#%1:s><#%2:s><#%3:s><#%4:s>'#13#10 +
'</BODY>'#13#10 +
'</HTML>'#13#10, [sIncludesTag, sStylesTag,
sWarningsTag, sFormsTag, sScriptTag]);
end;
GetDefaultTemplate produces a string using the Format
function. It uses the constants in the array of constants to build a skeleton
HTML document the body of which is filled with nothing but custom tags.
Each of the custom tags represents the different portions of the
resulting HTML document. Drop a TMidasPageProducer on a form, and look at the HTMLDoc
property, and you will see the results:
Listing 2
<HTML>
<HEAD>
</HEAD>
<BODY>
<#INCLUDES><#STYLES><#WARNINGS><#FORMS><#SCRIPT>
</BODY>
</HTML>
The <#INCLUDES> tag is where any references to included files will be added.
The <#STYLES> tag will be filled with
style information. The <#WARNINGS> tag is actually used only at
design-time to send messages to the programmer about errors in the linkages of
the various components within the TMidasPageProducer. <#FORMS> will be replaced
with the main part of the
document and contain all the HTML that will be seen by the user.
Finally, <#SCRIPT> is where all the Javascript produced by the components will be placed.
The GetDefaultTemplate
method is virtual, so as you will see, you can change the above default
template code, and add anything you like, including additional custom tags and
HTML. However, you should include all
the tags seen above. There's nothing stopping you from adding additional tags,
but you shouldn't take any of them away.
TMidasPageProducer uses
a helper class, TMidasPageElements, to handle the replacement of the default
custom tags seen above. You can, and
likely will, descend from this to provide your own custom handling of these
tags. You can tell your
TMidasPageProducer about your new TMidasPageElements descendent with the
CreatePageElements method, and it will use the new class to provide HTML.
You can add fields to the new class as well,
thus handling any custom tags that you added to the default HTML template in
GetDefaultTemplate.
TMidasPageElements has one method, BodyContent, which produces the HTML for the class.
You can override this method and produce your own content.
TMetaMidasPageProducer
Many search engines make use of the HTML feature
<META> tags. Meta tags provide
information about the site including the author, the name of the site, and the
type of content in site among other things.
It is generally a good idea to add <META> tags to your site, and
TMetaMidasPageProducer makes that easy.
TMetaMidasPageProducer adds properties that you can fill in
to automatically insert <META> tags into your HTML documents. It does this by first declaring a class,
TMetaTags, which holds all the information you can add to your page. TMetaTags knows how to produce the HTML that
the TMetaMidasPageProducer needs. As a
published property of the TMetaMidasPageProducer, it shows up in the Object
Inspector where you can change the properties as you like.
Note: TMetaTags
descends from TPersistent, and it is thus streamable. However, in order to get it to work properly in the Object
Inspector, it needs its own property editor, which is included with the code
for this article. In addition, you can
add other string properties to the class if you like.
Simply name them the same as the tag name you want added, and
they will automatically be included in the code.
TMetaTags uses RTTI to find all the string properties and turn
them into <META> tags.
The TMetaTags class is declared as follows:
type
TMetaTags = class(TPersistent)
private
FIdentifier: string;
FTitle: string;
FDescription: string;
FCopyright: string;
FKeywords: string;
FAuthor: string;
procedure SetAuthor(const Value: string);
procedure SetCopyright(const Value: string);
procedure SetDescription(const Value: string);
procedure SetIdentifier(const Value: string);
procedure SetKeywords(const Value: string);
procedure SetTitle(const Value: string);
published
function GetMetaTagsHTML: string;
property Author: string read FAuthor write SetAuthor;
property Description: string read FDescription write SetDescription;
property Keywords: string read FKeywords write SetKeywords;
property Copyright: string read FCopyright write SetCopyright;
property Title: string read FTitle write SetTitle;
property Identifier: string read FIdentifier write SetIdentifier;
end;
The key method is the GetMetaTagsHTML, which is implemented
as follows:
Listing 4
function TMetaTags.GetMetaTagsHTML: string;
var
TempStr: string;
i: Integer;
PropList: PPropList;
PropCount: Integer;
PropName, PropValue: String;
begin
TempStr := '';
New(PropList);
PropCount := GetPropList(Self.ClassInfo, [tkString, tkLString, tkWString], PropList);
for i := 0 to PropCount - 1 do
begin
PropName := PropList^[i].Name;
PropValue := GetStrProp(Self, PropList^[i]);
if PropValue <> '' then
begin
TempStr := TempStr + BuildMetaTag(PropName, PropValue);
end;
end;
Dispose(PropList);
Result := TempStr;
end;
Note that it uses RTTI to find all the string properties and
their corresponding values, and turns them into <META> tags.
This means that you can add <META>
tags of your choosing to the TMetaTags class declaration, and they will
automatically be added to the resulting HTML code, without having to change any
more code.
As mentioned above, TMetaMidasPageProducer overrides
GetDefaultTemplate. The new version is:
Listing 5
const
MetaHTML = '<HTML>'#13#10 +
'<HEAD>'#13#10 +
'<#META>' +
'</HEAD>'#13#10 +
'<BODY>'#13#10 +
'<#BODYELEMENTS>'#13#10 +
'</BODY>'#13#10 +
'</HTML>'#13#10;
function TMetaMidasPageProducer.GetDefaultTemplate: string;
begin
Result := MetaHTML;
end;
You will notice that I have added an additional tag inside
the <HEAD> portion of the document, <#META>.
This custom tag will be replaced with the
<META> tag information produced by the TMetaTags class.
Of course, this tag has to be handled somewhere, and that is
where the DoTagEvent method comes in.
This overridden, virtual method will pass all the tags, save one, on to
the inherited method. The <#META>
tag, however, is replaced with the <META> tags text from our trusty
TMetaTags class. The method is
implemented as follows:
Listing 6
procedure TMetaMidasPageProducer.DoTagEvent(Tag: TTag;
const TagString: string; TagParams: TStrings; var ReplaceText: string);
begin
if (Tag = tgCustom) and (CompareText(TagString, 'META') = 0) then
begin
ReplaceText := MetaTags.GetMetaTagsHTML;
Exit;
end;
inherited DoTagEvent(Tag, TagString, TagParams, ReplaceText);
end;
When you drop a TMetaMidasPageProducer on your application,
you can set the values for the <META> tags, and the component will take
care of the rest. The TMetaTags class knows how to produce the HTML for the
<META> tags, and does so in the GetMetaTagsHTML method.
From here, you can descend from TMetaMidasPageProducer to
create more elaborate pages. You know
how to override the GetDefaultTemplate method to control what goes into the new
page, and you can handle your own custom tags in an overridden DoTagEvent
method.
This paper was adapted from my presentation that will be
given at the Borland Conference 2000
in San Diego in July.
For a fuller treatment of this topic, and
for a look at how to build classes and components that work with
TMidasPageProducer, attend the conference and sit in on my presentation,
"Building InternetExpress Components".
About the Author
Nick Hodges recently separated from the Navy and now works happily at
Xapware Technologies,
where he wears whatever he wants to work. He can be reached at
nick@xapware.com.
Connect with Us