Announcement

Collapse
No announcement yet.

Frage an Andreas Kosch

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Frage an Andreas Kosch

    Hallo Andreas,<br>
    <br>
    Ich arbeite immer noch mit D3. Ich hab diverse Bücher, unter anderem auch Dein Buch "Delphi 3 Lösungen" konsultiert und bin auch in der Delphi-Hilfe nicht weiter gekommen.<br>
    Da Du Dich schon tief in das Thema Strings einstudiert hast, hoffe ich dass Du mir helfen kannst.<br>
    Hier also mein Anliegen:
    Ich möchte einen Editor bauen, der jede erdenkliche Datei öffnen und bearbeiten kann. Z.B. Hex- oder Grafik-Dateien.<br>
    Dies wollte ich mit dem Objekt TEdit realisieren, da es schon sehr viele praktische methoden bereitstellt. Beim ersten Einlesen von einer
    Hex datei musste ich jedoch feststellen, dass im Edit-Modul nicht die ganze Datei dargestellt wurde! Dies liegt daran, dass beim Einlesen eines
    Bytes mit dem Wert #0 der String als beendet angesehen wird, weil die strings ja neu Nullterminiert sind.
    Es wurde mir schon vorgeschlagen, die Bytes einzeln einzulesen und die untersten 32 Byte durch ein Spezialzeichen zu ersetzen und darzustellen. Nur weiss ich ja dann beim Zurückspeichern nicht mehr welchen Wert diese Zeichen ursprünglich hatten.
    Ich hab mich auch schon gefragt, ob es nicht mit Ansi-Zeichen zu lösen wäre. Doch da ergeben sich neue Probleme wie z.B. max 255 Zeichen, max 65k Zeilen (in Win9x) usw.<br>
    Hast Du mir eine einfache Lösung zu meinem Problem?<br>
    <br>
    Vielen Dank zum Voraus,<br>
    m.f.G Thomas

  • #2
    Hallo,

    bei einem HEX-Editor muss man zwei getrennte Datenbereiche verwenden: <br>
    A) Originaldaten als Byte-Array <br>
    B) Anzeigedaten, bei denen die nichtdarstellbaren Zeichen durch ein anderes Zeichen (in der Regel einen Punkt) ersetzt werden. <br>
    Das Programm muss sicherstellen, dass jederzeit die Position im Bereich B) bestimmt und die Eingabe im Bereich A) nachvollzogen wird. Allerdings muss die Eingabe im Byte-Format erfolgen, d.h. es wird für das Editieren eine Darstellung im HEX-Format benötigt. Somit ist TMemo von Haus aus dazu nicht in der Lage, zumal das dahinterliegende Win32-Control unter Windows 9x nur max. 64 kByte Daten verträgt.

    Das folgende Beispiel für die zweispaltige Anzeige (links HEX-Daten, rechts Textdarstellung) von HEX-Daten stammt aus meinem Buch <i>Delphi Win32-Lösungen</i>. Die aus der Registry ausgelesenen binären Daten werden angezeigt. Dabei wird sowohl die Verwaltung der Daten in einem PChar (Zeiger auf einen Speicherbereich) als auch die Umwandlung der nichtdarstellbaren Zeichen in einen Punkt demonstriert:
    <pre>
    uses
    Registry;

    procedure GetHexDisplay(aData: Pointer; aSize: Integer; aList: TStrings);
    var
    iDataLength : Integer;
    i : Integer;
    aStream : TMemoryStream;
    pBuffer : PChar;
    iLineLen : Integer;
    sStrBin : String;
    sStrTxt : String;
    begin
    iDataLength := ASize;
    AList.Add(EmptyStr);
    aStream := TMemoryStream.Create;
    try
    aStream.Write(AData^, ASize);
    aStream.Seek(0, soFromBeginning);
    while (aStream.Position < aStream.Size) do
    begin
    if (iDataLength > (aStream.Size - aStream.Position)) then
    iDataLength := aStream.Size - aStream.Position;
    pBuffer := AllocMem(iDataLength);
    try
    aStream.Read(pBuffer[0], iDataLength);
    sStrTxt := EmptyStr;
    sStrBin := EmptyStr;
    for i := 0 to iDataLength - 1 do
    begin
    if ((i = 0) or ((i mod 16) = 0)) then
    begin
    if (i <> 0) then
    begin
    aList.Add(sStrBin + '|' + sStrTxt + '|');
    sStrTxt := EmptyStr;
    end;
    sStrBin := Format('%5X: ', [i]);
    end;
    sStrBin := sStrBin + Format('%.02X ', [Byte(pBuffer[i])]);
    if (pBuffer[i] < char($20)) or (pBuffer[i] > char($7F)) then
    pBuffer[i] := '.';
    sStrTxt := sStrTxt + pBuffer[i];
    end;
    finally
    FreeMem(pBuffer);
    end;
    if (sStrTxt <> EmptyStr) then
    begin
    if (Length(sStrTxt) < 16) then
    begin
    iLineLen := 16 - Length(sStrTxt);
    sStrBin := sStrBin + StringOfChar(' ', iLineLen * 3);
    sStrTxt := sStrTxt + StringOfChar(' ', iLineLen);
    end;
    aList.Add(sStrBin+ '|' + sStrTxt + '|');
    sStrTxt := EmptyStr;
    end;
    end;
    finally
    aStream.Free;
    end;
    if (sStrTxt <> EmptyStr) then
    begin
    if (Length(sStrTxt) < 16) then
    begin
    iLineLen := 16 - Length(sStrTxt);
    sStrBin := StringOfChar(' ', iLineLen * 2);
    sStrTxt := StringOfChar(' ', iLineLen);
    end;
    AList.Add(sStrBin+ '|' + sStrTxt + '|');
    end;
    end;

    procedure TFormMain.ButtonReadClick(Sender: TObject);
    resourcestring
    cREGKEY = '\Software\OssiSoft\MULTI_SZ';
    cREGVALUE = 'Testeintrag';
    var
    aReg : TRegistry;
    iSize : integer;
    sBuffer : String;
    begin
    aReg := TRegistry.Create;
    try
    with aReg do
    begin
    if OpenKey(cREGKEY, False) then
    begin
    try
    iSize := GetDataSize(cREGVALUE);
    if iSize > 0 then
    begin
    SetLength(sBuffer, iSize);
    ReadBinaryData(cREGVALUE, sBuffer[1], iSize);
    GetHexDisplay(@sBuffer[1], iSize, ListBox1.Items);
    end;
    finally
    Closekey;

    Comment


    • #3
      vielen Dank erstmal für Deine prompte Antwort.<br>
      Wie Du sicher gesehen hast, hat offenbar auch das Forum eine Grössenbeschränkung. Dein Programmteil und eventuell noch Text von Dir wurde abgeschnitten. Könntest Du mir den Rest noch ins Forum kopieren? Du kannst es mir auch Mailen. Deshalb hier noch meine Adresse:
      [email protected]<br>
      Vielen Dank nochmals, für Deine Hilfe!<br>
      <br>
      Thoma

      Comment


      • #4
        Hallo,

        der fehlende Teil ergibt sich von selbst:
        <pre>
        procedure TFormMain.ButtonReadClick(Sender: TObject);
        resourcestring
        cREGKEY = '\Software\OssiSoft\MULTI_SZ';
        cREGVALUE = 'Testeintrag';
        var
        aReg : TRegistry;
        iSize : integer;
        sBuffer : String;
        begin
        aReg := TRegistry.Create;
        try
        with aReg do
        begin
        if OpenKey(cREGKEY, False) then
        begin
        try
        iSize := GetDataSize(cREGVALUE);
        if iSize > 0 then
        begin
        SetLength(sBuffer, iSize);
        ReadBinaryData(cREGVALUE, sBuffer[1], iSize);
        GetHexDisplay(@sBuffer[1], iSize, ListBox1.Items);
        end;
        finally
        Closekey;
        end;
        end;
        end;
        finally
        aReg.Free;
        end;
        end;
        </pre&gt

        Comment

        Working...
        X