Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Interface implementieren... (https://www.delphipraxis.net/28149-interface-implementieren.html)

barnti 20. Aug 2004 09:01


Interface implementieren...
 
Hallo,
ich versuche immer noch meine Klasse für die 'FileInfo' zu erstellen. Hier ein Teil des Codes:
Delphi-Quellcode:
unit Versioninfo;

interface
uses
  Types,windows,SysUtils;
type
  TVersionInfo=class

  private
    FStandardKeys:array[0..9] of String; // Beinhaltet Alle FileInfos

    function GetVersioninfo(Index: Integer): String;
    function GetKey(KeyName: String): String;
    procedure SetVersionInfo(const Index: Integer; const Value: String);
    function GetBuildNumber: String;
  public
    constructor Create (ThisSourceFile: String);
    destructor Destroy; override;

    property Key[KeyName: String]: String read GetKey;

    property CompanyName: String index 0 read GetVersionInfo write SetVersionInfo;
    property FileDescription: String index 1 read GetVersionInfo;
    property FileVersion: String index 2 read GetVersionInfo;
    property InternalName: String index 3 read GetVersionInfo;
    property Copyright: String index 4 read GetVersionInfo;
    property TradeMarks: String index 5 read GetVersionInfo;
    property OriginalFileName: String index 6 read GetVersionInfo;
    property ProductName: String index 7 read GetVersionInfo write SetVersionInfo;
    property ProductVersion: String index 8 read GetVersionInfo write SetVersionInfo;
    property Comments: String index 9 read GetVersionInfo;
    property BuildNumber: String read GetBuildNumber;

    // Hier versuche ich auf die Eigenschaften zuzugreifen. Leider schlägt das Kompilieren fehl:
    // [Error] Versioninfo.pas(35): Incompatible types
    property StandardKeys[index: Integer]: String read GetVersionInfo write SetVersionInfo;
   
  end;

implementation

{ TVersionInfo }
const MaxVersionKeys= 9;
constructor TVersionInfo.Create(ThisSourceFile: String);
const
  VersionkeyNames: array[0..MaxVersionKeys] of String = ('CompanyName',
  'FileDescription','FileVersion','InternalName','Copyright','TradeMarks',
  'OriginalFileName','ProductName','ProductVersion','Comments');
var
  ThisInfo: Integer;
  InfoLength: UInt64;
  Len, Handle: DWord;
  PCharset: PLongint;
  LangCharset: String;
  InfoAvailable: Boolean;
begin
  inherited Create;

  // Get size of version info
  Len:= GetFileVersionInfoSize(PChar(ThisSourceFile),Handle);

  // Allocate VersionInfo buffer size
  SetLength(VersionInfo, Len+1);

  //Get version info
  if GetFileVersionInfo(PChar(ThisSourceFile), Handle,Len,Pointer(VersionInfo))
  then
  begin
    if VerQueryValue(Pointer(VersionInfo),'\VarFileInfo\Translation',
    Pointer(PCharSet),Len)then
    begin
      LangCharset:= Format('%.4x%.4x',[LoWord(PCharset^),HiWord(PCharset^)]);
      InfoAvailable:= true;
      for ThisInfo:=0 to MaxVersionKeys do
      begin
        // Hier sollen die Informationen übernommen werden...
        StandardKeys[ThisInfo]:= GetKey(VersionKeyNames[ThisInfo]);
      end;
    end;
 end;
end;

destructor TVersionInfo.Destroy;
begin

  inherited;
end;

function TVersionInfo.GetBuildNumber: String;
begin

end;

function TVersionInfo.GetKey(KeyName: String): String;
var
 
begin

end;

function TVersionInfo.GetVersioninfo(Index: Integer): String;
begin
  result:= FStandardKeys[Index]
end;

procedure TVersionInfo.SetVersionInfo(const Index: Integer;
  const Value: String);
begin
  FStandardKeys[Index]:= Value;
end;

end.
Kann jemand helfen? Ich versuche die File info im Konstruktor in die Variable 'StandardKeys' zu schreiben...

MathiasSimmack 20. Aug 2004 09:09

Re: Interface implementieren...
 
Ich habe jetzt mal schnell eine alte Funktion rausgekramt (bitte auch hier den Patch beachten). Damit habe ich es mir relativ einfach gemacht, die Werte auszulesen, die ich brauche.

Evtl. kommst du mit einer ähnlichen Methode besser weg. Sprich: Aus dem Constructor würde ich den Code rausnehmen und lieber auslagern und dann die Properties gleich zuweisen. Ohne diesen Umweg über das Array "FStandardKeys".

barnti 20. Aug 2004 09:14

Re: Interface implementieren...
 
Hi,
nett von Dir aber ich möchte es auf diese Weise implementieren. Kannst Du zu meinem Code etwas sagen? Wo liegt mein Fehler?

MathiasSimmack 20. Aug 2004 10:34

Re: Interface implementieren...
 
Ich wollte dich keinesfalls in deinem Eifer bremsen. Wenn du mich nach deinem Code fragst, dann muss ich gestehen, dass ich den Sinn der Zeile
Zitat:

Delphi-Quellcode:
 property StandardKeys[index: Integer]: String read GetVersionInfo write SetVersionInfo;

nicht ganz verstehe. Warum führst du diese Variable heraus? Wozu soll das gut sein?

Ich habe eben mal auf der Basis deiner Unit eine Klasse zusammengezimmert, die sowohl mit einzelnen Strings als auch mit einem String-Array arbeitet (Compilerswitch). Was soll ich sagen? Keine Probleme.

btw: Das einzige, das mir im Moment wirklich als Problem auffällt, ist "Copyright". Das müsstest du in "LegalCopyright" ändern (im VersionkeyNames-Array), sonst liest du alles mögliche aus, aber nicht das Copyright. ;)

