DELPHI技术

博客园 首页 新随笔 联系 订阅 管理
  37 Posts :: 41 Stories :: 50 Comments :: 0 Trackbacks

公告

2005年12月9日 #

 How to get File Summary Info
On Windows 2000 you can right-click in Explorer to get the file properties on any file and can associate summary information to any type of files, including even text files.

For Word or Excel documents (compound files) the summary information is a part of document itself. For other files the way of storing additional information are different. This feature are only available on volumes formatted with NTFS. The NTFS implementation stores property sets in alternate streams of an NTFS file. The alternate streams must be copied when the main file is copied. However, not all file systems support such streams. For example, if an NTFS file with property sets is copied to a FAT volume, only the data in the file is copied; the property set is lost.

First thing you probably want do is to detect whether the current volume is NTFS:

// IsNTFS() - Verifies whether the file's volume is NTFS
function IsNTFS(AFileName : string) : boolean;
var
fso, drv : OleVariant;
begin
IsNTFS := False;
fso := CreateOleObject('Scripting.FileSystemObject');
drv := fso.GetDrive(fso.GetDriveName(AFileName));
 if drv.FileSystem = 'NTFS' then
  IsNTFS := True;
end;

But how to read these properties? Is it really nessesary to work with a streams? No, NTFS file system 5.0 provides an implementation of IPropertySetStorage interface for files on an NTFS volume when the files themselves are not compound files. To get a pointer to the NTFS implementation of IPropertySetStorage, we have to call the StgCreateStorageEx function:

function StgOpenStorageEx (
 const pwcsName : POleStr;  //Pointer to the path of the
                            //file containing storage object
 grfMode : LongInt;         //Specifies the access mode for the object
 stgfmt : DWORD;            //Specifies the storage file format
 grfAttrs : DWORD;          //Reserved; must be zero
 pStgOptions : Pointer;     //Address of STGOPTIONS pointer
 reserved2 : Pointer;       //Reserved; must be zero
 riid : PGUID;              //Specifies the GUID of the interface pointer
 out stgOpen :              //Address of an interface pointer
 IStorage ) : HResult; stdcall; external 'ole32.dll';

All Microsoft Windows 2000 applications should use this new function, StgOpenStorageEx, instead of StgOpenStorage, to take advantage of the enhanced Windows 2000 Structured Storage features.

The implementation of IPropertySetStorage on NTFS file system is similar with compound file implementation and available only on Windows 2000. Windows 95 and Windows NT 4.0 and earlier versions cannot access this interface. However, you cannot obtain the NTFS implementation of IPropertySetStorage for a compound file. When opening a compound file with StgOpenStorage, specifying the STGFMT_FILE enumeration value results in an error.

The next function dumps all properties of the specific file. By changing the STGFMT_FILE flag in the StgOpenStorageEx call to STGMT_ANY you can open a Structured Storage property set or an NTFS file system property set.

function GetFileSummaryInfo(const FileName: WideString): String;

const
FmtID_SummaryInformation: TGUID =     '{F29F85E0-4FF9-1068-AB91-08002B27B3D9}';
FMTID_DocSummaryInformation : TGUID = '{D5CDD502-2E9C-101B-9397-08002B2CF9AE}';
FMTID_UserDefinedProperties : TGUID = '{D5CDD505-2E9C-101B-9397-08002B2CF9AE}';
IID_IPropertySetStorage : TGUID =     '{0000013A-0000-0000-C000-000000000046}';

const
STGFMT_FILE = 3; //Indicates that the file must not be a compound file.
                 //This element is only valid when using the StgCreateStorageEx
                 //or StgOpenStorageEx functions to access the NTFS file system
                 //implementation of the IPropertySetStorage interface.
                 //Therefore, these functions return an error if the riid
                 //parameter does not specify the IPropertySetStorage interface,
                 //or if the specified file is not located on an NTFS file system
                 //volume.

STGFMT_ANY = 4; //Indicates that the system will determine the file type and
                //use the appropriate structured storage or property set
                //implementation.
                //This value cannot be used with the StgCreateStorageEx function.


