Einzelnen Beitrag anzeigen

Benutzerbild von arcticwolf
arcticwolf

Registriert seit: 3. Aug 2021
Ort: Erfurt
41 Beiträge
 
Delphi 11 Alexandria
 
#6

AW: Windows Codepages - Kernel32.dll - EnumSystemCodePages

  Alt 22. Jun 2023, 15:41
Vielen Dank für die Erklärungen. Ich denke ich habe das Prinzip von statischen Klassen beziehungsweise von statischen Funktionen einer Klasse verstanden.
Hier eine verkürzte Version meines Codes:

Delphi-Quellcode:
Type TWindowsCodepages = class
     private
       class var FList : TStrings;
     protected
       class function GetCodepageName(Codepage:Cardinal) : String; static;
       class function EnumCodePagesProc(CodePage:PWideChar) : Boolean; static; stdcall;
       class function GetList : String; static;
       class procedure SetList(Const Value:String); static;
     public
       class constructor CreateClass;
       class destructor DestroyClass;
       class property List:String Read GetList Write SetList;
       class function RetrieveSupported : Boolean; static;
     end;

class function TWindowsCodepages.GetCodepageName(Codepage:Cardinal) : String;
var CpInfoEx : TCPInfoEx;
begin
  Result := '';
  if IsValidCodePage(Codepage) then
  begin
    GetCPInfoEx(Codepage, 0, CpInfoEx);
    Result := Format('%s', [CpInfoEx.CodePageName]);
  end;
end;

class function TWindowsCodepages.EnumCodePagesProc(CodePage:PWideChar) : Boolean;
Var CP : cardinal;
begin
  Result := False;
  if (CodePage<>Nil) then
  begin
    if (Length(Codepage)>0) then
    begin
      CP := StrToIntDef(CodePage,0);
      if (CP>0) then
      begin
        FList.Text := FList.Text + GetCodepageName(CP);
        Result := True;
      end;
    end;
  end;
end;

class function TWindowsCodepages.GetList : String;
begin
  Result := FList.Text;
end;

class procedure TWindowsCodepages.SetList(Const Value:String);
begin
  FList.Text := Value;
end;

class constructor TWindowsCodepages.CreateClass;
begin
  FList := TStringList.Create;
  FList.Delimiter := ';';
end;

class destructor TWindowsCodepages.DestroyClass;
begin
  FList.Free;
end;

class function TWindowsCodepages.RetrieveSupported : Boolean;
begin
  Result := EnumSystemCodePagesW(@EnumCodePagesProc,CP_SUPPORTED);
end;

Procedure DoSomething;
begin
  TWindowsCodepages.RetrieveSupported;
  Writeln(TWindowsCodepage.List);
end;
Da ich die Unit mit dem Code sowohl unter Win32, als auch unter Win64 nutzen möchte, ist noch wichtig zu erwähnen, dass dann auch bei der Callback-Funktion (EnumCodePagesProc) das "stdcall" dahinter stehen muss, sonst knallt es bei der Win32-Version.

Trotzdem stellt sich mir die Frage, wo der Vorteil ist? Die statische Klasse erstellt auch eine "globale" Variable, ja OK, nicht wirklich global, weil ich nur über die Klasse darauf zugreifen kann. Aber sie wird beim Start des Programmes über CreateClass erzeugt und erst beim Beenden des Programmes über DestroyClass wieder freigegeben und belegt somit für die komplette Laufzeit Speicher. Auch dann wenn die Klasse nur in irgendeinem Modul benötigt wird, das vielleicht gar nicht vom User verwendet wird. Gibt es da nicht eine elegantere Lösung für API Callback-Funktionen, die nur dann Speicher belegen wenn sie aufgerufen werden, also ohne globale Variable?
Wolfgang
  Mit Zitat antworten Zitat