barnti 20. Aug 2004 10:40

Re: Interface implementieren...
 
Hallo,
ich habe deine Einwände bedacht und geändert. Kannst Du mir die 'zusammengezimmerte Klasse' einmal zeigen? Ich habe Probleme das so zu verstehen...
Danke!

MathiasSimmack 20. Aug 2004 11:23

Re: Interface implementieren...
 
Delphi-Quellcode:
unit VersionInfo;

{.$DEFINE USEARRAY}

interface

uses
  Windows, SysUtils;

type
  TVersionInfo=class
  private
    FInfo            : PVSFixedFileInfo;
{$IFDEF USEARRAY}
    FInfoKeys        : array[0..9]of string;
{$ELSE}
    FCompanyName,
    FFileDescription,
    FFileVersion,
    FInternalName,
    FCopyright,
    FTrademarks,
    FOriginalFileName,
    FProductName,
    FProductVersion,
    FComments,
{$ENDIF}
    FVersionNumber   : string;

    function FormatVersionNumber: string;
{$IFDEF USEARRAY}
    function GetKey(Idx: integer): string;
{$ENDIF}
  public
    constructor Create(const SourceFile: string);
    procedure LoadProperties(const SourceFile: string);

{$IFDEF USEARRAY}
    property CompanyName: string index 0 read GetKey;
    property FileDescription: string index 1 read GetKey;
    property FileVersion: string index 2 read GetKey;
    property InternalName: string index 3 read GetKey;
    property Copyright: string index 4read GetKey;
    property Trademarks: string index 5 read GetKey;
    property OriginalFileName: string index 6 read GetKey;
    property ProductName: string index 7 read GetKey;
    property ProductVersion: string index 8 read GetKey;
    property Comments: string index 9 read GetKey;
{$ELSE}
    property CompanyName: string read FCompanyName;
    property FileDescription: string read FFileDescription;
    property FileVersion: string read FFileVersion;
    property InternalName: string read FInternalName;
    property Copyright: string read FCopyright;
    property Trademarks: string read FTrademarks;
    property OriginalFileName: string read FOriginalFileName;
    property ProductName: string read FProductName;
    property ProductVersion: string read FProductVersion;
    property Comments: string read FComments;
{$ENDIF}
    property VersionNumber: string read FVersionNumber;
  end;

implementation

{$IFNDEF USEARRAY}
function GetFileInfo(const FileName, BlockKey: string): string;
var
  vis,
  dummy       : dword;
  vi,
  translation,
  ip          : pointer;