// Summary Information
 PID_TITLE        = 2;
 PID_SUBJECT      = 3;
 PID_AUTHOR       = 4;
 PID_KEYWORDS     = 5;
 PID_COMMENTS     = 6;
 PID_TEMPLATE     = 7;
 PID_LASTAUTHOR   = 8;
 PID_REVNUMBER    = 9;
 PID_EDITTIME     = 10;
 PID_LASTPRINTED  = 11;
 PID_CREATE_DTM   = 12;
 PID_LASTSAVE_DTM = 13;
 PID_PAGECOUNT    = 14;
 PID_WORDCOUNT    = 15;
 PID_CHARCOUNT    = 16;
 PID_THUMBNAIL    = 17;
 PID_APPNAME      = 18;
 PID_SECURITY     = 19;

 // Document Summary Information
 PID_CATEGORY     = 2;
 PID_PRESFORMAT   = 3;
 PID_BYTECOUNT    = 4;
 PID_LINECOUNT    = 5;
 PID_PARCOUNT     = 6;
 PID_SLIDECOUNT   = 7;
 PID_NOTECOUNT    = 8;
 PID_HIDDENCOUNT  = 9;
 PID_MMCLIPCOUNT  = 10;
 PID_SCALE        = 11;
 PID_HEADINGPAIR  = 12;
 PID_DOCPARTS     = 13;
 PID_MANAGER      = 14;
 PID_COMPANY      = 15;
 PID_LINKSDIRTY   = 16;
 PID_CHARCOUNT2   = 17;

var
 I: Integer;
 PropSetStg: IPropertySetStorage;
 PropSpec: array of TPropSpec;
 PropStg: IPropertyStorage;
 PropVariant: array of TPropVariant;
 Rslt: HResult;
 S: String;
 Stg: IStorage;
 PropEnum: IEnumSTATPROPSTG;
 HR : HResult;
 PropStat: STATPROPSTG;
 k : integer;

function PropertyPIDToCaption(const ePID: Cardinal): string;
begin
 case ePID of
   PID_TITLE:
     Result := 'Title';
   PID_SUBJECT:
     Result := 'Subject';
   PID_AUTHOR:
     Result := 'Author';
   PID_KEYWORDS:
     Result := 'Keywords';
   PID_COMMENTS:
     Result := 'Comments';
   PID_TEMPLATE:
     Result := 'Template';
   PID_LASTAUTHOR:
     Result := 'Last Saved By';
   PID_REVNUMBER:
     Result := 'Revision Number';
   PID_EDITTIME:
     Result := 'Total Editing Time';
   PID_LASTPRINTED:
     Result := 'Last Printed';
   PID_CREATE_DTM:
     Result := 'Create Time/Date';
   PID_LASTSAVE_DTM:
     Result := 'Last Saved Time/Date';
   PID_PAGECOUNT:
     Result := 'Number of Pages';
   PID_WORDCOUNT:
     Result := 'Number of Words';
   PID_CHARCOUNT:
     Result := 'Number of Characters';
   PID_THUMBNAIL:
     Result := 'Thumbnail';
   PID_APPNAME:
     Result := 'Creating Application';
   PID_SECURITY:
     Result := 'Security';
   else
     Result := '$' + IntToHex(ePID, 8);
   end
end;

begin
 Result := '';
try
 OleCheck(StgOpenStorageEx(PWideChar(FileName),
 STGM_READ or STGM_SHARE_DENY_WRITE,
 STGFMT_FILE,
 0, nil,  nil, @IID_IPropertySetStorage, stg));

 PropSetStg := Stg as IPropertySetStorage;

 OleCheck(PropSetStg.Open(FmtID_SummaryInformation,
    STGM_READ or STGM_SHARE_EXCLUSIVE, PropStg));

 OleCheck(PropStg.Enum(PropEnum));
 I := 0;

 hr := PropEnum.Next(1, PropStat, nil);
  while hr = S_OK do
  begin
    inc(I);
    SetLength(PropSpec,I);
    PropSpec[i-1].ulKind := PRSPEC_PROPID;
    PropSpec[i-1].propid := PropStat.propid;
    hr := PropEnum.Next(1, PropStat, nil);
 end;

 SetLength(PropVariant,i);
 Rslt := PropStg.ReadMultiple(i, @PropSpec[0], @PropVariant[0]);

 if Rslt =  S_FALSE then Exit;

 for k := 0 to i -1 do
  begin
    S := '';
    if PropVariant[k].vt = VT_LPSTR then
      if Assigned(PropVariant[k].pszVal) then
       S := PropVariant[k].pszVal;

    S := Format(PropertyPIDToCaption(PropSpec[k].Propid)+ ' %s',[s]);
   if S <> '' then Result := Result + S + #13;
 end;
 finally
 end;
