现在网上有很多提供主页空间的站点,但是大部分低价位的站点只提供静态
HTML
文档的功能,不支持
ASP
、
PHP
等动态网页技术。如果您像在您的主页上放上您喜欢的文章,那么需要一个一个链接的做。如果您删除了某篇文章或者想添加某篇文章,那么需要做很多改动,牵一发而动全身。
凌科文章动态发布系统就是为你解决这个问题而开发的软件。使用本软件后您可以轻易生成下面效果的网页。
///////////////////////////////////
Delphi
的使用帮助文件
最后一篇情书
上一页
//////////////////////////////////
凌科文章动态发布预览
凌科文章动态新技术发
下一页
/////////////////////////////////
点击相应的文章标题(如
"
最后一篇情书
"
)就会弹出一个窗口显示这篇文章。
软件的界面如下:
这款软件有两项关键性技术:瘦客户端的数据库应用和网页分页显示技术。其中的瘦客户端的数据库应用在我的另一款软件《凌科网页精灵》的“程序自动升级”功能中也有所应用。
一、
瘦客户端的数据库应用
本软件的一个基本要求就是用户可是随时在工程添加、删除文章,并能将工程保存到文件中,并可以在以后打开工程文件后继续编辑工程。实现这个功能可以有很多中解决方案:
(
1
)
定义一个结构体
TariticleItem(
因为要将文章保存到
ListBox
的
Item
属性中,所以要用类来模拟结构体
)
:
TariticleItem = class
Public
Title: string;
Ariticle: string;
End;
将用户输入的标题和文章正文存储在一个
TariticleItem
,然后再调用
ListBox.Item.Add()
将此
TariticleItem
保存到
ListBox
中,在保存工程的时候遍历
ListBox
中每个项目然后保存到文件。在加载工程文件时也类似的遍历项目。
但是这样会使工作量变得很大,况且很有可能出现内存问题(我猜测的,没有实践),而且保存的工程文件格式也会很难确定。
(
2
)用
Access
的
MDB
数据库存储文章,通过
ADO
操作数据库。之所以选择
ADO
访问
Access
数据库而不使用
BDE
的原因就是
BDE
的配置十分麻烦,在这种小规模的程序中使用
BDE
有点恐怖。而
Access
的
ADO
驱动在
Win98
以上操作系统中一般都有安装,这样就免去了配置的麻烦。而且使用
TADOTable
或
TADOQuery
的
SaveToFile
和
LoadFromFile
方法也可以轻易实现数据导出
/
导入文件。但是为什么我们不使用它呢?因为“
Win98
以上操作系统”
“一般”都有安装,这就说明
Win95
的用户就不能使用本软件了(现在还是有很多
Win95
用户的),而且即使是
Win98
以上的系统也不能保证一定装有
ADO
驱动。
(
3
)使用
Delphi
中的
TclientDataSet
控件。
TClientDataSet
控件继承自
TDataSet,
具有所有数据集组件的基本功能,而且还有自己的很多很有用的功能,它是一款基于文件型数据存储和操作的控件,数据可以导出到文件中(支持
xml
、
cds
两种文件格式)。该控件封装了对数据进行操作处理的接口和功能
,
具有
ADO
的上述优点
,
基本上能满足单机
"
瘦
"
数据库应用程序的需要。
Delphi5
的用户在发布软件时只要同时发布
Midas.dll
就可以了,
Delphi6
、
Delphi7
的用户只要在工程文件中包含
MidasLib
单元,
Midas.dll
的功能就集成在应用程序中了(会使程序增大
200K
左右),成为真正的零配置软件。况且使用
TclientDataSet
控件,我们就可以使用数据敏感组件,我们又免去了处理将保持用户输入数据更新的问题。基于以上原因,我决定使用
TclientDataSet
控件。
如上图,在窗体中放入一个
TclientDataSet
控件提供数据、一个
TdataSource
控件、一个
TDBGrid
控件用来显示文章标题列表,一个
TDBEdit
控件显示文章标题,一个
TDBMemo
控件显示文章内容,并设定它们之间的关系。
在
TclientDataSet
组件上单击右键,选择“
Fields Editor
”
,
在弹出的字段编辑器中单击右键,选择“
New Field
”,建一个名为
Title
的
String
类型字段和名为
Article
的
Memo
类型字段。再在
TclientDataSet
组件上单击右键,选择“
Create DataBase
”。至此一个模拟数据库就建好了,您可以调用
TclientDataSet
的
Delete,Edit,Insert
等方法实现对数据库操作了,还可以调用
SaveToFile
、
LoadFromFile
方法保存、加载数据文件了。
二、网页分页显示技术
网页分页显示技术比较简单,我现在也说得口干舌躁了,先给出代码,你先自己分析一下吧!我将网页分页显示封装成了一个
TarticlePublisher
类,核心方法就是
MakePublish
方法,下面给出类的定义和
MakePublish
方法的代码。
TArticlePublisher = class(TObject)
private
FTitleWord: string;
FIndexWord: string;
FNumPerPage: Integer;
FPageCount: Integer;
FDataSet: TDataSet;
FOutPutDir: string;
FLinkFont: TFont;
FUseDefFont: Boolean;
FIndexTemplete: string;
FLinkCSS: string;
procedure FSetNumPerPage(AValue: Integer);
procedure FSetLinkFont(AFont: TFont);
procedure FSetUseDefFont(AValue: Boolean);
procedure FSetIndexTemplete(AValue: string);
procedure FSetLinkCSS(AValue: string);
protected
function AddFontToText(AText: string; AFont: TFont): string;virtual;
public
//
输出文章文件的文件名的开始几个字符,默认为
'art'
property TitleWord: string read FTitleWord write FTitleWord;
//
输出索引文件的文件名的开始几个字符,默认为
'ind'
property IndexWord: string read FIndexWord write FIndexWord;
//
每页的条目数,默认为
30
property NumPerPage: Integer read FNumPerPage write FSetNumPerPage;
//
总页数,只读
property PageCount: Integer read FPageCount;
property DataSet: TDataSet read FDataSet write FDataSet;
//
输出路径
property OutPutDir: string read FOutPutDir write FOutPutDir;
//
超链接字体
property LinkFont: TFont read FLinkFont write FSetLinkFont;
//
使用默认字体
property UseDefFont: Boolean read FUseDefFont write FSetUseDefFont;
//
索引页模板
property IndexTemplete: string read FIndexTemplete write FSetIndexTemplete;
//
超链接
CSS
样式
property LinkCSS: string read FLinkCSS write FSetLinkCSS;
constructor Create;
procedure MakePublish;//
开始转化
end;
procedure TArticlePublisher.MakePublish;
var
LCount: Integer;
i, j: Integer;
LAriticleSL: TStringList;//
保存文章用
LStrList: TStringList;//
保存动态页面用
LTempStr: string;
begin
LCount := DataSet.RecordCount;
DataSet.First;
LAriticleSL := TStringList.Create;
for i := 0 to LCount - 1 do
begin
LAriticleSL.Clear;
LAriticleSL.Add(DataSet.FieldByName('Article').AsString);
LAriticleSL.SaveToFile(Format('%s%s%d.htm',[OutPutDir,TitleWord,i]));
DataSet.Next;
end;
LAriticleSL.Free;
if LCount mod NumPerPage = 0 then
FPageCount := LCount div NumPerPage
else
FPageCount := (LCount div NumPerPage) + 1;
LStrList := TStringList.Create;
DataSet.First;
for i := 1 to PageCount do
begin
LStrList.Clear;
for j := 0 to NumPerPage - 1 do
begin
if DataSet.Eof then break;
LStrList.Add('<p>');
if LinkCSS = '' then
LStrList.Add('<a href='+QuotedStr(TitleWord+IntToStr((i-1)*NumPerPage+j)+'.htm')+
' target=_blank>'+AddFontToText(DataSet.FieldByName('Title').AsString,LinkFont)+'</a>')
else
LStrList.Add('<a href='+QuotedStr(TitleWord+IntToStr((i-1)*NumPerPage+j)+'.htm')+
' target=_blank style="'+LinkCSS+'">'+
AddFontToText(DataSet.FieldByName('Title').AsString,LinkFont)+'</a>');
LStrList.Add('</p>');
DataSet.Next;
end;
if i <> 1 then
LStrList.Add('<a href='+QuotedStr(IndexWord+IntToStr(i-1)+'.htm')+
'>'+AddFontToText('
上一页
', LinkFont)+'</a>');
if i <> PageCount then
LStrList.Add('<a href='+QuotedStr(IndexWord+IntToStr(i+1)+'.htm')+
'>'+AddFontToText('
下一页
', LinkFont)+'</a>');
if IndexTemplete <> '' then
begin
LTempStr := AnsiReplaceText(IndexTemplete, INDEXTEMPLETESIGN, LStrList.Text);
LStrList.Text := LTempStr;
end;
LStrList.SaveToFile(Format('%s%s%d.htm',[OutPutDir,IndexWord,i]));
end;
LStrList.Free;
end;
二、
其他经验
1
、
将字体
Tfont
保存到
Ini
文件的方法。
因为
vcl
的
TFont
只是对
windows FONT
的封装,它内部所存储的数据只是为了使用户方便操作
windows
的
font
而定义的一些私有状态数据,可以说这些数据与真正
windows font
中的数据风马牛不相及,你保存、恢复这些数据根本没用(即使正确地恢复了这些数据也只会得到一个错误的
TFont
对象)
要保存
TFont
的内容并能正确恢复最简单的方法是保存
TFont.Handle
所对应
font
的具体结构,恢复时根据这个结构创建一个
HFONT
然后赋值给
TFont.Handle
即可。
保存字体:
var
LFont: TFont;
LLF: TLogFont;
LMS: TMemoryStream;
…………
begin
…………
LFont := Edit1.Font;
GetObject(LFont.Handle, SizeOf(LLF), @LLF);
LMS.Write(LLF, SizeOf(LLF));
LMS.Position := 0;//
不能丢了这句
LIni.WriteBinaryStream('Config', 'LinkFont', LMS);
…………
end;
加载字体:
var
LFont: TFont;
LLF: TLogFont;
LMS: TMemoryStream;
Begin
…………
LIni.ReadBinaryStream('Config', 'LinkFont', LMS);
LMS.Position := 0;//
不能丢了这句
LMS.Read(LLF, SizeOf(LLF));
LFont.Handle := CreateFontIndirect(LLF);
…………
End;
但是这样还有一个问题就是字体中的字体名、字体大小等属性都能正确的保存,但是字体的颜色却没有保存。分析
TlogFont
发现原来系统原生对象
TlogFont
中并没有颜色这个字段值,字体颜色是
VCL
封装上去的,所以需要另外再在
Ini
文件增加一个字体颜色的项目。
2
、为一段文字加上
HTML
字体
function AddFontToText(AText: string; AFont: TFont): string;
Const
LTmpl = '<font face="%s" size="%d" color="#%s">%s</font>';//
模板
var
LColorStr: string;
LR, LG, LB: Integer;
tmp: string;
begin
LR := GetRValue(AFont.Color);
LG := GetGValue(AFont.Color);
LB := GetBValue(AFont.Color);
LColorStr := Format('%x%x%x',[LR,LG,LB]);
tmp := Format(LTmpl,[AFont.Name, AFont.Size, LColorStr,AText]);
if fsBold in AFont.Style then
tmp := Format('<b>%s</b>',[tmp]);
if fsItalic in AFont.Style then
tmp := Format('<i>%s</i>',[tmp]);
if fsUnderline in AFont.Style then
tmp := Format('<u>%s</u>',[tmp]);
if fsStrikeOut in AFont.Style then
tmp := Format('<StrikeOut>%s</StrikeOut>',[tmp]);
result := tmp;
end;
本文出自 “CowNew开源团队” 博客,转载请与作者联系!