begin
  Result      := '';
  vis         := GetFileVersionInfoSize(pchar(FileName),dummy);
  if(vis > 0) then
  begin
    GetMem(vi,vis);
    try
      GetFileVersionInfo(pchar(Filename),0,vis,vi);
      if(vi = nil) then exit;

      // get language code
      VerQueryValue(vi,'\\VarFileInfo\\Translation',translation,vis);
      if(translation = nil) then exit;

      ip := nil;
      VerQueryValue(vi,
        pchar(Format('\\StringFileInfo\\%.4x%.4x\\%s',
          [LOWORD(longint(translation^)),HIWORD(longint(translation^)),
          BlockKey])),ip,vis);
      if(ip = nil) then exit;

      SetString(Result,pchar(ip),vis - 1);
    finally
      FreeMem(vi);
    end;
  end;
end;
{$ENDIF}

function GetDefaultFileInfo(const FileName: string): PVSFixedFileInfo;
var
  vis,
  dummy    : dword;
  vi       : pointer;
begin
  Result   := nil;
  vis      := GetFileVersionInfoSize(pchar(FileName),dummy);
  if(vis > 0) then
  begin
    GetMem(vi,vis);
    try
      GetFileVersionInfo(pchar(FileName),0,vis,vi);
      if(vi = nil) then exit;

      VerQueryValue(vi,'\\',pointer(Result),dummy);
    finally
      FreeMem(vi);
    end;
  end;
end;


// -- TVersionInfo -------------------------------------------------------------

constructor TVersionInfo.Create(const SourceFile: string);
begin
  inherited Create;
  self.LoadProperties(SourceFile);
end;

procedure TVersionInfo.LoadProperties(const SourceFile: string);
{$IFDEF USEARRAY}
const
  DefaultInfoKey : array[0..9]of string =
    ('CompanyName','FileDescription','FileVersion','InternalName',
     'LegalCopyright','TradeMarks','OriginalFileName','ProductName',
     'ProductVersion','Comments');
var
  vis,
  dummy         : dword;
  vi,
  translation,
  ip            : pointer;
  i             : integer;
{$ENDIF}
begin
{$IFDEF USEARRAY}
  vis           := GetFileVersionInfoSize(pchar(SourceFile),dummy);
  if(vis > 0) then
  begin
    GetMem(vi,vis);
    try
      GetFileVersionInfo(pchar(SourceFile),0,vis,vi);
      if(vi = nil) then exit;

      // get language code
      VerQueryValue(vi,'\\VarFileInfo\\Translation',translation,vis);
      if(translation = nil) then exit;

      for i := low(DefaultInfoKey) to high(DefaultInfoKey) do
      begin
        ip := nil;

        VerQueryValue(vi,
          pchar(Format('\\StringFileInfo\\%.4x%.4x\\%s',
            [LOWORD(longint(translation^)),HIWORD(longint(translation^)),
            DefaultInfoKey[i]])),ip,vis);
        if(ip = nil) then FInfoKeys[i] := ''
          else SetString(FInfoKeys[i],pchar(ip),vis - 1);
      end;
    finally
      FreeMem(vi);
    end;
  end;
{$ELSE}
  // fill properties
  FCompanyName      := GetFileInfo(SourceFile,'CompanyName');
  FFileDescription  := GetFileInfo(SourceFile,'FileDescription');
  FFileVersion      := GetFileInfo(SourceFile,'FileVersion');
  FInternalName     := GetFileInfo(SourceFile,'InternalName');
  FCopyright        := GetFileInfo(SourceFile,'LegalCopyright');
  FTrademarks       := GetFileInfo(SourceFile,'TradeMarks');
  FOriginalFileName := GetFileInfo(SourceFile,'OriginalFileName');
  FProductName      := GetFileInfo(SourceFile,'ProductName');
  FProductVersion   := GetFileInfo(SourceFile,'ProductVersion');
  FComments         := GetFileInfo(SourceFile,'Comments');
{$ENDIF}

  FInfo             := GetDefaultFileInfo(SourceFile);
  FVersionNumber    := self.FormatVersionNumber;
end;

function TVersionInfo.FormatVersionNumber: string;
const
  FormatStr = '%d.%d.%d.%d';
begin
  Result := Format(FormatStr,
    [(FInfo^.dwFileVersionMS and $FFFF0000) shr 16,
      FInfo^.dwFileVersionMS and $0000FFFF,
     (FInfo^.dwFileVersionLS and $FFFF0000) shr 16,
      FInfo^.dwFileVersionLS and $0000FFFF]);
end;

{$IFDEF USEARRAY}
function TVersionInfo.GetKey(Idx: integer): string;
begin
  Result := FInfoKeys[Idx];
end;
{$ENDIF}