end;
posted @ 2005-12-09 13:08 DELPHI技术 阅读(837) 评论(0) 编辑

2005年11月24日 #

begin
with Table1 do
begin
  Active := False;
  DatabaseName := 'DOCTOR';
  TableType := ttParadox;
  TableName := 'DOCTORINF23';
  if not Table1.Exists then begin
     with FieldDefs do begin
        Clear;
        with AddFieldDef do begin
            Name := '姓名';
            DataType := ftString;
            Required := True;
            Size := 10;
        end;
        with AddFieldDef do begin
             Name := '年龄';
             DataType := ftInteger;
        end;//建立字段定,利用AddFieldDef方法添加一个新的TFieldDef对象
        with AddFieldDef do begin
            Name := '职称';
            DataType := ftString;
            Required := True;
            Size := 10;
        end;
     end;
     with IndexDefs do begin
          Clear;
          with AddIndexDef do begin
          Name := 'MYINDEX';
          Fields := '姓名';
          Options := [ixPrimary];
          end;
     end;  //建立索引
  end;
  CreateTable;
end;
    //Table1.Append ;
    Table1.Open;
    Table1.Edit;
    Table1.FieldByName('姓名').AsString:='刘延';
    Table1.FieldByName('年龄').AsInteger:=22 ;
    Table1.FieldByName('职称').AsString:='医师';
    Table1.Append;
    Table1.Edit;
    Table1.FieldByName('姓名').AsString:='杨晓';
    Table1.FieldByName('年龄').AsInteger:=25 ;
    Table1.FieldByName('职称').AsString:='医师';
    DBGrid1.DataSource:=DataSource1;
    Table1.Active :=True;
end;

posted @ 2005-11-24 08:58 DELPHI技术 阅读(730) 评论(0) 编辑

2005年11月23日 #

    Enlib3.0组件包安装成功后,在系统的组件面板中会显示“enlib”组件包标签(如图1),添加DBGridEh到窗体的方法与其它组件一样。在窗体中添加该组件后,请跟我一起来实现图2的一些特殊效果,具体属性设置请参考属性表的说明。

A、定制标题行
 1、制作复杂标题行
    标题行可设为2行以上高度,并可以为多列创建一个共同的父标题行。为实现这个效果,需在各个列标题属性中以“|”分隔父标题和子标题,如办公用品包括代码和名称两部分,具体属性设置如下:

usemultititile=true;
titlelines=2
DBGridEh.Columns[0].Title.Caption := '办公用品|代码';
DBGridEh.Columns[1].Title.Caption := '办公用品|名称';

 2、标题行显示图片
    实现图2中的购买人标题行显示效果。首先添加一个imagelist组件img1并在其中添加一组bmp,ico格式的图片。然后将DBGridEh的TitleImages设置为img1.最后在需要显示图片的列标题的imageindex中设置需要显示的img1中图片的序号。按F9执行一下程序,是不是很酷!

 3、自动显示标题行的升降排序标志符(▽降序△升序)并做相应排序
    DBGridEh组件可以在标题行单元格中显示小三角形升、降排序标志符图片,在运行时可点击标题行,图片自动切换并做相应排序。具体属性设置如下:

OptionsEh=dghAutoSortMarking
Column.Title.TitleButton=true

SortMarkedColumns 为当前排序列可在运行时使用.
然后在该列的ontitleclick事件中添加代码:
procedure TForm_Query.DBGridEh1TitleBtnClick(Sender: TObject; ACol: Integer; Column: TColumnEh);
var
  sortstring:string; //排序列
begin
  //进行排序
  with Column do
  begin
    if FieldName = '' then
      Exit;
    case Title.SortMarker of
      smNoneEh:
      begin
        Title.SortMarker := smDownEh;
        sortstring := Column.FieldName + ' ASC';
      end;
      smDownEh: sortstring := Column.FieldName + ' ASC';
      smUpEh: sortstring := Column.FieldName + ' DESC';
    end;
  //进行排序
    try
      dataset.Sort := sortstring //dataset为实际数据集变量名
    except
    end;
  end;
