It possible to assign version number etc to rtm's. So when someone is in explorer they can right click on the rtm file and view a version tab like you can with exes.
No. However RTM's do store their version numbers in a field called Version inside the Report component so you can parse out that value if needed. Windows version numbers (along with other custom information) are stored in a structure at the beginning of the file and can be retrieved using the code below:
var liSize: Cardinal; lBuffer: Pointer; liHandle: Cardinal; lVerStruct: VS_FIXEDFILEINFO; begin liSize := GetFileVersionInfoSize('c:\test.rtm', liHandle); if (liSize <> 0) then begin GetMem(lBuffer, liSize); GetFileVersionInfo('c:\test.rtm', liHandle, liSize, lBuffer); VerQueryValue(lBuffer, '\', lVerInfo, liSize); VS_FIXEDFILEINFO(lVerInfo^).dwFileVersionMS := 1; // the ms version number end: end;
Though I haven't tried this, you might be able to simply store this structure in the rtm as extra information. See the guidlelines below for doing that.
-- Cheers,
Alexander Kramnik Digital Metaphors
----------------------------------------------------- Tech Tip: Storing Custom Information with Templates -----------------------------------------------------
Question: ---------
How can I store descriptive information with my report template?
Solution: ---------
1. If you are storing the templates to a database, then you can use the Report.Template.OnSaveEnd and OnLoadEnd events to store and load the custom information to appropriate data fields for the record. (This is the technique used by the ReportExplorer.)
2. If you are storing templates to .rtm files, then you will need to store the custom information in an Offset area of the template file. The Report.Template object enables you do this by utilizing the Template.Offset property and the Template.OnLoadStart and OnLoadEnd events. Below is a detailed example.
Example: -------- - Create a new application. - Add to the main form one TButton, one TppReport and one TppDesigner. - Set the Designer's Report property to ppReport1. - Add ppTypes to the uses clause.
{note: use compiler directive to declare strings as 'ShortStrings' this is required for record structures}
{$H-}
{record structure used to store information inside report template } TmyTemplateInfo = record HeaderID: Integer; Comments: String; DateTime: TDateTime;
{note: if not one of the templates with our header info, then set Offset to 0 } if lTemplateInfo.HeaderID = cHeaderID then begin lsMessage := 'Reading data from template file: ' + #13#10 + #13#10 + lTemplateInfo.Comments + ' (' + DateTimeToStr(lTemplateInfo.DateTime) + ')';
procedure TForm1.SaveReportStreamEvent(Sender: TObject; Stream: TStream); var lTemplateInfo: TmyTemplateInfo; lsMessage: String;
begin
lTemplateInfo.HeaderID := cHeaderID; lTemplateInfo.Comments := 'This comment is being stored inside the report template, ' + #13#10 + 'along with the date and time written. '; lTemplateInfo.DateTime := Now;
{write info to template header} Stream.Seek(0, soFromBeginning); Stream.Write(lTemplateInfo, SizeOf(TmyTemplateInfo));
Comments
inside the Report component so you can parse out that value if needed.
Windows version numbers (along with other custom information) are stored in
a structure at the beginning of the file and can be retrieved using the code
below:
var
liSize: Cardinal;
lBuffer: Pointer;
liHandle: Cardinal;
lVerStruct: VS_FIXEDFILEINFO;
begin
liSize := GetFileVersionInfoSize('c:\test.rtm', liHandle);
if (liSize <> 0) then
begin
GetMem(lBuffer, liSize);
GetFileVersionInfo('c:\test.rtm', liHandle, liSize, lBuffer);
VerQueryValue(lBuffer, '\', lVerInfo, liSize);
VS_FIXEDFILEINFO(lVerInfo^).dwFileVersionMS := 1; // the ms version
number
end:
end;
Though I haven't tried this, you might be able to simply store this
structure in the rtm as extra information. See the guidlelines below for
doing that.
--
Cheers,
Alexander Kramnik
Digital Metaphors
-----------------------------------------------------
Tech Tip: Storing Custom Information with Templates
-----------------------------------------------------
Question:
---------
How can I store descriptive information with my report template?
Solution:
---------
1. If you are storing the templates to a database, then you can use the
Report.Template.OnSaveEnd and OnLoadEnd events to store and load the custom
information to appropriate data fields for the record. (This is the
technique used by the ReportExplorer.)
2. If you are storing templates to .rtm files, then you will need to store
the custom information in an Offset area of the template file. The
Report.Template object enables you do this by utilizing the Template.Offset
property and the Template.OnLoadStart and OnLoadEnd events. Below is a
detailed example.
Example:
--------
- Create a new application.
- Add to the main form one TButton, one TppReport and one TppDesigner.
- Set the Designer's Report property to ppReport1.
- Add ppTypes to the uses clause.
type
TForm1 = class(TForm)
Button1: TButton;
ppReport1: TppReport;
ppDesigner1: TppDesigner;
procedure FormCreate(Sender: TObject);
procedure Button1Click(Sender: TObject);
private
procedure LoadReportStreamEvent(Sender: TObject; Stream: TStream);
procedure SaveReportStreamEvent(Sender: TObject; Stream: TStream);
public
end; { class TForm1 }
{note: use compiler directive to declare strings as 'ShortStrings'
this is required for record structures}
{$H-}
{record structure used to store information inside report template }
TmyTemplateInfo = record
HeaderID: Integer;
Comments: String;
DateTime: TDateTime;
end; {record, TppTemplateRec}
{$H+}
const
cHeaderID = 12345;
implementation
{-------------------------------------------------}
{ TForm1.FormCreate }
procedure TForm1.FormCreate(Sender: TObject);
begin
{setup Template events }
ppReport1.Template.Format := ftASCII;
ppReport1.Template.Offset := SizeOf(TmyTemplateInfo);
ppReport1.Template.OnLoadStart := LoadReportStreamEvent;
ppReport1.Template.OnSaveEnd := SaveReportStreamEvent;
end; {procedure, FormCreate}
{-------------------------------------------------}
{ TForm1.Button1Click }
procedure TForm1.Button1Click(Sender: TObject);
begin
ppDesigner1.Show;
end; {procedure, Button1Click}
{--------------------------------------------------}
{ TForm1.LoadReportStreamEvent }
procedure TForm1.LoadReportStreamEvent(Sender: TObject; Stream: TStream);
var
lTemplateInfo: TmyTemplateInfo;
lsMessage: String;
begin
{read string stored in template header }
Stream.Seek(0, soFromBeginning);
Stream.Read(lTemplateInfo, SizeOf(TmyTemplateInfo));
{note: if not one of the templates with our header info, then set Offset
to 0 }
if lTemplateInfo.HeaderID = cHeaderID then
begin
lsMessage := 'Reading data from template file: ' + #13#10 + #13#10 +
lTemplateInfo.Comments + ' (' +
DateTimeToStr(lTemplateInfo.DateTime) + ')';
MessageDlg(lsMessage, mtInformation, [mbOK],0);
ppReport1.Template.Offset := SizeOf(TmyTemplateInfo);
end
else
ppReport1.Template.Offset := 0;
end; {procedure, LoadReportStreamEvent}
{---------------------------------------------------------------------------
---}
{ TForm1.SaveReportStreamEvent }
procedure TForm1.SaveReportStreamEvent(Sender: TObject; Stream: TStream);
var
lTemplateInfo: TmyTemplateInfo;
lsMessage: String;
begin
lTemplateInfo.HeaderID := cHeaderID;
lTemplateInfo.Comments := 'This comment is being stored inside the report
template, ' + #13#10 +
'along with the date and time written. ';
lTemplateInfo.DateTime := Now;
{write info to template header}
Stream.Seek(0, soFromBeginning);
Stream.Write(lTemplateInfo, SizeOf(TmyTemplateInfo));
lsMessage := 'Writing data to template file: ' + #13#10 + #13#10 +
lTemplateInfo.Comments + ' (' +
DateTimeToStr(lTemplateInfo.DateTime) + ')';
MessageDlg(lsMessage, mtInformation, [mbOK],0);
end; {procedure, SaveReportStreamEvent}
http://www.digital-metaphors.com
info@digital-metaphors.com