2012-03-08 11 views
4

TMemoから基本的な16進数のビューアを作成しようとしていますが、これはおそらく理想的ではないと私は知っていますが、TMemoのワードブロック

(1)

を第一に、メモがそうのような六角情報で満たされているとします

私は無視して、示されている全てのテキストブロックの数を得ることができますどのように

enter image description here

空白?だからイメージを使用すると、この場合の結果は28になります。

これは私が試したものですが、メモ行にアクセスしているので完全に間違っているとわかりますが、各文字にアクセスする方法はわかりません。私はここでは、この単純な問題:(

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; 

を解決するように見えるカント

は、私がメモに六角値を表示するために使用していたコードです:

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)

メモをクリックしてテキストブロックがカーソルの下にある場合、選択したブロックが他のすべての番号のどれに含まれているかをどのように知ることができますか?

だから同じ第1の画像を使用して、キャレットが68次トップラインであるので、これはそれほど容易でなければならない28

のうち第三のテキストブロックであるように、結果は3であろうが、私はっきりと考えることができない、私はまだ正しいプログラミングの心を持っていないので、基本的なロジックと問題を解決するために本当に闘争!

(3)

最後Iは、ブロック番号の値を渡すことによって、実行時にブロックを選択したいです。私は多くの成功なしにこれを試してみました:

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; 

答えて

6

(1)

これは動作します:

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; 

メモの内容に関するより詳細な情報が入手可能である場合は、それを最適化することができます。たとえば、各行が4つのブロックで構成されていることがわかっている場合、ブロックの数は単に4*Memo1.Lines.Countになります。上記の私のコードは、幅の異なるブロックを受け付けることさえできます。あなたが行の書式設定の制御であり、そして行は固定フォーマットを持っているので

(2)

を単純に、

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

Character.IsWhiteSpaceは何?私は宣言されていない識別子エラーを取得します。私は各行のブロックの数を知らない、それはTMemoの幅になる。質問を編集して16進数を取得するコードを追加します。 –

+1

@Blobby: 'uses'節に' Character'を追加してください。 –

+0

+1私はそのようなユニットについては知らなかった:) –

2

によって

for i := 1 to Length(txt) do 

を置き換えます個々のラインを1度にループすることなく、表示されているバイト数を計算するのは非常に簡単です。すべての行には1バイトあたり3文字が表示され、最後の行以外のすべての行には16バイトが表示されるため、完全な16バイト行あたり48文字が表示されます。現在、完全な16バイトのラインの数に基づいて、バイト数を計算するためにあなたの利点にそれらの事実を使用して、あなただけの最後の行からの残りのバイト数に追加することができます。

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; 

することができますワークブロックの数にメモ内のオフセット文字翻訳する似たような操作を行います。与えられたブロックの数を選択するには

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; 

を、あなたがこれを行うことができます:

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

入力いただきありがとうございます。あなたの答えを使ってブロックを数えるほうがずっと簡単です。両方とも非常に良い解決策です。 –

+0

私はこれを取得しません。確かにあなたは '4 *(Count - 1)'を意味しますか?とにかく、OPは(私の答えのコメントで)1行あたりのブロックの数は必ずしも4に等しいとは限りませんが、変わるかもしれないと言った。 ** UPDATE ** OK、OPのQが更新されたことを確認しました... –

+0

Blobbyのスクリーンショットでは、1行に4ブロックしか表示されませんが、 'ReadFileAsHex()'関数のコードは '16 '行ごとのブロック。私のコードスニペットはすべてそれに基づいています。実際には、1行あたりのブロック数が「TMemo」幅に基づいている場合は、実際に行に収まるブロックの数で単に「16」を置き換えます。これは、最初の行の長さ「3」である。 –