end.
:mrgreen: Ich hoffe, du kommst mit den Compilerschaltern klar. Im Moment werden die einzelnen Strings benutzt. Willst du mit dem String-Array arbeiten, dann entferne den Punkt in der Zeile
Delphi-Quellcode:
{.$DEFINE USEARRAY}
Ach so, ein Beispiel vllt. noch, damit du weißt warum ich das Laden der Properties in eine separate Funktion gepackt habe:
Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
var
  vi : TVersionInfo;
begin
  vi := TVersionInfo.Create('c:\pctools\smc.exe');
  try
    Memo1.Lines.Add(vi.CompanyName);
    Memo1.Lines.Add(vi.VersionNumber);
    Memo1.Lines.Add('');

    vi.LoadProperties('c:\pctools\hed.exe');
    Memo1.Lines.Add(vi.ProductName);
    Memo1.Lines.Add(vi.Copyright);
  finally
    FreeAndNil(vi);
  end;
end;
btw: Weil du das MSDN-Library durchsuchenVS_FIXEDFILEINFO-Record in der privaten Variablen "FInfo" hast, könntest du auch auf andere Daten zugreifen, nicht bloß auf die Versionsnummer.

barnti 20. Aug 2004 11:29

Re: Interface implementieren...
 
Hallo,
ich dachte Du hast das nach meinem Quellcode implementiert? Ich verfüge bereits über Beispiele, wie man die Info ermittelt.
Ich würde gern wissen wo mein Fehler in meinem Quellcode liegt!
Hast Du da einen Tip?
Quellcode:
siehe dieses post

MathiasSimmack 20. Aug 2004 11:34

Re: Interface implementieren...
 
Natürlich war deine Unit die Grundlage. Bloß warum soll ich deine Fehler übernehmen? Ich hab´s so gestaltet, dass es für mich einfach zu handhaben war. Außerdem hast du mir immer noch nicht die Frage beantwortet, warum du unbedingt das String-Array als öffentliche Eigenschaft haben willst. Welchen Sinn soll das machen?

barnti 20. Aug 2004 11:42

Re: Interface implementieren...
 
Hallo,
das habe ich bereits entfernt.
Ich verstehe, dass du wenig Arbeithaben willst aber mein Ziel ist es nicht anderen Code zu übernehmen sondern meinen zum Laufen zu kriegen...
Der Fehler steckt im Aufruf im Konstruktor:
Delphi-Quellcode:
...  // Diese liefert mir immer false, obwohl Informationen vorhanden sind.
  if VerQueryValue(Pointer(ThisSourceFile),'\VarFileInfo\Translation',
       Pointer(PCharSet),Len) then
    begin
      //LangCharset:= Format('%.4x%.4x',[LoWord(PCharset^),HiWord(PCharset^)]);
      InfoAvailable:= true;
...
Ich denke die Wahl meiner Parameter und deren Initialisierung ist falsch. Ich weiß nur nicht was falsch ist. Auch nach durchsicht deines Codes habe ich den Fehler noch nicht gefunden.

MathiasSimmack 20. Aug 2004 11:47

Re: Interface implementieren...
 
Ich finde das wirklich gut, dass du es allein hinbekommen willst. Das ist mehr, als manch andere wollen. Aber andererseits: Ich habe meine Umsetzung erst absichtlich nicht gepostet, eben weil du es selbst machen wolltest. Dann hast du darum gebeten, und ich hab sie dir gezeigt.

Und da ich keine Probleme mit dem Auslesen der Versionsnummer habe, und weil ich notgedrungen die gleichen Befehle verwenden muss wie du (logisch, oder? ;)), spricht IMHO nichts dagegen, wenn du dir einfach mal nur diesen Teil meiner Umsetzung ansiehst.
Genauer gesagt: Ich habe das Rückgabeergebnis von "VerQueryValue" ignoriert und stattdessen geschaut ob meine pointer-Variable ungleich nil ist.
Delphi-Quellcode:
      VerQueryValue(vi,
        pchar(Format('\\StringFileInfo\\%.4x%.4x\\%s',
          [LOWORD(longint(translation^)),HIWORD(longint(translation^)),
          BlockKey])),ip,vis);
      if(ip = nil) then exit;
Wie gesagt, Null Probleme.


Alle Zeitangaben in WEZ +1. Es ist jetzt 05:52 Uhr.
Seite 1 von 2  1 2      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz