Entwickler-Ecke

Delphi Language (Object-Pascal) / CLX - Record-Eigenschaft Text aus TMemo übernehmen.


bf109g.01 - Di 23.08.11 15:19
Titel: Record-Eigenschaft Text aus TMemo übernehmen.
Hallo, ich habe ein Record-Array mit einer Eigenschaft "Beschreibung : Text".
In die Recordeigenschaft Beschreibung will ich nämlich einen längeren Textblock unterbringen.
Deshalb gibt es in der Eingabe-Maske ein Memo dafür. Speichern wollte ich das dann so:

Delphi-Quelltext
1:
 ArrayF[Stelle].Beschreibung:=Fr_MLoesung.Lines.                    

Das gibt Fehler. Wie kann ich das stattdessen anständig hinbekommen?

LG


Moderiert von user profile iconNarses: Topic aus Dateizugriff verschoben am Di 23.08.2011 um 15:45


bummi - Di 23.08.11 15:44

Der Datentyp Text ist Synonym für Textfile (Assign(f, dateiname), Reset(f) etc..)
Du benötigst den Typ String und ArrayF[Stelle].Beschreibung:=Fr_MLoesung.Lines.Text;


bf109g.01 - Di 23.08.11 17:06

user profile iconbummi hat folgendes geschrieben Zum zitierten Posting springen:
Du benötigst den Typ String

Dann hab ich aber nur 255 Zeichen frei. Soweit ich weiß lässt sich ein String ohne Einschränkung (=255) gar nicht speichern/laden, weils wohl nur ein Zeiger ist, oder irgendsowas....
Wie kann ich den Text länger machen? So 500 Zeichen wären fein... Muss ich da mit ner Stringlist arbeiten?


jaenicke - Di 23.08.11 20:03

Nein, du solltest dir lieber eine eigene Datenstruktur überlegen und in Klassen ablegen (Records geht auch, aber ich halte es mit Klassen für sinnvoller). Dann kannst du auch sehr einfach mehr als nur die selben Daten hintereinander speichern...

Kleines Beispiel, ungetestet...

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
118:
119:
120:
121:
122:
123:
124:
125:
126:
127:
128:
129:
130:
131:
132:
133:
134:
135:
136:
137:
138:
139:
140:
141:
142:
143:
144:
145:
146:
147:
148:
149:
150:
151:
152:
153:
154:
155:
156:
157:
158:
159:
160:
161:
162:
163:
164:
165:
166:
167:
168:
169:
170:
171:
172:
173:
174:
175:
176:
uses
  ActiveX, ShlObj;


type
  TMyData = class
  strict private
    FMyDataExample: string;
  public
    constructor Create(const AMyDataExample: string = '');
    procedure LoadFromStream(AStream: TStream);
    procedure SaveToStream(AStream: TStream);
    property MyDataExample: string read FMyDataExample write FMyDataExample;
  end;

  TMyDataList = class(TObjectList<TMyData>)
  public
    constructor Create;
    procedure LoadFromStream(AStream: TStream);
    procedure SaveToStream(AStream: TStream);
    procedure LoadFromFile(const AFileName: string);
    procedure SaveToFile(const AFileName: string);
  end;

// ...

// aus: http://www.delphi-library.de/viewtopic.php?t=9428
// Gibt den Pfad des übergebenen Ordners zurück.
function GetSpecialFolder(AFolder: Integer): string;
var
  pIdL: PItemIDList;
  Path: array[0..Max_Path] of Char;
  Allocator: IMalloc;
begin
  // ItemIdList für den Ordner holen
  SHGetSpecialFolderLocation(0, aFolder, pIdL);
  // ItemIdList in String umwandeln lassen
  SHGetPathFromIDList(pIDL, Path);
  // Speicher wieder freigeben
  if Succeeded(SHGetMalloc (Allocator)) then
    Allocator.Free (pIdL);
  Result := Path;
end;

function LoadStringFromStream(AStream: TStream): String;
var
  ResultString: AnsiString;
  StringSize: Integer;
begin
  Result := '';
  if AStream.Size - AStream.Position < SizeOf(StringSize) then
    Exit;
  AStream.ReadBuffer(StringSize, SizeOf(StringSize));
  SetLength(ResultString, StringSize);
  if AStream.Size - AStream.Position < StringSize then
    Exit;
  AStream.ReadBuffer(Pointer(ResultString)^, StringSize);
  {$ifdef UNICODE} // ab Delphi 2009
  Result := Utf8ToString(ResultString);
  {$else}
  Result := Utf8Decode(ResultString);
  {$endif}
