加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

如何增强Delphi中的默认备忘录控件,并能够为文本加下划线

发布时间:2020-12-15 09:48:52 所属栏目:大数据 来源:网络整理
导读:我正在尝试构建一个能够显示错误的简单脚本编辑器.我在网上搜索了一个可以为我显示/下划线错误的组件,但我找不到一个.所以我决定根据Delphi中包含的备忘录控件自己构建一个. 我打算在备忘录控件中添加以下功能: function下划线(startline,startchar,endline
我正在尝试构建一个能够显示错误的简单脚本编辑器.我在网上搜索了一个可以为我显示/下划线错误的组件,但我找不到一个.所以我决定根据Delphi中包含的备忘录控件自己构建一个.

我打算在备忘录控件中添加以下功能:

function下划线(startline,startchar,endline,endchar:integer);

这是我第一次加强像这样的视觉控制,我问是否有人可以大致勾勒出如何做到这一点.无需深入了解具体细节:)

ps:我不想使用richedit控件.

解决方法

下面是一些使用常规winapi的D2007代码示例,它将向您展示如何在可滚动的备忘录中找到绘制位置以及如何绘制简单的下划线.为简洁起见,它没有错误捕获/处理.还只允许一个下划线范围,因为作为组件的可用性不是样本的目的.尝试使用垂直滚动备忘录,但如果您愿意,如果出现问题,您应该能够微调细节.

在2K,XP和7上测试,XP上的外观如下:

memo with underlined text http://img687.imageshack.us/img687/8176/20101210061602.png

和代码:

type
  TMemo = class(stdctrls.TMemo)
  private
    FStartChar,FEndChar: Integer;
    procedure WMPaint(var Msg: TWMPaint); message WM_PAINT;
  public
    procedure Underline(StartLine,StartChar,EndLine,EndChar: Integer);
  end;

  TForm1 = class(TForm)
    Memo1: TMemo;
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
  public
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

{ TMemo }

procedure TMemo.Underline(StartLine,EndChar: Integer);
begin
  FStartChar := SendMessage(Handle,EM_LINEINDEX,StartLine,0) + StartChar;
  FEndChar := SendMessage(Handle,0) + EndChar;
  Invalidate;
end;

procedure TMemo.WMPaint(var Msg: TWMPaint);

  function GetLine(CharPos: Integer): Integer;
  begin
    Result := SendMessage(Handle,EM_LINEFROMCHAR,CharPos,0);
  end;

  procedure DrawLine(First,Last: Integer);
  var
    LineHeight: Integer;
    Pt1,Pt2: TSmallPoint;
    DC: HDC;
    Rect: TRect;
    ClipRgn: HRGN;
  begin
    // font height approximation (compensate 1px for internal leading)
    LineHeight := Abs(Font.Height) - Abs(Font.Height) div Font.Height;

    // get logical top-left coordinates for line bound characters
    Integer(Pt1) := SendMessage(Handle,EM_POSFROMCHAR,First,0);
    Integer(Pt2) := SendMessage(Handle,Last,0);

    DC := GetDC(Handle);

    // clip to not to draw to non-text area (internal margins)
    SendMessage(Handle,EM_GETRECT,Integer(@Rect));
    ClipRgn := CreateRectRgn(Rect.Left,Rect.Top,Rect.Right,Rect.Bottom);
    SelectClipRgn(DC,ClipRgn);
    DeleteObject(ClipRgn); // done with region

    // set pen color to red and draw line
    SelectObject(DC,GetStockObject(DC_PEN));
    SetDCPenColor(DC,RGB(255,0));
    MoveToEx(DC,Pt1.x,Pt1.y + LineHeight,nil);
    LineTo(DC,Pt2.x,Pt2.y + LineHeight);

    ReleaseDC(Handle,DC); // done with dc
  end;

var
  StartChar,LinePos: Integer;
begin
  inherited;
  if FEndChar > FStartChar then begin

    // Find out where to draw.
    // Can probably optimized a bit by using EM_LINELENGTH
    StartChar := FStartChar;
    CharPos := StartChar;
    LinePos := GetLine(CharPos);
    while True do begin
      Inc(CharPos);
      if GetLine(CharPos) > LinePos then begin
        DrawLine(StartChar,CharPos - 1);
        StartChar := CharPos;
        Dec(CharPos);
        Inc(LinePos);
        Continue;
      end else
        if CharPos >= FEndChar then begin
          DrawLine(StartChar,FEndChar);
          Break;
        end;
    end;
  end;
end;

{  --end TMemo-- }

procedure TForm1.Button1Click(Sender: TObject);
begin
  Memo1.Underline(7,14,8,17);
end;

编辑:忘记提及,在键入时你可能会删除下划线.我不知道它在键入时应该如何表现,并且可能很难实现所期望的行为.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读