end;

切记lookup型字段不可做上述设置,否则系统会提示错误。

    另外,组件说明书中提到不需要编写代码即可自动排序,但是不编写代码自动排序方法我还没找到,有知道的朋友烦请告诉我一声啊!让我也对程序代码进行“减肥”。

 

B、定制表格底部(footer)区域的汇总统计行
    DBGridEh 组件可以在表格底部显示汇总行,如记录数合计、列字段累加和等信息。在FooterRowCount中设置底部显示的行数;然后在Footers 编辑器中添加一个或多个显示列,显示列可以是字段值累加和、记录数合计、字段值或静态文件等集合类型,可以在设计时在ValueType属性中设置,也可在运行时通过设置Footers[i].ValueType指定其类型。其含义见下表:

    切记设置DBGridEh.SumList.Active 为 True,才会进行汇总统计运算。需注意的是,如显示类型为不是当前列的累加和,则需在fieldname属性中指定汇总列,其它类型则无此要求。

 

C、定制表格数据单元外观
 1、根据不同字段值显示相应的小图片
    如根据库存材料的不同状态在数据单元格中显示相应图片,具体设置如下:
    添加一个imagelist组件img1并在其中添加一组bmp,ico格式的图片。然后将需要显示图片的列的imagelist属性设置为img1;在keylist属性中添加实际数据存储值,一行为一个值,切记一定要与imagelist中图片顺序一一对应,否则会张冠李戴,面目全非。还可在picklist中添加提示信息,也要求是一行为一个值,并设tooltip为true,那么,运行时当鼠标移动到该数据单元格时在显示图片的同时还显示提示信息,怎么样,功能够强大吧!可使用空格键或鼠标切换下一张图片,图片切换的同时也改变了实际存储数据值。也可通过shift+空格或鼠标切换为上一张图片。这样就实现了上下两个方向图片切换。

 2、显示检查框(checkbox)外观
    对于Boolean型字段值在dbgrideh组件中自动显示为检查框。通常情况下我们需将非Boolean型字段值也此外观显示,如性别字段为字符型,字段值为“男性”时为选中,“女性”时为未选中。需要在keylist编辑器中设置实际存储数据值,第一行为选中时的值“1”,第二行为未选中的值“0”,第三行为其它值“2”,支持三态显示。

 3、显示单、多列下拉列表
    根据单元格字段值显示与其相关的其它表字段内容,如部门代码字段显示为部门名称。首先需在当前表中新建立一个lookup型字段,设置好关联表的字段和返回字段。多列下拉列表需在单列基础上做进一步设置,在LookupDisplayFields中以“;”号将关联表中多个字段分隔开,而且返回字段必须作为其中的第一项。具体设置如下:

dropdownshowtitles=true
dropdownsizing=true
dropdownwidth=-1

    例:当前表中只有部门代码无部门名称列,需与部门表建立关联,当点击单元格时以部门代码、部门名称两列下拉列表形式显示。

 4、显示日历下拉列表
    Date 和 DateTime类型字段值均可以此形式显示。外观与编辑框无异,当点击该单元格时,右侧会出现“▽”符号,点击之即可出现日历下拉列表。有时不希望出现日历下拉列表,只需设置Column.ButtonStyle属性为 cbsNone即可,此方法同样适用于其它组件不以特殊外观显示的情况。

 5、3D或平面外观效果
    设置OptionsEh属性 中fixed, frozen, footer 和 data rows等属性表格外观为3D效果,设置flat为true则为平面外观效果.

 6、锁定多列不滚动
    当表格水平方向信息在一屏幕显示不下时,此项功能非常有用。例如,工资表格中包含姓名、基本工资、绩效工资等信息一屏幕显示不下,需要通过移动水平滚动条显示下一屏信息。如果不锁定关键字段列如姓名,则移动到下一屏时就不知道此条记录对应的姓名。因此,在实际应用中经常需锁定多列不滚动。

    例:姓名字段为表格第二列,则设置FrozenCols=2.这样当一屏幕显示不下,通过移动水平滚动条显示下一屏信息时,表格前两列不滚动,作为参照列。

D、导入/导出数据
    导入/导出数据在实际处理过程中是比较烦琐的。但是Enlib3.0提供了一系列函数让你轻松实现此功能,而且支持的文件格式很多:Text, Csv, HTML, RTF, XLS 和内部数据格式。除此之外,还可对任意选择的数据区域进行操作。函数如下:

Pascal: SaveDBGridEhToExportFile(TDBGridEhExportAsText,DBGridEh1,'c:\temp\file1.txt',False);

C++: SaveDBGridEhToExportFile(__classid(TDBGridEhExportAsText),DBGridEh1,"c:\\temp\\file1.txt",false);

说明:其中false参数表示导出的是选中的局部数据区域数据,true则为整个表格数据。

   例:将当前表格中数据导出为EXCEL等格式文件。
    在窗体中添加一个SaveDialog组件和“导出”按钮B_exp,在“导出”按钮的click事件中添加如下代码:

procedure TForm1.B_expClick(Sender: TObject);
var
  ExpClass:TDBGridEhExportClass;
  Ext:String;
begin
  SaveDialog1.FileName := 'file1';
  if (ActiveControl is TDBGridEh) then
    if SaveDialog1.Execute then
    begin
      case SaveDialog1.FilterIndex of
        1: begin ExpClass := TDBGridEhExportAsText; Ext := 'txt'; end;
        2: begin ExpClass := TDBGridEhExportAsCSV; Ext := 'csv'; end;
        3: begin ExpClass := TDBGridEhExportAsHTML; Ext := 'htm'; end;
        4: begin ExpClass := TDBGridEhExportAsRTF; Ext := 'rtf'; end;
        5: begin ExpClass := TDBGridEhExportAsXLS; Ext := 'xls'; end;
      else
        ExpClass := nil; Ext := '';
    end;
    if ExpClass <> nil then
    begin
      if UpperCase(Copy(SaveDialog1.FileName,Length(SaveDialog1.FileName)-2,3)) <> UpperCase(Ext) then
        SaveDialog1.FileName := SaveDialog1.FileName + '.' + Ext;
      SaveDBGridEhToExportFile(ExpClass,DBGridEh1,SaveDialog1.FileName,False);
      //其中false为局部数据
    end;
  end;
end;

E、将存在的DBGrid组件转换为DBGridEh组件.
    通过笔者上述介绍,想必你已经对Enlib组件包产生好感而且越越欲试了,那就赶快下载使用吧。但是,使用一段时间并且喜欢上它后,你又有新的问题产生了,那就是为了保持界面风格一致,能否将已经开发完成的应用程序中的DBGrid组件能否转换为DBGridEh组件,进行一次彻底革命?答案是肯定的。尽管DBGridEh并不是继承于CustomDBGrid组件, 但是DBGridEh和DBGrid它们之间有许多相同之处.因此可以相互转换。

具体步骤如下:
 1、在Delphi IDE下打开TDBGrid组件.
 2、通过组合键Alt-F12将form 以文本方式显示;
 3、将所有TDBGrid 对象名改变为 TDBGridEh对象名,如:DBGrid1: TDBGrid改为 DBGrid1: TDBGridEh;
 4、再次通过组合键Alt-F12将文本方式恢复为form 显示;
 5、将form各相关事件中定义的所有TDBGrid改为TDBGrideh,如DBGrid1: TDBGrid改为DBGrid1: TDBGridEh;
 6、重新编译应用程序。

    以上只是本人在实际程序开发过程中使用dbgrideh组件的一些体会,当然其功能还远不止这些。欢迎朋友与我做进一步交流。

posted @ 2005-11-23 09:16 DELPHI技术 阅读(5022) 评论(1) 编辑