end;

procedure SaveStringToStream(AStream: TStream; AString: String);
var
  StringSize: Integer;
  StringToSave: AnsiString;
begin
  StringToSave := Utf8Encode(AString);
  StringSize := Length(StringToSave);
  AStream.WriteBuffer(StringSize, SizeOf(StringSize));
  AStream.WriteBuffer(Pointer(StringToSave)^, StringSize);
end;

constructor TMyData.Create(const AMyDataExample: string);
begin
  FMyDataExample := AMyDataExample;
end;

procedure TMyData.LoadFromStream(AStream: TStream);
begin
  FMyDataExample := LoadStringFromStream(AStream);
end;

procedure TMyData.SaveToStream(AStream: TStream);
begin
  SaveStringToStream(AStream, FMyDataExample);
end;

constructor TMyDataList.Create;
begin
  inherited Create(True);
end;

procedure TMyDataList.LoadFromFile(const AFileName: string);
var
  FileContents: TFileStream;
begin
  FileContents := TFileStream.Create(AFileName, fmOpenRead);
  try
    LoadFromStream(FileContents);
  finally
    FileContents.Free;
  end;
end;

procedure TMyDataList.LoadFromStream(AStream: TStream);
var
  i, DataCount: LongInt;
  NewData: TMyData;
begin
  AStream.ReadBuffer(DataCount, SizeOf(DataCount));
  for i := 1 to DataCount do
  begin
    NewData := TMyData.Create;
    NewData.LoadFromStream(AStream);
    Add(NewData);
  end;
end;

procedure TMyDataList.SaveToFile(const AFileName: string);
var
  FileContents: TFileStream;
begin
  FileContents := TFileStream.Create(AFileName, fmCreate);
  try
    SaveToStream(FileContents);
  finally
    FileContents.Free;
  end;
end;

procedure TMyDataList.SaveToStream(AStream: TStream);
var
  i, DataCount: LongInt;
  CurrentData: TMyData;
begin
  DataCount := Count;
  AStream.WriteBuffer(DataCount, SizeOf(DataCount));
  for CurrentData in Self do
    CurrentData.SaveToStream(AStream);
end;

// Beispiel:
var
  MyDataList: TMyDataList;
  CurrentData: TMyData;
  DataFileName: string;
begin
  MyDataList := TMyDataList.Create;
  try
    // bestehende Daten laden
    DataFileName := IncludeTrailingPathDelimiter(GetSpecialFolder(CSIDL_LOCAL_APPDATA)) + 'Test.txt';
    if FileExists(DataFileName) then
      MyDataList.LoadFromFile(DataFileName);

    // alle ausgeben
    for CurrentData in MyDataList do
      ShowMessage(CurrentData.MyDataExample);

    // neue Einträge erzeugen
    MyDataList.Add(TMyData.Create('Ein kleiner Test'));
    MyDataList.Add(TMyData.Create('Noch ein Test'));
    MyDataList.Add(TMyData.Create('Das ist ein Satz!'));

    // alle ausgeben
    for CurrentData in MyDataList do
      ShowMessage(CurrentData.MyDataExample);

    // alle speichern
    MyDataList.SaveToFile(DataFileName);
  finally
    MyDataList.Free;
  end;
end;


bummi - Di 23.08.11 22:48

user profile iconbf109g.01 hat folgendes geschrieben Zum zitierten Posting springen:
user profile iconbummi hat folgendes geschrieben Zum zitierten Posting springen:
Du benötigst den Typ String

Dann hab ich aber nur 255 Zeichen frei. Soweit ich weiß lässt sich ein String ohne Einschränkung (=255) gar nicht speichern/laden, weils wohl nur ein Zeiger ist, oder irgendsowas....
Wie kann ich den Text länger machen? So 500 Zeichen wären fein... Muss ich da mit ner Stringlist arbeiten?


Wieso, wie alt ist Deine Delphiversion?
Ich meine alle nicht uralten Versionen haben bei String keine nennenswerte Grenze > 2GB


jaenicke - Di 23.08.11 23:10

ShortStrings für die Billigvariante des Speicherns von Records als Datenpakete haben die Beschränkung auch in Delphi XE und werden sie immer haben. ;-)