Delphi-PRAXiS
Seite 1 von 3  1 23      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Memo lässt Zeilen verschwinden (https://www.delphipraxis.net/159382-memo-laesst-zeilen-verschwinden.html)

aphexx 25. Mär 2011 14:08

Delphi-Version: 2009

Memo lässt Zeilen verschwinden
 
Hallo!

Ich bin gerade dabei ein Chat-Programm für Dropbox zu entwickeln.
Nix großes und manche Stimmen halten es für überflüssig, aber ich finds toll :wink:

Hintergrund: Ich arbeite mit einem Verzeichnis in dem x txt-Dateien liegen.
Diese lade ich bei einer Aktualisierung in ein array (da das integrierte Datum zum sortieren beutzt wird) vom typ record
(Username, Datum/Zeit, Nachricht). Danach wird alles in einem Memo angezeigt.

Das Problem ist, dass immer der vorletzte Eintrag (von beispielseise 3 txt-Dateien) nur mit Username und Datum angezigt wird.
Die Nachricht ist nicht zu sehen. Das Array läuft sauber, die Daten exisiteren, nur die Darstellung nicht :?

Vielleicht hilft es, wenn ich zusätzlich die EXE bereitstelle?

Hier ist der Code. Unwichtige Funktionen/Prozeduren habe ich ausgeklammert.

Delphi-Quellcode:
unit main;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ExtCtrls, ImgList;

function RandomString(const len: Integer = 30; const CharSet: string = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'): string;overload;

type
  TEntry = record
    User: String[25];
    Msg: TStringList;
    DatumZeit: String;
  end;
  TForm1 = class(TForm)
    Panel1: TPanel;
    Panel2: TPanel;
    BSend: TButton;
    MOutput: TMemo;
    MMessage: TMemo;
    EUser: TEdit;
    Label1: TLabel;
    EDiv: TEdit;
    Label2: TLabel;
    BSort: TButton;
    Icons: TImageList;
    BRefresh: TButton;
    procedure FormCreate(Sender: TObject);
    procedure BSendClick(Sender: TObject);
    procedure BSortClick(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure BRefreshClick(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;
  Entry: TEntry;
  Entries: Array of TEntry;
  AufAb: Boolean;

implementation

{$R *.dfm}

procedure GetFilesInDirectory(Directory: string; const Mask: string;
                              List: TStrings;
                              WithSubDirs, ClearList: Boolean);
[...]
end;

procedure Sortieren(Aufsteigend: Boolean);
var
  E: TEntry;
  i, j, max: Integer;
  x, y: TDateTime;
begin
  E.Msg := TStringlist.Create;
  max := Length(Entries);
  for i:=0 to max-1 do
  for j:=0 to max-1 do
  begin
     DateSeparator := '.';
     ShortDateFormat := 'dd.mm.yyyy';
     LongTimeFormat := 'hh:nn:ss.zzz';

     if Aufsteigend = True
     then
     begin
       x := StrToDateTime(Entries[i].DatumZeit);
       y := StrToDateTime(Entries[j].DatumZeit);
     end
     else
     begin
       x := StrToDateTime(Entries[j].DatumZeit);
       y := StrToDateTime(Entries[i].DatumZeit);
     end;

     if x > y then
      begin
       E := Entries[i];
       Entries[i] := Entries[j];
       Entries[j] := E;
     end;
  end;
  E.Msg.Clear;
end;

procedure InitFillEntries(Liste: TStringList);
var
  i, zeilen, j: Integer;
  Inhalt: TStringlist;
begin
  Inhalt := TStringlist.Create;

  if Length(Entries) > Liste.Count then
  begin
    for i := 0 to Length(Entries) - 1 do
    begin
      Entries[i].Msg.Clear;
      Entries[i].User := '';
      Entries[i].DatumZeit := '';
    end;
  end;

  SetLength(Entries, Liste.Count);

  for i := 0 to Length(Entries) - 1 do
  begin
    if FileExists(Liste[i]) then Inhalt.LoadFromFile(Liste[i])
    else
    begin
      ShowMessage(Liste[i] + #13 + 'does not exist.');
      Exit;
    end;

    Entries[i].User := Inhalt.Strings[0];
    Entries[i].DatumZeit := Inhalt.Strings[1];

    Entries[i].Msg := TSTringlist.Create;
    Entries[i].Msg.BeginUpdate;
    Entries[i].Msg.LoadFromFile(Liste[i]);
    Entries[i].Msg.Delete(0);
    Entries[i].Msg.Delete(0);

    Entries[i].Msg.EndUpdate;
  end;
  Sortieren(AufAb);
  Inhalt.Free;
end;


procedure PassEntries;
var
  i, c, j: Integer;
  L, laden: TStringlist;
  Liste: TStringlist;
  s, dir: String;
begin
  L := TStringlist.Create;
  Liste := TStringlist.Create;
  Laden := TStringlist.Create;

  dir := ExtractFilePath(ParamStr( 0 ))+'dbchat\';

  GetFilesInDirectory(dir, '*.txt', Liste, False, True);

  L.BeginUpdate;

  InitFillEntries(Liste);              //Array Füllen

  for i := 0 to Length(Entries) - 1 do
  begin
    L.BeginUpdate;
    L.Add(Entries[i].User);
    L.Add(Entries[i].DatumZeit);
    L.Add('');
    L.Add(Trim(Entries[i].Msg.Text));

    for c := 0 to 19 do s := s + Form1.EDiv.Text;
    L.Add(s);
    s := '';
  end;
  L.EndUpdate;

  Form1.MOutput.Lines.Clear;

  Form1.MOutput.Lines.Assign(L);

  Liste.Free;
  laden.Free;
  L.Free;
end;

function RandomString(const len: Integer; const CharSet: string): string;
[...]
end;

procedure TForm1.BSendClick(Sender: TObject);
[...]
end;

procedure TForm1.BSortClick(Sender: TObject);
begin
[...]
end;

procedure TForm1.BRefreshClick(Sender: TObject);
begin
  PassEntries;
end;

procedure TForm1.FormCreate(Sender: TObject);
var
  dir : string;
begin
  Randomize;
  // Get the current directory
  dir := GetCurrentDir;
  if DirectoryExists('dbchat') = True
  then
    begin
      AufAb := True;
      PassEntries;
    end
  else
  begin
   CreateDir('dbchat');
   ShowMessage('Directory created:' + #13 + dir + 'dbchat');
  end;
  MMessage.Lines.Clear;
end;

procedure TForm1.FormDestroy(Sender: TObject);
var
  i: Integer;
begin
  //Leeren
  for i := 0 to Length(Entries) - 1 do
  begin
    Entries[i].Msg.Clear;
    Entries[i].User := '';
    Entries[i].DatumZeit := '';
  end;
  SetLength(Entries, 0);
end;

end.

p80286 25. Mär 2011 15:07

AW: Memo lässt Zeilen verschwinden
 
Delphi-Quellcode:
  ....
  InitFillEntries(Liste); //Array Füllen

  for i := 0 to Length(Entries) - 1 do
  begin
    L.BeginUpdate;
    L.Add(Entries[i].User);
    L.Add(Entries[i].DatumZeit);
    L.Add('');
    L.Add(Trim(Entries[i].Msg.Text));

    for c := 0 to 19 do s := s + Form1.EDiv.Text;
    L.Add(s);
    s := '';
  end;
  L.EndUpdate;

  Form1.MOutput.Lines.Clear;

  Form1.MOutput.Lines.Assign(L);
  ....
Das ist ja der Teil um den es geht, und abgesen von s='' (das sollte vor for c:=0... stehen) sehe ich da nichts erwähnenswertes.
Zitat:

Zitat von aphexx (Beitrag 1090953)
Die Nachricht ist nicht zu sehen. Das Array läuft sauber, die Daten exisiteren, nur die Darstellung nicht :?

Da bist Du Dir sicher?

Gruß
K-H

Luckie 25. Mär 2011 16:39

AW: Memo lässt Zeilen verschwinden
 
Wie kommen die Daten in die Dateien? Kann es sein, dass da noch irgendwelche Steuerzeichen von der Übertragung drin stehen?

aphexx 25. Mär 2011 18:39

AW: Memo lässt Zeilen verschwinden
 
Liste der Anhänge anzeigen (Anzahl: 1)
Zitat:

Zitat von p80286 (Beitrag 1090982)
Delphi-Quellcode:
  ....
  InitFillEntries(Liste); //Array Füllen

  for i := 0 to Length(Entries) - 1 do
  begin
    L.BeginUpdate;
    L.Add(Entries[i].User);
    L.Add(Entries[i].DatumZeit);
    L.Add('');
    L.Add(Trim(Entries[i].Msg.Text));

    for c := 0 to 19 do s := s + Form1.EDiv.Text;
    L.Add(s);
    s := '';
  end;
  L.EndUpdate;

  Form1.MOutput.Lines.Clear;

  Form1.MOutput.Lines.Assign(L);
  ....
Das ist ja der Teil um den es geht, und abgesen von s='' (das sollte vor for c:=0... stehen) sehe ich da nichts erwähnenswertes.
Zitat:

Zitat von aphexx (Beitrag 1090953)
Die Nachricht ist nicht zu sehen. Das Array läuft sauber, die Daten exisiteren, nur die Darstellung nicht :?

Da bist Du Dir sicher?

Gruß
K-H

s bringt uns nur eine improvisierte Trennlinie von 20 Zeichen. In PassEntries hole ich die Daten aus dem Array und setze sie ins Memo, in InitFillEntries fülle ich das Array wiederum. Ich werde mal die EXE uppen, dann sieht man den Murks mal in action ;)

@Luckie: Sorry, da war Zensursula etwas übereifrig. Beim Speichern kann eigentlich auch nix schief laufen, da die txt-Dateien alle vollständig sind.

Hier die OnClick vom Senden-Button:
Delphi-Quellcode:
procedure TForm1.BSendClick(Sender: TObject);
var
  L: TStringList;
  s1, s2, p: String;
begin
  if EUser.Text = '' then
  begin
    ShowMessage('Chatting without a name sucks.');
    EUser.SetFocus;
    Exit;
  end;
  if MMessage.Lines.Count = 0 then
  begin
    ShowMessage('Chatting without writing something sucks.');
    MMessage.SetFocus;
    Exit;
  end;
  L := TStringList.Create;
  L.BeginUpdate;
  L.Clear;
  L.Add(EUser.Text);
  L.Add(FormatDateTime('dd.mm.yyyy hh:nn:ss.zzz', now));
  L.AddStrings(MMessage.Lines);
  if DirectoryExists('dbchat') then
  begin
    s1 := RandomString;
    p := ExtractFilePath(ParamStr( 0 ))+'\dbchat\' + s1 + '.txt';
    while FileExists(p) = True do
    begin
      ShowMessage('FileExists');
      s1 := RandomString;
      p := ExtractFilePath(ParamStr( 0 ))+'\dbchat\' + s1 + '.txt';
    end;
    L.SaveToFile(p);
  end;
  L.EndUpdate;
  L.Free;
  PassEntries;
  MMessage.Lines.Clear;
  MMessage.SetFocus;
end;

Die EXE habe ich beigelegt, bitte versucht mal 3 oder 4 Einträge anzulegen und danach die Sortierung nach Datum umzukehren; ihr werdet sehen, dass nur bei einem Eintrag was faul ist. DANKE!

aphexx 25. Mär 2011 19:18

AW: Memo lässt Zeilen verschwinden
 
Eilmeldung: Ich habe gerade beschlossen keine einzelnen Dateien mehr zu erstellen, sondern pro user genau eine Datei anzulegen, dann stresst Dropbox nicht so oft rum. Verstehen würde ich das Problem von weiter oben trotzdem gern, also wenn jemand eine spontane Eingebung wär ich sehr dankbar =)

aphexx 27. Mär 2011 14:53

AW: Memo lässt Zeilen verschwinden
 
Liste der Anhänge anzeigen (Anzahl: 3)
Ok, wie es ausschaut, habe ich doch irgendeinen Denkfehler gemacht, denn auch in der neuen Version, bei der pro Chat-User immer nur eine txt angelegt wird, wird die Nachricht des vorletzten Eintrags ausgelassen.
Und weil das nicht schon nervig genug ist, wird auch nur die letzte Zeile einer Nachricht angezeigt.

Bitte bitte helft mir, ich stehe so kurz vorm Ziel und Verzweifeln.

Zur Veranschaulichung habe ich die Prozeduren zum Füllen des Arrays und Darstellung im Memo etwas kommentiert, hoffentlich hilft's.
Delphi-Quellcode:
//################################################### Deklaration
type
  TEntry = record
    User: String[25];
    Msg: TStringList;
    DatumZeit: String;
  end;
  TForm1 = class(TForm)
    Panel1: TPanel;
    Panel2: TPanel;
    BSend: TButton;
    MOutput: TMemo;
    MMessage: TMemo;
    EUser: TEdit;
    Label1: TLabel;
    EDiv: TEdit;
    Label2: TLabel;
    BSort: TButton;
    Icons: TImageList;
    BRefresh: TButton;
    procedure FormCreate(Sender: TObject);
    procedure BSendClick(Sender: TObject);
    procedure BSortClick(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure BRefreshClick(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;
  Entry: TEntry;
  Entries: Array of TEntry;
  AufAb: Boolean;

//################################################### Deklaration Ende

{...verschiedene Funktionen...}

//################################################### Sortieren
procedure Sortieren(Aufsteigend: Boolean);
var
  E: TEntry;
  i, j, max: Integer;
  x, y: TDateTime;
begin
  E.Msg := TStringlist.Create;
  max := Length(Entries);
  for i:=0 to max-1 do
  for j:=0 to max-1 do
  begin
     DateSeparator := '.';
     ShortDateFormat := 'dd.mm.yyyy';
     LongTimeFormat := 'hh:nn:ss.zzz';

     if Aufsteigend = True
     then
     begin
       x := StrToDateTime(Entries[i].DatumZeit);
       y := StrToDateTime(Entries[j].DatumZeit);
     end
     else
     begin
       x := StrToDateTime(Entries[j].DatumZeit);
       y := StrToDateTime(Entries[i].DatumZeit);
     end;

     if x > y then
      begin
       E := Entries[i];
       Entries[i] := Entries[j];
       Entries[j] := E;
     end;
  end;
  E.Msg.Clear;
end;


//################################################### Array füllen

procedure InitFillEntries(Liste: TStringList);
var
  i, eintrAuf, c: Integer;
  Inhalt, temp: TStringlist;
  PosisAuf, PosisZu: Array of Integer;
  f: String;
begin
  Inhalt := TStringlist.Create;
  temp := TStringlist.Create;

  //Array leeren
  for i := 0 to Length(Entries) - 1 do
    begin
      Entries[i].Msg.Clear;
      Entries[i].User := '';
      Entries[i].DatumZeit := '';
    end;
  SetLength(Entries,0);
  //Array leeren Ende

  //Alle TXT-Dateien in "temp" reinladen | "Liste" enthält die Filenames
  for i := 0 to Liste.Count - 1 do
  begin
    f := Liste[i];
    if FileExists(f) then Inhalt.LoadFromFile(f);
    temp.BeginUpdate;
    temp.AddStrings(Inhalt);
    temp.EndUpdate;
  end;
  //TXT-Dateien Ende

  eintrAuf := 0;            //Nachrichtenzähler nullen
  SetLength(PosisAuf, 0);   //Start-Merker nullen
  SetLength(PosisZu, 0);    //Ende-Merker nullen

  //"temp" scannen
  for i := 0 to temp.Count - 1 do
  begin
    if temp.Strings[i] = '{{' then               //Start eines Beitrags | Start-Merker
    begin
      Inc(eintrAuf);
      SetLength(PosisAuf, Length(PosisAuf)+1);
      PosisAuf[High(PosisAuf)] := i;
    end;

    if temp.Strings[i] = '}}' then              //Ende eines Beitrags | Ende-Merker
    begin
      SetLength(PosisZu, Length(PosisZu)+1);
      PosisZu[High(PosisZu)] := i;
    end;
  end;

  SetLength(Entries, eintrAuf);                //Array auf die Anzahl der Einträge setzen


  for i := 0 to eintrAuf-1 do                        //Array durchlaufen
  begin
      Entries[i].User := temp[PosisAuf[i]+1];        //Übergabe aus "temp" --> User-Name
      Entries[i].DatumZeit := temp[PosisAuf[i]+2];   //Übergabe aus "temp" --> Datum/Zeit
      for c := PosisAuf[i]+1 to PosisZu[i] - 1 do    //Zeilenweise Übergabe aus "temp" --> Nachricht
      begin
        Entries[i].Msg := TStringList.Create;
        Entries[i].Msg.Add(temp.Strings[c]);
      end;
  end;

  //Leichen begraben
  SetLength(PosisAuf, 0);
  SetLength(PosisZu, 0);
  Inhalt.Clear;
  temp.Clear;
end;


//################################################### An Memo Übergeben

procedure PassEntries;
var
  i, c: Integer;
  L: TStringlist;
  Liste: TStringlist;
  s, dir: String;
begin
  L := TStringlist.Create;              //Zukünftiger Inhalt vom Memo
  Liste := TStringlist.Create;          //Liste der TXT-Dateien

  dir := ExtractFilePath(ParamStr( 0 ))+'dbchat\';

  GetFilesInDirectory(dir, '*.txt', Liste, False, True);      //Alle TXT-Dateien in Verz. "dbchat" einlesen

  L.BeginUpdate;
  L.Clear;

  InitFillEntries(Liste);              //Array Füllen
  Sortieren(AufAb);                    //Array nach Datum/Zeit sortieren

  for i := 0 to Length(Entries) - 1 do                //"L" befüllen
  begin
    L.BeginUpdate;
    L.Add(Entries[i].User);
    L.Add(Entries[i].DatumZeit);
    L.Add('');

    for c := 0 to Entries[i].Msg.Count - 1 do        //Zeilen aus der Nachricht holen
    begin
      L.Add(Entries[i].Msg[c]);
    end;

    for c := 0 to 19 do s := s + Form1.EDiv.Text;    //20 Zeichen als Trennlinie
    L.Add(s);
    s := '';
  end;
  L.EndUpdate;

  Form1.MOutput.Lines.Clear;                        // "L" an Memo übergeben
  Form1.MOutput.Lines.Assign(L);

  Liste.Free; //Freigeben
  L.Free;

  //Scrollen
  if AufAb = True then Form1.MOutput.Perform(EM_LineScroll, 0 , Form1.MOutput.Lines.Count-1);
end;
EDIT:
Ich habe den Anhang um den Screenshot "debugger.png" erweitert. Dieser zeigt, was sich tatsächlich im Array verbirgt.
Username ist ok, Datum/Zeit ist ok. Aber warum steht unter Msg (TStringlist) nicht der Text? Das macht mich echt mürbe -.-

EDIT2:
Delphi-Quellcode:
  for i := 0 to eintrAuf-1 do                        //Array durchlaufen
  begin
      Entries[i].User := temp[PosisAuf[i]+1];        //Übergabe aus "temp" --> User-Name
      Entries[i].DatumZeit := temp[PosisAuf[i]+2];   //Übergabe aus "temp" --> Datum/Zeit
      Entries[i].Msg := TStringList.Create;
      for c := PosisAuf[i]+3 to PosisZu[i] - 1 do    //Zeilenweise Übergabe aus "temp" --> Nachricht
      begin
        Entries[i].Msg.Add(temp.Strings[c]);
      end;
  end;
Ich hatte die Stringlist an der falschen Stelle created. Nun funzen zumindest alle Einträge bis auf den vorletzten. Sry für den monolog, aber vllt. sieht es sich ja trotzdem noch einer an ;)

aphexx 27. Mär 2011 20:56

AW: Memo lässt Zeilen verschwinden
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hier ist der letzte Stand der EXE.
Würde mich freuen, wenn Ihr eine Idee bzgl. des Bugs habt.

p80286 28. Mär 2011 11:25

AW: Memo lässt Zeilen verschwinden
 
Was ist denn eigentlich jetzt der Stand der Dinge?
Versuch doch bitte noch einmal das Problem, genau zu beschreiben!

Gruß
K-H

P.S.
Ich schlage mich im allg. nicht darum, fremde Sourcen zu lesen, um mögliche Fehler zu finden.

aphexx 28. Mär 2011 13:31

AW: Memo lässt Zeilen verschwinden
 
Liste der Anhänge anzeigen (Anzahl: 1)
Zitat:

Zitat von p80286 (Beitrag 1091504)
Was ist denn eigentlich jetzt der Stand der Dinge?
Versuch doch bitte noch einmal das Problem, genau zu beschreiben!

Gruß
K-H

P.S.
Ich schlage mich im allg. nicht darum, fremde Sourcen zu lesen, um mögliche Fehler zu finden.

Danke erstmal, dass Du Dich überhaupt mit meinem Problem befassen magst.
Der Chat funktioniert mittlerweile fast einwandfrei. Das einzige Problem ist leider immer noch das vom Anfang,
dass das Memo, welches den gesamten Chatlog anzeigt, bei der vorletzten Nachricht nur den User und das Datum mit Zeit anzeigt.
Die Daten kommen aus einem Array of TEntry, welcher ein Record aus 2 Strings und einer Stringlist ist. Die Vermutung liegt nahe,
dass die Übergabe ans Memo fehlerhaft ist (PassEntries). Diese Schlussfolgerung kommt daher, dass dieses Array vor der Darstellung
analysiert und sortiert wird (also Datum/Zeit) und allein vom Datensatz her richtig befüllt ist. Das erkennt man daran,
dass sowohl in der aufsteigenden als auch absteigenden Sortieung der vorletzte Message-Eintrag des Chat-Logs fehlt.
Vielleicht ist es irgendein dubioser Zahlendreher, den ich einfach nicht sehe.

Ich werde nochmal die aktuellste main.pas anhängen. Die Übergabe vom Array zum Memo passiert in "PassEntries".

p80286 28. Mär 2011 14:42

AW: Memo lässt Zeilen verschwinden
 
Viel wichtiger,
wie sieht der Eintrag für den Text in deinem array aus?
"vorletzter" scheint mir sehr unwahrscheinlich, es sei denn Du fügst noch einen Standardsatz am Ende ein.

Gruß
K-H


Alle Zeitangaben in WEZ +1. Es ist jetzt 07:33 Uhr.
Seite 1 von 3  1 23      

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