一、打印dbgrid数据:
//==============================================================================
//打印DBGrid中的所有数据********************************************************
//==============================================================================
procedure DBGridPrint(DBGrid: TDBGrid; Title: string);
var PrintDialog: TPrintDialog;
RowHeight, Temp_X, Temp_Y, PageEdgeX, PageEdgeY, PixelsPerInchX, PixelsPerInchY: integer;
TempStr: string;
Scale: Double;
Rect: TRect;
//==============================================================================
//1.输出标题********************************************************************
//==============================================================================
procedure Print_Title;
begin
Rect := Bounds(0,0,Printer.PageWidth,PageEdgeY);
Printer.Canvas.Font.Name := '楷体_GB2312';
Printer.Canvas.Font.Style := Printer.Canvas.Font.Style + [fsBold];
Printer.Canvas.Font.Size := 20;
DrawText(Printer.Canvas.Handle,PChar(Title),Length(Title),Rect,DT_CENTER or DT_VCENTER or DT_SINGLELINE);
Printer.Canvas.Rectangle(PageEdgeX, PageEdgeY, Printer.PageWidth - PageEdgeX, PageEdgeY + 1);
end;





//==============================================================================
//2.输出列头********************************************************************
//==============================================================================
procedure Print_Column;
var j: integer;
begin
Printer.Canvas.Font.Name := '黑体';
Printer.Canvas.Font.Size := 9;
Temp_X := PageEdgeX;
Temp_Y := PageEdgeY;
//========================================================================
for j:=1 to DBGrid.Columns.Count do
begin
if not DBGrid.Columns[j-1].Visible then Continue;
//======================================================================
TempStr := DBGrid.Columns[j-1].Title.Caption;
Rect := Bounds(Temp_X, Temp_Y, Trunc(DBGrid.Columns[j-1].Width*Scale), RowHeight);
case DBGrid.Columns[j-1].Field.Alignment of
//====================================================================
//case.1.居中*********************************************************
//====================================================================
taCenter: DrawText(Printer.Canvas.Handle,PChar(TempStr),Length(TempStr),Rect,DT_CENTER or DT_VCENTER or DT_SINGLELINE);
//====================================================================
//case.2.居左*********************************************************
//====================================================================
taLeftJustify: DrawText(Printer.Canvas.Handle,PChar(TempStr),Length(TempStr),Rect,DT_LEFT or DT_VCENTER or DT_SINGLELINE);
//====================================================================
//case.3.居右*********************************************************
//====================================================================
taRightJustify: if Rect.Right-Rect.Left>=Printer.Canvas.TextWidth(TempStr)
then DrawText(Printer.Canvas.Handle,PChar(TempStr),Length(TempStr),Rect,DT_RIGHT or DT_VCENTER or DT_SINGLELINE)
else DrawText(Printer.Canvas.Handle,PChar(TempStr),Length(TempStr),Rect,DT_LEFT or DT_VCENTER or DT_SINGLELINE);
end;
Temp_X := Temp_X + Trunc(DBGrid.Columns[j-1].Width*Scale);
end;
Temp_Y := Temp_Y + RowHeight;
end;
//==============================================================================
//3.输出DBGrid内容**************************************************************
//==============================================================================
procedure Print_Cells;
var j: integer;
begin
Printer.Canvas.Font.Name := '宋体';
Printer.Canvas.Font.Style := Printer.Canvas.Font.Style - [fsBold];
while Temp_Y<Printer.PageHeight-PageEdgeY do
begin
Temp_X := PageEdgeX;
for j:=1 to DBGrid.Columns.Count do
begin
if not DBGrid.Columns[j-1].Visible then Continue;
//====================================================================
Rect := Bounds(Temp_X, Temp_Y, Trunc(DBGrid.Columns[j-1].Width*Scale), RowHeight);
if (DBGrid.Columns[j-1].Field is TCurrencyField)
or (DBGrid.Columns[j-1].Field is TLargeIntField)
or (DBGrid.Columns[j-1].Field is TSmallIntField)
or (DBGrid.Columns[j-1].Field is TIntegerField)
or (DBGrid.Columns[j-1].Field is TFloatField)
or (DBGrid.Columns[j-1].Field is TWordField)
then TempStr := FormatFloat(',##0.00',DBGrid.Columns[j-1].Field.AsFloat)
else TempStr := DBGrid.Columns[j-1].Field.AsString;
//====================================================================
case DBGrid.Columns[j-1].Field.Alignment of
//==================================================================
//case.1.居中*******************************************************
//==================================================================
taCenter: DrawText(Printer.Canvas.Handle,PChar(TempStr),Length(TempStr),Rect,DT_CENTER or DT_VCENTER or DT_SINGLELINE);
//==================================================================
//case.2.居左*******************************************************
//==================================================================
taLeftJustify: DrawText(Printer.Canvas.Handle,PChar(TempStr),Length(TempStr),Rect,DT_LEFT or DT_VCENTER or DT_SINGLELINE);
//==================================================================
//case.3.居右*******************************************************
//==================================================================
taRightJustify: DrawText(Printer.Canvas.Handle,PChar(TempStr),Length(TempStr),Rect,DT_RIGHT or DT_VCENTER or DT_SINGLELINE);
end;
Temp_X := Temp_X + Trunc(DBGrid.Columns[j-1].Width*Scale);
end;
Temp_Y := Temp_Y + RowHeight;
DBGrid.DataSource.DataSet.Next;
if DBGrid.DataSource.DataSet.Eof then Exit;
end;
end;
//==============================================================================
//4.输出页脚********************************************************************
//==============================================================================
procedure Print_Footer;
begin
Temp_Y := Printer.PageHeight - PageEdgeY + RowHeight;
//========================================================================
//4.0.输出横线************************************************************
//========================================================================
Printer.Canvas.Rectangle(PageEdgeX, Temp_Y, Printer.PageWidth - PageEdgeX, Temp_Y + 1);
//========================================================================
//4.1.输出日期************************************************************
//========================================================================
Rect := Bounds(PageEdgeX, Temp_Y, Printer.PageWidth-PageEdgeX, RowHeight);
DrawText(Printer.Canvas.Handle,PChar(DateTimeToStr(Now)),Length(DateTimeToStr(Now)),Rect,DT_LEFT or DT_VCENTER or DT_SINGLELINE);
//========================================================================
//4.2.输出页号************************************************************
//========================================================================
Rect := Bounds(PageEdgeX, Temp_Y, Printer.PageWidth-PageEdgeX*2, RowHeight);
DrawText(Printer.Canvas.Handle,PChar('#'+IntToStr(Printer.PageNumber)),Length('#'+IntToStr(Printer.PageNumber)),Rect,DT_RIGHT or DT_VCENTER or DT_SINGLELINE);
end;
//==============================================================================
begin
PrintDialog := TPrintDialog.Create(DBGrid);
if PrintDialog.Execute then
begin
//==========================================================================
//0.取当前打印机X,Y方向每英寸像素*******************************************
//==========================================================================
PixelsPerInchX := GetDeviceCaps(Printer.Handle, LOGPIXELSX);
PixelsPerInchY := GetDeviceCaps(Printer.Handle, LOGPIXELSY);
//==========================================================================
//1.变量初始化**************************************************************
//==========================================================================
PageEdgeX := PixelsPerInchX div 6;
PageEdgeY := PixelsPerInchY div 5 * 4;
RowHeight := Trunc(1.5 * 9 * PixelsPerInchY / 72);
Scale := PixelsPerInchX / Screen.PixelsPerInch;
//==========================================================================
try
Printer.BeginDoc;
DBGrid.DataSource.DataSet.First;
while not DBGrid.DataSource.DataSet.Eof do
begin
Print_Title;
Print_Column;
Print_Cells;
Print_Footer;
Printer.NewPage;
end;
//========================================================================
if not Printer.Aborted then Printer.EndDoc;
except
on E:EPrinter do
begin
MessageBox(Application.Handle,PChar('打印机没有准备好!'),'提示!',MB_OK+MB_ICONINFORMATION);
Printer.Abort;
Exit;
end;
on E:Exception do
begin
raise;
Exit;
end;
end;
end;
//============================================================================
PrintDialog.Free;
end;
二、dbgrideh标题排序:
首先把需要排序的title.titlebutton:=true
ehlib的optioneh中autosortmarking最好设为true
titelbutton事件中写:
var
sortstring:string;
begin
//进行排序
with Column do
begin
if FieldName = '' then Exit;
case Title.SortMarker of
smNoneEh:
begin
Title.SortMarker := smDownEh;
sortstring := Column.FieldName + ' ASC';
end;
smDownEh:sortstring:= Column.FieldName + ' ASC';
smUpEh:sortstring:=Column.FieldName + ' DESC';
end;

