2010. május 25., kedd

How to limit the number of characters per line and the number of lines in a TMemo


Problem/Question/Abstract:

Is there any way to control the amount of characters per line in a TMemo component, e.g. that I can only store 7 lines of 50 chars each. The MaxLength property does not help in this case as it controls the total number of characters in the control.

Answer:

Limiting a memo to 6 lines of input:

procedure TForm1.Memo1KeyPress(Sender: TObject; var Key: Char);
var
  line: Integer;
begin
  if key = #13 then
  begin
    with Sender as TMemo do
    begin
      if lines.count >= 6 then
      begin
        key := #0;
        line := Perform(EM_LINEFROMCHAR, SelStart, 0);
        if line < 5 then
          SelStart := Perform(EM_LINEINDEX, line + 1, 0);
      end;
    end;
  end;
end;

Limiting a memo to 5 lines of input of max. 25 characters each:

procedure TForm1.Memo1KeyPress(Sender: TObject; var Key: Char);
var
  line, col: Integer;
begin
  with Sender as TMemo do
  begin
    line := Perform(EM_LINEFROMCHAR, SelStart, 0);
    col := SelStart - Perform(EM_LINEINDEX, line, 0);
    if key = #8 then
    begin
      { Do not allow backspace if caret is on first column and deleting the
                        linebreak of the line in front would result in a line of more than 25
                        characters. Inconvenient for the user but specs are specs... }
      if (col = 0) and (line > 0) then
      begin
        if (Length(lines[line]) + Length(lines[line - 1])) > 25 then
          Key := #0;
      end;
    end
    else if key in [#13, #10] then
    begin
      { Handle hard linebreaks via Enter or Ctrl-Enter }
      if lines.count >= 5 then
      begin
        { Max number of lines reached or exceeded, set caret to start of next
                                line or this line, if on the last }
        key := #0;
        if line = 4 then
          SelStart := Perform(EM_LINEINDEX, line, 0)
        else
          SelStart := Perform(EM_LINEINDEX, line + 1, 0);
      end;
    end
    else if Key >= ' ' then
    begin
      { Do swallow key if current line has reached limit. }
      if Length(lines[line]) >= 25 then
        Key := #0;
    end;
  end;
  if Key = #0 then
    Beep;
end;

procedure TForm1.Memo1KeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
var
  line, col: Integer;
begin
  if Key = VK_DELETE then
    with Sender as TMemo do
    begin
      line := Perform(EM_LINEFROMCHAR, SelStart, 0);
      col := SelStart - Perform(EM_LINEINDEX, line, 0);
      if col = Length(lines[line]) then
        if (line < 4) and ((Length(lines[line]) + Length(lines[line + 1])) > 25) then
        begin
          key := 0;
          Beep
        end;
    end;
end;

Nincsenek megjegyzések:

Megjegyzés küldése