Search code examples
delphidelphi-2007

How can I highlight a line in TMemo?


I would like to highlight the line that contains the caret in a TMemo control, similar to the editor in the Delphi IDE. I tried the following code and it kind of works: (Sorry for the With-statement, this needs refactoring.)

procedure TMemo.WMPaint(var Message: TWMPaint);
var
  PS: TPaintStruct;
  DC: Hdc;
  Canvas: TCanvas;
  LineIdx: Integer;
  X, Y: Integer;
  Max: Integer;
  s: string;
  h: Integer;
begin
  DC := Message.DC;
  if DC = 0 then
    DC := BeginPaint(Handle, PS);
  Canvas := TCanvas.Create;
  try
    Canvas.Handle := DC;
    Canvas.Font.Name := Font.Name;
    Canvas.Font.Size := Font.Size;
    with Canvas do begin
      Max := TopLine + VisibleLines;
      if Max > Pred(Lines.Count) then
        Max := Pred(Lines.Count);

      Brush.Color := Self.Color;
      FillRect(Self.ClientRect);

      Brush.Color := clYellow;
      h := Canvas.TextHeight('Mg');
      Y := (Line - TopLine) * h;
      Marker.Top := y + self.Top;
      FillRect(Rect(0, Y, ClientRect.Right, Y + h));
      Brush.Color := Self.Color;

      Y := 1;
      for LineIdx := TopLine to Max do begin
        X := 2;
        s := Lines[LineIdx];
        if LineIdx = Line then
          Brush.Color := clYellow
        else
          Brush.Color := Self.Color;
        TextOut(X, Y, s);
        Inc(Y, h);
      end;
    end;
  finally
    if Message.DC = 0 then
      EndPaint(Handle, PS);
  end;
  Canvas.Free;
  inherited;
end;

(This code is added to the memo through an interposer class.)

This works, but it isn't triggered often enough. E.g. when I scroll using the down arrow.

I could, of course now start adding all kinds of events in order to call the memo's invalidate method and so forcing a repaint, but that doesn't seem right. Maybe there is already such a component, that I could just use? I already checked TJvMemo from the Jvcl which doesn't seem to have such a feature.

Edit: I ended up using SynEdit.


Solution

  • TMemo doesn't support that feature natively, and attempting to add that feature will lead to no end of headaches.

    Instead, consider using a different text-editing control. That's what the Delphi IDE does. SynEdit, for example, supports the feature: Set the ActiveLineColor property to something other than clNone.