//数据集排序。
try
dataset.Sort:=sortstring //dataset为实际数据集变量名
except
end;
posted @ 2005-11-23 08:56 DELPHI技术 阅读(1105) 评论(1) 编辑

2005年11月22日 #

delphi 默认情况下参数保存的位置:函数的第一个参数保存在eax中,第二个参数保存在edx中,第三个参数保存在ecx中, 函数的返回值经常放在eax中。
posted @ 2005-11-22 15:50 DELPHI技术 阅读(659) 评论(0) 编辑

2005年11月21日 #

procedure TForm1.Button1Click(Sender: TObject) ;
var
   lf : TLogFont;
   tf : TFont;
begin
   with Form1.Canvas do begin
     Font.Name := 'Arial';
     Font.Size := 24;
     tf := TFont.Create;
     try
       tf.Assign(Font) ;
       GetObject(tf.Handle, sizeof(lf), @lf) ;
       lf.lfEscapement := 450;
       lf.lfOrientation := 450;
       tf.Handle := CreateFontIndirect(lf) ;
       Font.Assign(tf) ;
     finally
       tf.Free;
     end;
     TextOut(20, Height div 2, 'Rotated Text!') ;
   end;
end;
posted @ 2005-11-21 19:22 DELPHI技术 阅读(207) 评论(0) 编辑

