如何从 TRichEdit 控件中完全删除选择栏?

Posted

技术标签:

【中文标题】如何从 TRichEdit 控件中完全删除选择栏?【英文标题】:How to completely remove the selection bar from a TRichEdit control? 【发布时间】:2013-06-05 11:51:24 【问题描述】:

TRichEdit 控件中每一行的左侧都有一个不可见的空间,光标变为右上箭头,当您单击该处时,整行被选中。当 TRichEdit 的文本对齐是居中或右时,很容易看到它。我相信这个空间被称为选择栏

TMemo 控件中不存在这样的栏。

我的问题:

如何移除这个选择栏,使光标行为与TMemo 中的相同?

我使用的是 Delphi 7,没有 TRichEdit 属性来控制这种行为。

有一个ECO_SELECTIONBAR 值可以与EM_SETOPTIONS 消息一起使用,但它只会添加或删除选择栏的一小部分(仅当您想将选择栏添加到TRichEdit 具有左对齐)。

【问题讨论】:

+1 好问题,我认为你没有办法禁用这种行为 【参考方案1】:

感谢大家的回答。

由于似乎没有“正确”的方法来做到这一点,我设计了以下解决方案:

unit TRichEditRemoveSelectionBar;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ComCtrls;

type
  TForm1 = class(TForm)
    RichEdit1: TRichEdit;
    procedure RichEdit1MouseMove(Sender: TObject; Shift: TShiftState; X,
      Y: Integer);
    procedure RichEdit1MouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure RichEdit1MouseUp(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
  private
     Private declarations 
  public
     Public declarations 
  end;

var
  Form1: TForm1;
  B: Boolean = False;

implementation

$R *.dfm

// ------------------------------------------------------------------------- //

procedure TForm1.RichEdit1MouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
begin
  if (GetCursor <> Screen.Cursors[crDefault]) and
     (GetCursor <> Screen.Cursors[crIBeam]) then
  begin
    SetCursor(Screen.Cursors[crIBeam]);
    B := True;
  end else
    B := False;
end;

procedure TForm1.RichEdit1MouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  if B then
  begin
    SetCursor(Screen.Cursors[crIBeam]);
    RichEdit1.SelLength := 0;
  end;
end;

procedure TForm1.RichEdit1MouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  if B then
    SetCursor(Screen.Cursors[crIBeam]);
end;

// ------------------------------------------------------------------------- //

end.

它一点也不优雅,但它完成了工作。

请注意,此代码不允许双击整行选择,也不能处理三次单击全文选择。为此,您可能必须使用拦截器类。

【讨论】:

【参考方案2】:

没有记录的方法可以为富编辑控件禁用此行为。没有样式、消息或函数可以提供任何方式来禁用此行为。

您提到的ES_SELECTIONBAR 样式允许在文本左对齐时添加小边距。富编辑控件的 Delphi 包装器不包含 ES_SELECTIONBAR 样式,因此您不能将其删除,因为它从一开始就不存在。

对于居中和右对齐的文本,无论ES_SELECTIONBAR 样式是否存在,选择区域始终存在。事实上,ES_SELECTIONBAR 样式似乎对控件对居中和右对齐文本的行为没有任何影响。

我希望,如果您对该选择区域的实现进行逆向工程,您将能够通过修改富编辑控件的窗口过程来移除该行为。

【讨论】:

【参考方案3】:

尝试使用SetWindowLong() 从RichEdit 中删除ES_SELECTIONBAR 窗口样式,例如:

dwStyle := GetWindowLong(RichEdit1.Handle, GWL_STYLE);
SetWindowLong(RichEdit1.Handle, GWL_STYLE, dwStyle and not ES_SELECTIONBAR);

或者,从TRichEdit 派生一个新组件,或使用拦截器类来覆盖虚拟CreateParams() 方法以删除样式:

type
  TMyRichEdit = class(TRichEdit)
  protected
    procedure CreateParams(var Params: TCreateParams); override;
  end;

Procedure TMyRichEdit.CreateParams(var Params: TCreateParams);
Begin
  inherited;
  Params.Style := Params.Style and not ES_SELECTIONBAR;
End;

【讨论】:

ES_SELECTIONBAR 从未添加到样式中,因此删除不存在的内容不会改变任何内容。

以上是关于如何从 TRichEdit 控件中完全删除选择栏?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Android 中完全禁用上下文操作栏?

QT如何设置QTableWidget控件占满下方?

常用组件的使用- TRichEdit文本内容显示组件

从 android 上的操作栏中删除图标/徽标

有人知道如何从导航栏中删除不需要的动画吗?截图

TRichEdit 如何测量文本的高度