Блоки слова в TMemo - PullRequest
4 голосов
/ 09 марта 2012

Я пытаюсь сделать из Hemo обычного средства просмотра Hex, я знаю, что это, вероятно, не идеально, но только я лично использую его, так что это не имеет значения.

(1)

Во-первых, предположим, что записка заполнена шестнадцатеричной информацией, например, так:

enter image description here

Как можно получить счетчик всех текстовых блоковпоказано, игнорируя пустое пространство?Таким образом, при использовании изображения результат в этом случае будет 28.

Это то, что я пробовал, и я знаю, что это совершенно неправильно, так как я получаю доступ к строкам Memo, но я не знаю, как получить доступ к каждому символу.

Кажется, я не могу решить эту простую проблему: (

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)

Если я нажимаю на заметку и текстовый блок находится под курсором, как я могу узнать, какой номер у выбранного блока из всех остальных?

Таким образом, используя то же первое изображение, каретка находится в верхней строке рядом с 68, поэтому результат будет равен 3, поскольку это третий текстовый блок из 28.

Это должно быть так просто, но яне могу мыслить ясно, у меня пока нет правильного умения программирования, и поэтому я действительно борюсь с базовой логикой и решением проблем!

(3)

Наконец-то я бы хотелвыбрать блок во время выполнения, передав значение номера блока. Я попытался это без особогоccess:

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;

Ответы [ 2 ]

6 голосов
/ 09 марта 2012

(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*Memo1.Lines.Count.Мой код выше даже принимает блоки различной ширины.

(2)

Просто замените

for i := 1 to Length(txt) do

на

for i := 1 to Memo1.SelStart + 1 do
2 голосов
/ 09 марта 2012

Поскольку вы контролируете форматирование ваших строк и строки имеют фиксированный формат, очень легко рассчитать количество отображаемых байтов, не прибегая к циклическому прохождению по отдельным строкам по одному.Каждая строка отображает 3 символа на байт, а каждая строка, отличная от последней строки, отображает 16 байтов, то есть 48 символов на полную 16-байтовую строку.Используйте эти факты в своих интересах, чтобы рассчитать количество байтов на основе количества полных имеющихся 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; 
...