2012-03-08 1 views
4

Je suis en train de faire une visionneuse hexadécimale de base d'un TMemo, je sais que ce n'est probablement pas idéal, mais ce sera moi personnellement l'utiliser, donc cela n'a pas vraiment d'importance.Blocs de mots dans TMemo

(1)

Tout d'abord, supposons un mémo est rempli d'informations Hex comme ceci:

enter image description here

Comment pourrais-je obtenir un compte de tous les blocs de texte affiché, en ignorant la espace blanc? Donc, en utilisant l'image, le résultat dans ce cas serait 28.

C'est ce que j'ai essayé et je sais que c'est complètement faux car j'accède aux lignes Mémo mais je ne sais pas comment accéder à chaque caractère.

Je ne peux pas semble résoudre ce problème simple :(

function CountWordBlocks(Memo: TMemo): Integer; 
var 
    i: Integer; 
    vCount: Integer; 
begin 
    for i := 0 to Memo.Lines.Count - 1 do 
    begin 
    if Length(Memo.Lines.Strings[i]) = 2 then 
    begin 
     Inc(vCount); 
    end; 
    end; 

    Result := vCount; 
end; 

Voici le code que je utilise pour afficher les valeurs Hex dans le mémo:

procedure ReadFileAsHex(const AFileName: string; ADestination: TStrings); 
var 
    fs: TFileStream; 
    buff: Byte; 
    linecount: Byte; 
    line: string; 
begin 
    linecount := 0; 
    line := ''; 
    fs := TFileStream.Create(AFileName, fmOpenRead); 

    try 
    ADestination.BeginUpdate; 
    try 
     while fs.Position < fs.Size do 
     begin 
     fs.Read(buff, 1); 
     line := line + IntToHex(buff, 2) + ' '; 
     Inc(linecount); 
     if linecount = 16 then 
     begin 
      ADestination.Add(line); 
      line := ''; 
      linecount := 0; 
     end; 
     end; 
     if Length(line) <> 0 then 
     ADestination.Add(line); 
    finally 
     ADestination.EndUpdate; 
    end; 
    finally 
    fs.Free; 
    end; 
end; 

(2)

Si je clique sur le mémo et qu'un bloc de texte est sous le curseur, comment pourrais-je savoir quel est le numéro du bloc sélectionné parmi tous les autres?

Donc, en utilisant la même première image, le caret est à la première ligne à côté de 68, de sorte que le résultat serait 3 comme il est le troisième bloc de texte sur 28.

Cela devrait être si facile mais je Je ne peux pas penser clairement, je n'ai pas encore le bon esprit de programmation et je me bats vraiment avec la logique de base et la résolution de problèmes!

(3)

Enfin, je voudrais sélectionner un bloc à l'exécution en passant une valeur de numéro de bloc. J'ai essayé sans grand succès:

procedure FindBlock(Memo: TMemo; BlockNumber: Integer); 
var 
    i: Integer; 
    txt: string; 
    ThisWhite, PrevWhite: boolean; 
    vRead: Integer; 
begin 
    txt := Memo.Text; 
    vRead:= 0; 
    PrevWhite := True; 
    for i := 1 to Length(txt) do 
    begin 
    ThisWhite := Character.IsWhiteSpace(txt[i]); 
    if PrevWhite and not ThisWhite then 
    begin 
     Inc(vRead); 
     PrevWhite := False; 
    end; 
    PrevWhite := ThisWhite; 

    if vRead = BlockNumber then 
    begin 
     Memo.SelStart := vRead; 
     Memo.SetFocus; 
     Exit; 
    end; 
    end; 
end; 

Répondre

6

(1)

Cela fonctionne:

function TForm1.CountBlocks: integer; 
var 
    i: Integer; 
    txt: string; 
    ThisWhite, PrevWhite: boolean; 
begin 
    txt := Memo1.Text; 
    result:= 0; 
    PrevWhite := true; 
    for i := 1 to Length(txt) do 
    begin 
    ThisWhite := Character.IsWhiteSpace(txt[i]); 
    if PrevWhite and not ThisWhite then 
    begin 
     inc(result); 
     PrevWhite := false; 
    end; 
    PrevWhite := ThisWhite; 
    end; 
end; 

Cependant, il peut être optimisé si des informations plus détaillées sur le contenu du mémo est disponible. Par exemple, si vous savez que chaque ligne est composée de quatre blocs, alors le nombre de blocs est simplement 4*Memo1.Lines.Count. Mon code ci-dessus acceptera même des blocs de largeur différente.

(2)

remplacer simplement

for i := 1 to Length(txt) do 

par

for i := 1 to Memo1.SelStart + 1 do 
+0

Qu'est-ce que Character.IsWhiteSpace? Je reçois une erreur d'identificateur non déclarée. Je ne connais pas le nombre de blocs sur chaque ligne, ça va par la largeur du TMemo. Je vais éditer la question pour inclure le code d'obtention du code hexadécimal. –

+1

@Blobby: Ajoutez 'Character' à votre clause' uses'. –

+0

+1 Je ne savais même pas d'une telle unité :) –

2

Puisque vous êtes dans le contrôle de la mise en forme de vos lignes et les lignes ont un format fixe, il est très facile de calculer le nombre d'octets affichés sans recourir à une boucle à travers les lignes individuelles une fois. Chaque ligne affiche 3 caractères par octet, et chaque ligne autre que la dernière ligne affiche 16 octets, soit 48 caractères par ligne complète de 16 octets. Utilisez ces faits à votre avantage pour calculer le nombre d'octets en fonction du nombre de lignes complètes de 16 octets présents, et vous pouvez ajouter sur le nombre d'octets restants de seulement la dernière ligne:

function CountWordBlocks(Memo: TMemo): Integer; 
var 
    Count: Integer; 
begin 
    Count := Memo.Lines.Count; 
    if Count > 0 then 
    Result := (16 * (Count-1)) + (Length(Memo.Lines[Count-1]) div 3); 
    else 
    Result := 0; 
end; 

Vous pouvez faire quelque chose de similaire à traduire un décalage de caractères dans le mémo dans un numéro de bloc de travail:

function GetCurrentWordBlock(Memo: TMemo): Integer; 
var 
    SelStart, LineStart, LineNum: Integer 
begin 
    Result := 0; 
    SelStart := Memo.SelStart; 
    if SelStart < 0 then Exit; 
    LineStart := Memo.Perform(EM_LINEINDEX, SelStart, 0); 
    if LineStart < 0 then Exit; 
    LineNum := Memo.Perform(EM_LINEFROMCHAR, LineStart, 0); 
    Result := (16 * LineNum) + ((SelStart - LineStart) div 3) + 1; 
end; 

pour sélectionner un numéro de bloc donné, vous pouvez le faire:

procedure FindBlock(Memo: TMemo; BlockNumber: Integer); 
var 
    LineNum, LineStart: Integer; 
begin 
    if BlockNumber < 1 then Exit; 
    LineNum = (BlockNumber - 1) div 16; 
    LineStart = Memo.Perform(EM_LINEINDEX, LineNum, 0); 
    if LineStart < 0 then Exit; 
    Memo.SelStart = LineStart + (((BlockNumber - 1) - (16 * LineNum)) * 3); 
    Memo.SelLength := 2; 
    Memo.SetFocus; 
end; 
+0

Merci pour votre contribution Remy. compter les blocs semble encore plus facile en utilisant votre réponse. Les deux très bonnes solutions. –

+0

Je ne comprends pas. Vous voulez certainement dire "4 * (Compte - 1)"? Quoi qu'il en soit, le PO a dit (dans un commentaire à ma réponse), que le nombre de blocs par ligne pourrait ne pas toujours être égal à quatre, mais peut varier. ** UPDATE ** OK, je vois maintenant que le Q de l'OP a été mis à jour ... –

+0

La capture d'écran de Blobby montre seulement les blocs '4' affichés par ligne, mais le code dans sa fonction' ReadFileAsHex() 'va jusqu'à' 16 'blocs par ligne. Tous mes extraits de code sont basés sur cela. Si en réalité, le nombre de blocs par ligne est basé sur la largeur de 'TMemo', remplacez simplement' 16' par le nombre de blocs qui correspondent réellement à une ligne, ce qui pourrait être déterminé dynamiquement en divisant la longueur de la première ligne par '3'. –