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 Pointer - Wie verwenden? (https://www.delphipraxis.net/130063-pointer-wie-verwenden.html)

Andreas L. 2. Mär 2009 20:57


Pointer - Wie verwenden?
 
Abend,
ich habe einer Form zwei Methode verpasst. Einmal LoadValues(FileList TFiles); und SaveValues(FileList: TFiles); (TFiles ist eine TObjectList) Jetzt soll sich das Form beim laden merken, welche Dateiliste übergeben wurde und diese dann zum speichern verwenden. So sieht mein Code bisher aus:

Delphi-Quellcode:
type
  TfrmCookieFiles = class(TForm)
    lblFiles: TLabel;
    lstFiles: TListView;
    btnOK: TButton;
    procedure LoadValues(FileList: TFiles);
    procedure SaveValues(FileList: TFiles);
    procedure btnOKClick(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    FFileList: Pointer;
  end;

var
  frmCookieFiles: TfrmCookieFiles;

implementation

{$R *.dfm}

procedure TfrmCookieFiles.btnOKClick(Sender: TObject);
begin
  SaveValues(@FFileList);
  lstFiles.Clear;
  Close;
end;

procedure TfrmCookieFiles.LoadValues(FileList: TFiles);
var
  i: Integer;
begin
  FFileList := @FileList;
  for i := 0 to FileList.Count -1 do
  begin
    with lstFiles.Items.Add do
    begin
      Caption := FileList[i].Title;
      SubItems.Add(FileList[i].Profile);
      SubItems.Add(FileList[i].FileName);
      Checked := FileList[i].Checked;
    end;
  end;
end;

procedure TfrmCookieFiles.SaveValues(FileList: TFiles);
var
  i: Integer;
begin
  for i := 0 to lstFiles.Items.Count -1 do
    FileList.GetFileByFileName(lstFiles.Items[i].SubItems[1]).Checked := lstFiles.Items[i].Checked;
end;
Das laden klappt auch einwandfrei, beim Speichern passiert leider nichts. Nehme ich bei SaveValues(@FFileList); das @ weg, kommt eine AV. Was mache ich falsch?

mkinzler 2. Mär 2009 21:00

Re: Pointer - Wie verwenden?
 
Variablen mit Klassentypen sind schon Referenzen(Zeiger)!

Neutral General 2. Mär 2009 21:02

Re: Pointer - Wie verwenden?
 
Hi,

Wird FFileList überhaupt irgendwo zugeordnet?
Außerdem ist @FFileList ein Pointer, der auf die Pointervariable FFileList zeigt (Ein Pointer also, der auf einen Pointer zeigt). Das hattest du sicherlich nicht vor ;)

Warum übergibst du deiner Funktion nicht einfach eine Variable vom Typ TFiles?

Andreas L. 2. Mär 2009 21:03

Re: Pointer - Wie verwenden?
 
Zitat:

Zitat von mkinzler
Variablen mit Klassentypen sind schon Referenzen(Zeiger)!

Wenn ich alle @ weglasse wird trotzdem nicht gespeichert.

Zitat:

Wird FFileList überhaupt irgendwo zugeordnet?
LoadValues wird vom Hauptformular aufgerufen. In LoadValues wirds dann zugeordnet.

mkinzler 2. Mär 2009 21:05

Re: Pointer - Wie verwenden?
 
hast du auch
Delphi-Quellcode:
FFileList: TFiles;
angepasst?

Andreas L. 2. Mär 2009 21:07

Re: Pointer - Wie verwenden?
 
Zitat:

Zitat von mkinzler
hast du auch
Delphi-Quellcode:
FFileList: TFiles;
angepasst?

Ja

mkinzler 2. Mär 2009 21:12

Re: Pointer - Wie verwenden?
 
Was macht/soll den SaveValues den (machen)?

Andreas L. 2. Mär 2009 21:17

Re: Pointer - Wie verwenden?
 
Zitat:

Zitat von mkinzler
Was macht/soll den SaveValues den (machen)?

In FileList eintragen, welche Dateien aktiviert (checked) sind.

TFiles sieht so aus:

Delphi-Quellcode:
  TFiles = class(TObjectList)
  protected
    procedure SetItem(Index: Integer; Value: TFile);
    function GetItem(Index: Integer):TFile;
  public
    function Add:Integer;
    function GetFileByFileName(FileName: String):TFile;
    function CheckedCount:Integer;
    function GetCheckBoxStyle:TCheckBoxState;
    property Items[Index: Integer]:TFile read GetItem write SetItem; default;
  end;

  TFile = class(TPersistent)
  private
    FFileName: String;
    FBrowser: String;
    FProfile: String;
    FFormat: TCookieFormat;
    FTitle: String;
    FSize: Int64;
    FChecked: Boolean;
  protected
    procedure Assign(Source: TFile);
  published
    property FileName: String read FFileName write FFileName;
    property Browser: String read FBrowser write FBrowser;
    property Profile: String read FProfile write FProfile;
    property Format: TCookieFormat read FFormat write FFormat;
    property Title: String read FTitle write FTitle;
    property Size: Int64 read FSize write FSize;
    property Checked: Boolean read FChecked write FChecked;
  end;

...

{ TFile }
procedure TFile.Assign(Source: TFile);
begin
  FFileName := Source.FileName;
  FBrowser := Source.Browser;
  FProfile := Source.Profile;
  FFormat := Source.Format;
  FTitle := Source.Title;
  FSize := Source.Size;
  FChecked := Source.Checked;
end;

{ TFiles }
procedure TFiles.SetItem(Index: Integer; Value: TFile);
begin
  inherited Items[Index] := Value;
end;

function TFiles.GetItem(Index: Integer):TFile;
begin
  Result := inherited Items[Index] as TFile;
end;

function TFiles.Add:Integer;
var
  NewFile: TFile;
begin
  NewFile := TFile.Create;
  Result := inherited Add(NewFile);
end;

function TFiles.GetFileByFileName(FileName: string):TFile;
var
  iFile: Integer;
begin
  Result := TFile.Create;
  Result.Checked := False;
  for iFile := 0 to Count -1 do
  begin
    if LowerCase(Items[iFile].FileName) = LowerCase(FileName) then
    begin
      Result.Assign(Items[iFile]);
      Break;
    end;
  end;
end;

function TFiles.CheckedCount:Integer;
var
  iFile: Integer;
begin
  Result := 0;
  for iFile := 0 to Count -1 do
    if Items[iFile].Checked then
      Inc(Result);
end;

function TFiles.GetCheckBoxStyle:TCheckBoxState;
begin
  Result := cbUnchecked;
  if CheckedCount = Count then
    Result := cbChecked
  else if CheckedCount > 0 then
    Result := cbGrayed;
end;

Blup 3. Mär 2009 12:17

Re: Pointer - Wie verwenden?
 
Der Fehler liegt in der Methode GetFileByName. Dort wird bei jedem Zugriff eine neue Instanz von TFile erzeugt.
Bei dieser Instanz wird dann Checked gesetzt, nicht bei der Instanz in der Liste.
Zusätzlich entsteht noch ein Speicherloch, da keine Freigabe erfolgt.

Delphi-Quellcode:
function TFiles.GetFileByFileName(FileName: string):TFile;
var
  iFile: Integer;
begin
  for iFile := 0 to Count -1 do
  begin
    if LowerCase(Items[iFile].FileName) = LowerCase(FileName) then
    begin
      Result.Assign(Items[iFile]);
      Exit;
    end;
  end;
  Result := nil;
end;
Die Methode SaveValues würde dann aber in ihrer jetzigen Form zu einer Zugriffsverletzung führen,
wenn deren Inhalt nicht mit der dargestellten Listbox übereinstimmt.

Delphi-Quellcode:
procedure TfrmCookieFiles.SaveValues(FileList: TFiles);
var
  i: Integer;
  f: TFile;
begin
  for i := 0 to lstFiles.Items.Count -1 do
  begin
    f := FileList.GetFileByFileName(lstFiles.Items[i].SubItems[1]);
    if Assigned(f) then
      f.Checked := lstFiles.Items[i].Checked;
  end;
end;

Andreas L. 3. Mär 2009 14:39

Re: Pointer - Wie verwenden?
 
Zitat:

Der Fehler liegt in der Methode GetFileByName.
Ja, das habe ich gestern Nacht auch noch gemerkt. Jetzt funkioniert alles.

Trotzdem danke :-D


Alle Zeitangaben in WEZ +1. Es ist jetzt 22:58 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