There are many times when you need to split a string into an array of strings by using a character as a separator.
For example, a CSV ("comma" separated) file might have a line like "Zarko;Gajic;;DelphiGuide" and you want this line to be parsed into 4 lines (strings) "Zarko", "Gajic", "" (empty string) and "DelphiGuide" using the semi-colon character ";" as a delimiter.

Delphi provides several methods to parse a string, but you might find that neither one does exactly what you need. For example, the ExtractStrings RTL method always uses quote characters (single or double) for delimiters. Another approach is to use the Delimiter and DelimitedText properties of the TStrings class - but unfortunately there is a bug in the implementation ("inside" Delphi) where the space character is always used as a delimiter.

The only solution to parsing a delimited string is to write a method of your own:

~~~~~~~~~~~~~~~~~~~~~~~~~
procedure ParseDelimited(const sl : TStrings; const value : string; const delimiter : string) ;
var
   dx : integer;
   ns : string;
   txt : string;
   delta : integer;
begin
   delta := Length(delimiter) ;
   txt := value + delimiter;
   sl.BeginUpdate;
   sl.Clear;
   try
     while Length(txt) > 0 do
     begin
       dx := Pos(delimiter, txt) ;
       ns := Copy(txt,0,dx-1) ;
       sl.Add(ns) ;
       txt := Copy(txt,dx+delta,MaxInt) ;
     end;
   finally
     sl.EndUpdate;
   end;
end;
~~~~~~~~~~~~~~~~~~~~~~~~~

Usage (fills in Memo1) :
ParseDelimited(Memo1.lines,'Zarko;Gajic;;DelphiGuide',';')

posted @ 2005-11-21 19:20 DELPHI技术 阅读(389) 评论(0) 编辑

2005年7月22日 #

摘要: 每隔10年Borland都要经过一个生死劫?!1985年Borland 发布了Turb Pascal,Borland进入了10年辉煌期。1995年Borland 成功开发了Delphi 1.0 Borland起死回生,从死亡的边缘获得了新生!2005年Borland 又一次面临生死关口:连续两季度亏损,JBuilder战线失守,Kylix出师不利!总裁被迫下课!这一次Delphi 2005还能帮助...阅读全文
posted @ 2005-07-22 12:47 DELPHI技术 阅读(821) 评论(0) 编辑

2005年7月16日 #

摘要: DFM File(main.dfm): object MainForm: TMainForm Left = 301 Top = 163 Width = 696 Height = 480 Color = clBtnFace Font.Charset = DEFAULT_CHARSET Font.Color = clWindowText Font.Height = -16 Font.Name = 'T...阅读全文
posted @ 2005-07-16 15:18 DELPHI技术 阅读(1295) 评论(1) 编辑

摘要: unit uMainFrm;interfaceuses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, Mask;type TMainForm = class(TForm) btnPkgForm: TButton; medtOp1: TMaskEdit; me...阅读全文
posted @ 2005-07-16 11:50 DELPHI技术 阅读(854) 评论(0) 编辑

仅列出标题  下一页