迷你5207专属论坛

注册

 

发新话题 回复该主题

TMemo高亮显示文字 [复制链接]

发表者
delphi在TMemo中实现高亮文字
在memo中实现类似IDE的效果,对数字及自定义的关键字高亮显示,并自定义关键字
  1. unit Unit1;

  2. interface

  3. uses
  4.   Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  5.   Dialogs, StdCtrls;
  6. type
  7.   TMemo = class(stdctrls.TMemo)
  8.   private
  9.     procedure WMPaint(var Message: TWMPaint); message WM_PAINT;
  10.     procedure WMSize(var Message: TWMSize); message WM_SIZE;
  11.     procedure WMMove(var Message: TWMMove); message WM_MOVE;
  12.     procedure WMVScroll(var Message: TWMMove); message WM_VSCROLL;
  13.     procedure WMMousewheel(var Message: TWMMove); message WM_MOUSEWHEEL;
  14.   protected
  15.     procedure Change; override;
  16.     procedure KeyDown(var Key: Word; Shift: TShiftState); override;
  17.     procedure KeyUp(var Key: Word; Shift: TShiftState); override;
  18.     procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
  19.       override;
  20.     procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
  21.       override;
  22.   public
  23.     PosLabel: TLabel;
  24.     procedure Update_label;
  25.     procedure GotoXY(mCol, mLine: Integer);
  26.     function Line: Integer;
  27.     function Col: Integer;
  28.     function TopLine: Integer;
  29.     function VisibleLines: Integer;
  30.   end;
  31. type
  32.   TForm1 = class(TForm)
  33.     Label1: TLabel;
  34.     GroupBox1: TGroupBox;
  35.     KeywordList: TListBox;
  36.     GroupBox2: TGroupBox;
  37.     GroupBox3: TGroupBox;
  38.     Memo1: TMemo;
  39.     Label2: TLabel;
  40.     procedure FormCreate(Sender: TObject);
  41.     procedure FormClose(Sender: TObject; var Action: TCloseAction);
  42.   private
  43.     { Private declarations }
  44.   public
  45.     { Public declarations }
  46.   end;

  47. var
  48.   Form1: TForm1;

  49. implementation

  50. {$R *.dfm}
  51. //分隔符,如有特殊需要自己添加
  52. function IsSeparator(Car: Char): Boolean;
  53. begin
  54.   case Car of
  55.     '.', ';', ',', ':', '?', '!', '"', '''',' ', '^', '+', '-', '*', '/', '\', '`', '[', ']', '(', ')', 'o', 'a', '{', '}', '%', '=': Result := True;
  56.   else
  57.     Result := False;
  58.   end;
  59. end;
  60. ////////////////////////////////////////////////////////////////////////////////

  61. function NextWord(var s: string; var PrevWord: string): string;
  62. begin
  63.   Result := '';
  64.   PrevWord := '';
  65.   if s = '' then Exit;
  66.   while (s <> '') and IsSeparator(s[1]) do
  67.   begin
  68.     PrevWord := PrevWord + s[1];
  69.     Delete(s, 1, 1);
  70.   end;
  71.   while (s <> '') and not IsSeparator(s[1]) do
  72.   begin
  73.     Result := Result + s[1];
  74.     Delete(s, 1, 1);
  75.   end;
  76. end;
  77. ////////////////////////////////////////////////////////////////////////////////

  78. function IsKeyWord(s: string): Boolean;
  79. begin
  80.   Result := False;
  81.   if s = '' then Exit;
  82.   Result := Form1.KeywordList.Items.IndexOf(lowercase(s)) <> -1;
  83. end;
  84. ////////////////////////////////////////////////////////////////////////////////

  85. function IsNumber(s: string): Boolean;
  86. var
  87.   i: Integer;
  88. begin
  89.   Result := False;
  90.   for i := 1 to Length(s) do
  91.     case s[i] of
  92.       '0'..'9': ;
  93.     else
  94.       Exit;
  95.     end;
  96.   Result := True;
  97. end;
  98. ////////////////////////////////////////////////////////////////////////////////
  99. ////////////////////////////////////////////////////////////////////////////////
  100. ////////////////////////////////////////////////////////////////////////////////
  101. // New or overrided methods and properties for TMemo using Interjected Class ///
  102. // Technique ///////////////////////////////////////////////////////////////////
  103. ////////////////////////////////////////////////////////////////////////////////

  104. function TMemo.VisibleLines: Integer;
  105. begin
  106.   Result := Height div (Abs(Self.Font.Height) + 2);
  107. end;
  108. ////////////////////////////////////////////////////////////////////////////////

  109. procedure TMemo.GotoXY(mCol, mLine: Integer);
  110. begin
  111.   Dec(mLine);
  112.   SelStart := 0;
  113.   SelLength := 0;
  114.   SelStart := mCol + Self.Perform(EM_LINEINDEX, mLine, 0);
  115.   SelLength := 0;
  116.   SetFocus;
  117. end;
  118. ////////////////////////////////////////////////////////////////////////////////

  119. procedure TMemo.Update_label;
  120. begin
  121.   if PosLabel = nil then Exit;
  122.   PosLabel.Caption := '(' + IntToStr(Line + 1) + ',' + IntToStr(Col) + ')';
  123. end;
  124. ////////////////////////////////////////////////////////////////////////////////

  125. function TMemo.TopLine: Integer;
  126. begin
  127.   Result := SendMessage(Self.Handle, EM_GETFIRSTVISIBLELINE, 0, 0);
  128. end;
  129. ////////////////////////////////////////////////////////////////////////////////

  130. function TMemo.Line: Integer;
  131. begin
  132.   Result := SendMessage(Self.Handle, EM_LINEFROMCHAR, Self.SelStart, 0);
  133. end;
  134. ////////////////////////////////////////////////////////////////////////////////

  135. function TMemo.Col: Integer;
  136. begin
  137.   Result := Self.SelStart - SendMessage(Self.Handle, EM_LINEINDEX,
  138.     SendMessage(Self.Handle,
  139.     EM_LINEFROMCHAR, Self.SelStart, 0), 0);
  140. end;
  141. ////////////////////////////////////////////////////////////////////////////////

  142. procedure TMemo.WMVScroll(var Message: TWMMove);
  143. begin
  144.   Update_label;
  145.   Invalidate;
  146.   inherited;
  147. end;
  148. ////////////////////////////////////////////////////////////////////////////////

  149. procedure TMemo.WMSize(var Message: TWMSize);
  150. begin
  151.   Invalidate;
  152.   inherited;
  153. end;
  154. ////////////////////////////////////////////////////////////////////////////////

  155. procedure TMemo.WMMove(var Message: TWMMove);
  156. begin
  157.   Invalidate;
  158.   inherited;
  159. end;
  160. ////////////////////////////////////////////////////////////////////////////////

  161. procedure TMemo.WMMousewheel(var Message: TWMMove);
  162. begin
  163.   Invalidate;
  164.   inherited;
  165. end;
  166. ////////////////////////////////////////////////////////////////////////////////

  167. procedure TMemo.Change;
  168. begin
  169.   Update_label;
  170.   Invalidate;
  171.   inherited Change;
  172. end;
  173. ////////////////////////////////////////////////////////////////////////////////

  174. procedure TMemo.KeyDown(var Key: Word; Shift: TShiftState);
  175. begin
  176.   Update_label;
  177.   inherited KeyDown(Key, Shift);
  178. end;
  179. ////////////////////////////////////////////////////////////////////////////////

  180. procedure TMemo.KeyUp(var Key: Word; Shift: TShiftState);
  181. begin
  182.   Update_label;
  183.   inherited KeyUp(Key, Shift);
  184. end;
  185. ////////////////////////////////////////////////////////////////////////////////

  186. procedure TMemo.MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
  187. begin
  188.   Update_label;
  189.   inherited MouseDown(Button, Shift, X, Y);
  190. end;
  191. ////////////////////////////////////////////////////////////////////////////////

  192. procedure TMemo.MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
  193. begin
  194.   Update_label;
  195.   inherited MouseUp(Button, Shift, X, Y);
  196. end;
  197. ////////////////////////////////////////////////////////////////////////////////

  198. procedure TMemo.WMPaint(var Message: TWMPaint);
  199. var
  200.   PS: TPaintStruct;
  201.   DC: HDC;
  202.   Canvas: TCanvas;
  203.   i: Integer;
  204.   X, Y: Integer;
  205.   OldColor: TColor;
  206.   Size: TSize;
  207.   Max: Integer;
  208.   s, Palabra, PrevWord: string;
  209. begin
  210.   DC := Message.DC;
  211.   if DC = 0 then DC := BeginPaint(Handle, PS);
  212.   Canvas := TCanvas.Create;
  213.   try
  214.     OldColor := Font.Color;
  215.     Canvas.Handle := DC;
  216.     Canvas.Font.Name := Font.Name;
  217.     Canvas.Font.Size := Font.Size;
  218.     with Canvas do
  219.     begin
  220.       Max := TopLine + VisibleLines;
  221.       if Max > Pred(Lines.Count) then Max := Pred(Lines.Count);

  222.       //Limpio la sección visible
  223.       Brush.Color := Self.Color;
  224.       FillRect(Self.ClientRect);
  225.       Y := 1;
  226.       for i := TopLine to Max do
  227.       begin
  228.         X := 2;
  229.         s := Lines[i];

  230.         //Detecto todas las palabras de esta línea
  231.         Palabra := NextWord(s, PrevWord);
  232.         while Palabra <> '' do
  233.         begin
  234.           Font.Color := OldColor;
  235.           TextOut(X, Y, PrevWord);
  236.           GetTextExtentPoint32(DC, PChar(PrevWord), Length(PrevWord), Size);
  237.           Inc(X, Size.cx);

  238.           Font.Color := clBlack;
  239.           if IsKeyWord(Palabra) then
  240.           begin
  241.             Font.Color := clHighlight;

  242.             TextOut(X, Y, Palabra);
  243.              {
  244.              //Draw dot underline
  245.              Pen.Color := clHighlight;
  246.              Pen.Style := psDot;
  247.              PolyLine([ Point(X,Y+13), Point(X+TextWidth(Palabra),Y+13)]);
  248.              }
  249.           end
  250.           else if IsNumber(Palabra) then
  251.           begin
  252.             Font.Color := $000000DD;
  253.             TextOut(X, Y, Palabra);
  254.           end
  255.           else
  256.           begin

  257.             TextOut(X, Y, Palabra);
  258.            end;
  259.           GetTextExtentPoint32(DC, PChar(Palabra), Length(Palabra), Size);
  260.           Inc(X, Size.cx);

  261.           Palabra := NextWord(s, PrevWord);
  262.           if (s = '') and (PrevWord <> '') then
  263.           begin
  264.             Font.Color := OldColor;
  265.             TextOut(X, Y, PrevWord);
  266.           end;
  267.         end;
  268.         if (s = '') and (PrevWord <> '') then
  269.         begin
  270.           Font.Color := OldColor;
  271.           TextOut(X, Y, PrevWord);
  272.         end;

  273.         s := 'W';
  274.         GetTextExtentPoint32(DC, PChar(s), Length(s), Size);
  275.         Inc(Y, Size.cy);
  276.       end;
  277.     end;
  278.   finally
  279.     if Message.DC = 0 then EndPaint(Handle, PS);
  280.   end;
  281.   Canvas.Free;
  282.   inherited;
  283. end;

  284. procedure TForm1.FormCreate(Sender: TObject);
  285. begin
  286.   Memo1.PosLabel := Label1;
  287.   Memo1.Update_label;
  288. end;

  289. procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
  290. begin
  291.   Action := caFree;
  292. end;

  293. end.
复制代码
分享 转发
TOP
发新话题 回复该主题