吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 1037|回复: 5
收起左侧

[求助] 在RichViewEdit控件中如何去选择一个查找到的关键字?

  [复制链接]
冥界3大法王 发表于 2023-3-20 14:57
或者是设置I形光标的位置?

在上一贴中lovemit帮助解决了大问题
@lovemit
还有最后一问题搞不明白如何设置?

帮助中有以下小节是这么说的,感觉有门就是不知咋调用?

Functions from RVLinear Unit
Top  Previous  Next  


const

  RVCharsPerLineBreak: Integer = 2;

  RVNonTextCharacter: TRVUnicodeChar = ' ';



function RVGetLinearCaretPos(rve: TCustomRichViewEdit;
  CharsPerLineBreak: Integer = -1): Integer;
procedure RVSetLinearCaretPos(rve: TCustomRichViewEdit; LinearPos: Integer;
  CharsPerLineBreak: Integer = -1);

RVGetLinearCaretPos returns the caret position (as a number of characters before the caret). Non-text objects (except for tables and tabulators) are treated as one character, line breaks are treated as CharsPerLineBreak characters.

RVSetLinearCaretPos moves the caret to the specified position.



Value of CharsPerLineBreak parameter

Meaning


2

Use #13#10 to separate lines


1

Use #13 to separate lines


0

Lines are not separated


-1

Use the value of RVCharsPerLineBreak global variable (which, in its order, may be 2, 1, or 0)


procedure RVGetSelection(rv: TCustomRichView; out SelStart, SelLength: Integer;
  CharsPerLineBreak: Integer = -1);
procedure RVSetSelection(rv: TCustomRichView; SelStart, SelLength: Integer;
  CharsPerLineBreak: Integer = -1);

RVGetSelection returns the selection position in memo/richedit-like parameters (SelStart and SelLength). RVSetSelection sets selection by these values.

type

  TRVSelection = record

    SelStart, SelLength: Integer;

    MultiCell: Boolean;

    StartRow, StartCol, RowOffs, ColOffs: Integer;

  end;

procedure RVGetSelectionEx(rv: TCustomRichView; out Selection: TRVSelection;
  CharsPerLineBreak: Integer = -1);
procedure RVSetSelectionEx(rv: TCustomRichView; const Selection: TRVSelection;
  CharsPerLineBreak: Integer = -1);

RVGetSelectionEx returns the selection position in TRVSelection record. RVSetSelectionEx sets selection by this record. These functions can handle not only a normal selection, but a multicell selection in tables as well.

function RichViewToLinear(rv: TCustomRichView; CurRVData, RVData: TCustomRVData;
  ItemNo, ItemOffs: Integer; out LinearPos: Integer;
  CharsPerLineBreak: Integer = -1): Boolean;
function LinearToRichView(rv: TCustomRichView; CurRVData: TCustomRVData;
  var LinearPos: Integer; out RVData: TCustomRVData;
  out ItemNo, ItemOffs: Integer; CharsPerLineBreak: Integer = -1): Boolean;

RichViewToLinear converts the position specified in TRichView coordinates (RVData ? document, ItemNo ? index of item in this document, ItemOffs ? offset in this item) to a linear coordinate (a number of characters from the beginning of CurRVData before this position). Non-text objects (except for tables and tabulators) are treated as one character, line breaks are treated as CharsPerLineBreak characters. LinearToRichView performs an opposite conversion.

function RVGetTextRange(rv: TCustomRichView;
  RangeStart, RangeLength: Integer;
  CharsPerLineBreak: Integer = -1): TRVUnicodeString;
function RVGetTextLength(rv: TCustomRichView;
  CharsPerLineBreak: Integer = -1): Integer;

RVGetTextRange returns text from rv, from RangeStart to RangeLength positions. Non-text items (except for the tables and tabulators) are returned as RVNonTextCharacter. As for line breaks, see the table about CharsPerLineBreak above.

The call RVGetTextRange(rv, 0, RVGetTextLength(rv)) returns the whole text.



All these functions are compatible, they calculate position identically (providing that the same value of CharsPerLineBreak is used). A text returned by RVGetTextRange has one-to-one correspondence to TRichView document (unlike text returned by the functions from RVGetText unit).

免费评分

参与人数 1吾爱币 +1 热心值 +1 收起 理由
liudeliu + 1 + 1 鼓励转贴优秀软件安全工具和文档!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

 楼主| 冥界3大法王 发表于 2023-3-20 15:01
还有以下的:
//  RichViewEdit1.SelectCurrentWord;        选择当前单词,但是搜索出来的咋去做到呢?
// RichViewEdit1.SelectWordAt(5, 2);         这个不行,咋感觉有门?
//  RichViewEdit1.SetSelectionBounds(1, 2, 3, 1);

下面写写官方实例:有参考的地方吗?
[Delphi] 纯文本查看 复制代码
unit SyntaxRichViewEdit;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  RVScroll, RichView, RVEdit, RVStyle, ExtCtrls;

type
  TSyntaxRichViewEdit = class(TRichViewEdit)
  private
    { Private declarations }
    FSyntaxUpdateTimer : TTimer;
    FTimerInterval : Cardinal;
    FSyntaxUpdating : boolean;
    FOnColorize: TNotifyEvent;
    procedure SetTimerInterval(Value: Cardinal);
  protected
    { Protected declarations }
    procedure DoUpdateSyntax(Sender: TObject);
  public
    { Public declarations }
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;

    procedure DoChange(ClearRedo: Boolean); override;
    procedure Undo; override;

    function ItemOffsToAbs(aItemNo, aOffs : integer) : integer;
    procedure AbsToItemOffs(aPos : integer; var aItemNo, aOffs : integer);
    procedure GetSelBounds(var aStart, aEnd : integer; var Inverted : boolean);
    procedure SetSelBounds(aStart, aEnd : integer; Inverted : boolean);
    function GetSelStart : integer;
    function GetSelEnd : integer;
    function GetSelLength : integer;
    procedure SetSelLength(aLen : integer);
    function GetAbsCaretPos : integer;
    procedure SetAbsCaretPos(aPos : integer);

    procedure Mark(aText : string; aStyleIndex : integer);
    procedure MarkBetween(aStartText, aEndText : string;
      aOuterStyleIndex, aInnerStyleIndex : integer;
      aAllowMultiline: boolean);
    procedure InsertTags(aTag1, aTag2 : string);
  published
    { Published declarations }
    property TimerInterval : Cardinal read FTimerInterval write SetTimerInterval default 100;
    property OnColorize: TNotifyEvent read FOnColorize write FOnColorize;
  end;

procedure Register;
function GetTextFromClipboard : string;

implementation

uses
  Clipbrd;

//------------------------------------------------------------------------------
procedure Register;
//------------------------------------------------------------------------------
begin
  RegisterComponents('RichView', [TSyntaxRichViewEdit]);
end;

//------------------------------------------------------------------------------
function GetTextFromClipboard : string;
//------------------------------------------------------------------------------
var
  Clipboard : TClipboard;
begin
  Clipboard := TClipboard.Create;
  Clipboard.Open;
  Result := Clipboard.AsText;
  Clipboard.Close;
  Clipboard.Free;
end;

//------------------------------------------------------------------------------
constructor TSyntaxRichViewEdit.Create(AOwner: TComponent);
//------------------------------------------------------------------------------
begin
  inherited Create(AOwner);
  Options := [rvoAllowSelection,rvoClientTextWidth,rvoShowPageBreaks,
              rvoAutoCopyText,rvoFormatInvalidate,rvoDblClickSelectsWord,
              rvoRClickDeselects];

  SetAddParagraphMode(False);

  FSyntaxUpdating := false;

  FTimerInterval := 100;

  FSyntaxUpdateTimer := TTimer.Create(nil);
  with FSyntaxUpdateTimer do
  begin
    Enabled := false;
    Interval := FTimerInterval;
    OnTimer := DoUpdateSyntax;
  end;
end;

//------------------------------------------------------------------------------
destructor TSyntaxRichViewEdit.Destroy;
//------------------------------------------------------------------------------
begin
  FSyntaxUpdateTimer.Free;
  inherited Destroy;
end;

//------------------------------------------------------------------------------
procedure TSyntaxRichViewEdit.DoChange(ClearRedo: Boolean);
//------------------------------------------------------------------------------
begin
  FSyntaxUpdateTimer.Enabled := false;
  if not FSyntaxUpdating then
  begin
    inherited DoChange(ClearRedo);

    if Assigned(FOnColorize) then // do nothing if no colorizer procedure defined
      FSyntaxUpdateTimer.Enabled := true;
  end;  
end;

//------------------------------------------------------------------------------
procedure TSyntaxRichViewEdit.Undo;
//------------------------------------------------------------------------------
begin
  BeginUpdate;
  if (UndoAction = rvutCustom) then
    inherited Undo;
  inherited Undo;
  EndUpdate;
end;

//------------------------------------------------------------------------------
procedure TSyntaxRichViewEdit.SetTimerInterval(Value: Cardinal);
//------------------------------------------------------------------------------
begin
  if (Value < 20) then Value := 20;
  if (FTimerInterval <> Value) then
  begin
    FTimerInterval := Value;
    FSyntaxUpdateTimer.Interval := FTimerInterval;
  end;
end;

//------------------------------------------------------------------------------
procedure TSyntaxRichViewEdit.DoUpdateSyntax(Sender: TObject);
//------------------------------------------------------------------------------
var
  OldSelStart,
  OldSelEnd : integer;
  OldInverted : boolean;
begin
  FSyntaxUpdateTimer.Enabled := false;
  FSyntaxUpdating := true;

  BeginUpdate;
  LockWindowUpdate(Handle);

  try
    GetSelBounds(OldSelStart, OldSelEnd, OldInverted);

    BeginUndoGroup(rvutCustom);
    SetUndoGroupMode(true);

    SelectAll;
    ApplyTextStyle(0);

    if (GetSelText <> '') then
    begin
      if Assigned(FOnColorize) then
        FOnColorize(Self);
    end;

    SetUndoGroupMode(false);

  finally
    LockWindowUpdate(0);
    EndUpdate;

    SetSelBounds(OldSelStart, OldSelEnd, OldInverted);

    FSyntaxUpdating := false;
  end;
end;

//------------------------------------------------------------------------------
function TSyntaxRichViewEdit.ItemOffsToAbs(aItemNo, aOffs : integer) : integer;
//------------------------------------------------------------------------------
var
  i, n : integer;
begin
  n := 0;
  for i := 0 to aItemNo-1 do
  begin
    if IsFromNewLine(i) then
      n := n + 1;

    if (GetItemStyle(i) >= 0) then // if it is a text item
      n := n + Length(GetItemText(i));
  end;
  n := n + aOffs-1;

  if IsFromNewLine(aItemNo) then
    n := n + 1;

  Result := n;
end;

//------------------------------------------------------------------------------
procedure TSyntaxRichViewEdit.AbsToItemOffs(aPos : integer;
  var aItemNo, aOffs : integer);
//------------------------------------------------------------------------------
var
  i, j, l, n : integer;
begin
  n := aPos;
  j := 0;
  for i := 0 to ItemCount-1 do
  begin
    j := i;

    l := 0;
    if (GetItemStyle(i) >= 0) then // if it is a text item
      l := Length(GetItemText(i));

    if IsFromNewLine(i) then
      l := l + 1;

    if n <= l then Break;

    n := n - l;
  end;

  if IsFromNewLine(j) then
    n := n - 1;

  aItemNo := j;
  aOffs := n + 1;
end;

//------------------------------------------------------------------------------
procedure TSyntaxRichViewEdit.GetSelBounds(var aStart, aEnd : integer;
  var Inverted : boolean);
//------------------------------------------------------------------------------
var
  aStartItem, aStartOffs,
  aEndItem, aEndOffs, i : integer;
begin
  RVData.GetSelectionBoundsEx(aStartItem, aStartOffs,
                              aEndItem, aEndOffs, false);

  aStart := ItemOffsToAbs(aStartItem, aStartOffs);
  aEnd := ItemOffsToAbs(aEndItem, aEndOffs);

  Inverted := (aStart > aEnd);
  if Inverted then
  begin // swap values
    i := aStart;
    aStart := aEnd;
    aEnd := i;
  end;
end;

//------------------------------------------------------------------------------
procedure TSyntaxRichViewEdit.SetSelBounds(aStart, aEnd : integer;
  Inverted : boolean);
//------------------------------------------------------------------------------
var
  aStartItem, aStartOffs,
  aEndItem, aEndOffs : integer;
begin
  AbsToItemOffs(aStart, aStartItem, aStartOffs);
  AbsToItemOffs(aEnd, aEndItem, aEndOffs);

  if Inverted then
    SetSelectionBounds(aEndItem, aEndOffs, aStartItem, aStartOffs)
  else
    SetSelectionBounds(aStartItem, aStartOffs, aEndItem, aEndOffs);
end;

//------------------------------------------------------------------------------
function TSyntaxRichViewEdit.GetSelStart : integer;
//------------------------------------------------------------------------------
var
  i : integer;
  f : boolean;
begin
  GetSelBounds(Result, i, f);
end;

//------------------------------------------------------------------------------
function TSyntaxRichViewEdit.GetSelEnd : integer;
//------------------------------------------------------------------------------
var
  i : integer;
  f : boolean;
begin
  GetSelBounds(i, Result, f);
end;

//------------------------------------------------------------------------------
function TSyntaxRichViewEdit.GetSelLength : integer;
//------------------------------------------------------------------------------
var
  aStart, aEnd : integer;
  f : boolean;
begin
  GetSelBounds(aStart, aEnd, f);
  Result := (aEnd - aStart);
end;

//------------------------------------------------------------------------------
procedure TSyntaxRichViewEdit.SetSelLength(aLen : integer);
//------------------------------------------------------------------------------
var
  aStartItem, aStartOffs,
  aEndItem, aEndOffs,
  aStart, aEnd : integer;
begin
  RVData.GetSelectionBoundsEx(aStartItem, aStartOffs,
                              aEndItem, aEndOffs, false);

  aStart := ItemOffsToAbs(aStartItem, aStartOffs);
  aEnd := ItemOffsToAbs(aEndItem, aEndOffs);

  if (aLen < 0) then aLen := 0;

  if (aEnd - aStart) = aLen then Exit;

  if (aLen > 0) then
    AbsToItemOffs(aStart + aLen, aEndItem, aEndOffs)
  else
  begin
    aEndItem := aStartItem;
    aEndOffs := aStartOffs;
  end;

  SetSelectionBounds(aStartItem, aStartOffs, aEndItem, aEndOffs);
end;

//------------------------------------------------------------------------------
function TSyntaxRichViewEdit.GetAbsCaretPos : integer;
//------------------------------------------------------------------------------
begin
  Result := ItemOffsToAbs(CurItemNo, OffsetInCurItem);
end;

//------------------------------------------------------------------------------
procedure TSyntaxRichViewEdit.SetAbsCaretPos(aPos : integer);
//------------------------------------------------------------------------------
var
  aItemNo, aOffs : integer;
begin
  AbsToItemOffs(aPos, aItemNo, aOffs);

  SetSelectionBounds(aItemNo, aOffs, aItemNo, aOffs);
end;

//------------------------------------------------------------------------------
procedure TSyntaxRichViewEdit.Mark(aText : string; aStyleIndex : integer);
//------------------------------------------------------------------------------
begin
  if ItemCount = 0 then Exit;
  SetSelectionBounds(0, GetOffsBeforeItem(0), 0, GetOffsBeforeItem(0));

  while SearchText(aText, [rvseoDown]) do
    ApplyTextStyle(aStyleIndex);
end;

//------------------------------------------------------------------------------
procedure TSyntaxRichViewEdit.MarkBetween(aStartText, aEndText : string;
  aOuterStyleIndex, aInnerStyleIndex : integer;
  aAllowMultiline: boolean);
//------------------------------------------------------------------------------
var
  StartItemNo, EndItemNo, i : integer;
  OldProtect : boolean;
begin
  if ItemCount = 0 then Exit;
  SetSelectionBounds(0, GetOffsBeforeItem(0), 0, GetOffsBeforeItem(0));

  while SearchText(aStartText, [rvseoDown]) do
  begin
    ApplyTextStyle(aOuterStyleIndex);

    StartItemNo := CurItemNo;

    if SearchText(aEndText, [rvseoDown]) then
    begin
      ApplyTextStyle(aOuterStyleIndex);

      EndItemNo := CurItemNo;

      If (StartItemNo < 1 + EndItemNo) then
      begin
        if not aAllowMultiline then
          for i := StartItemNo+1 to EndItemNo do
            if IsFromNewLine(i) then
              exit;
        OldProtect := (rvprConcateProtect in Style.TextStyles[aInnerStyleIndex].Protection);
        if not OldProtect then
          with Style.TextStyles[aInnerStyleIndex] do
            Protection := Protection + [rvprConcateProtect];

        for i := StartItemNo+1 to EndItemNo-1 do
          GetItem(i).StyleNo := aInnerStyleIndex;

        if not OldProtect then
          with Style.TextStyles[aInnerStyleIndex] do
            Protection := Protection - [rvprConcateProtect];
      end;
    end;
  end;
end;

//------------------------------------------------------------------------------
procedure TSyntaxRichViewEdit.InsertTags(aTag1, aTag2 : string);
//------------------------------------------------------------------------------
var
  OldSelStart, OldSelEnd, SelLen : integer;
  NewSelStart : integer;
  f : boolean;
begin
  BeginUpdate;
  LockWindowUpdate(Handle);
  try
    BeginUndoGroup(rvutInsert);
    SetUndoGroupMode(true);

    GetSelBounds(OldSelStart, OldSelEnd, f);
    SelLen := OldSelEnd - OldSelStart;

    SetAbsCaretPos(OldSelStart);
    InsertText(aTag1);

    NewSelStart := GetAbsCaretPos;

    SetAbsCaretPos(NewSelStart + SelLen);
    InsertText(aTag2);

    SetSelBounds(NewSelStart, NewSelStart + SelLen, f);

    SetUndoGroupMode(false);
  finally
    LockWindowUpdate(0);
    EndUpdate;
    //Change;
  end;
end;

end.
 楼主| 冥界3大法王 发表于 2023-3-20 15:08
下面的貌似好像有效果了:


CustomRichView.SetSelectionBounds
Top  Previous  Next  


Selects part of RichView document (for copying to the Clipboard)

procedure SetSelectionBounds(StartItemNo, StartItemOffs,

  EndItemNo, EndItemOffs: Integer);

Parameters

StartItemNo ? index of the first selected item.

StartItemOffs:

§if the first item is a text item, then the selection start is before the StartItemOffs-th character of string (characters in strings are counted from 1, the last position (after the text item) is text length+1). The exception is empty text items formatted with style having EmptyWidth>0; for them, the position after the item is 2.

§if the first item is not a text, then

·if StartItemOffs=0, then the selection start is before the first item;

·if StartItemOffs=1, then the selection start is after the first item.

EndItemNo ? index of the last selected item.

EndItemOffs:

§if the last item is a text item, then the selection end is before the EndItemOffs-th character of string (characters in strings are counted from 1, the last position (after the text item) is text length+1). The exception is empty text items formatted with style having EmptyWidth>0; for them, the position after the item is 2.

§if the last item is not a text, then

·if EndItemOffs=0, then the selection end is before the last item

·if EndItemOffs=1, then the selection end is after the last item.



Caret position

In TRichViewEdit, the caret is always at the end of the selection, so this method can be used to move caret.



Selection in table cells

Before making selecting inside a table cell, activates its editing:

var RVData: TCustomRVFormattedData;


RVData := TCustomRVFormattedData(Table.Cells[r,c].Edit);
RVData.SetSelectionBounds(...);



Deselection

There are two ways to deselect:

§to pass StartItemNo=-1

§to pass StartItemNo=EndItemNo and StartItemOffs=EndItemOffs (in editor, the caret is moved to the specified position).

Please be careful and do not specify incorrect values.



Additional information

This method does not repaint the component (use Invalidate)

This method generates OnSelect event.

There are two useful methods to work with SetSelectionBounds: GetOffsBeforeItem and GetOffsAfterItem.

This method must be called only when the document is formatted.

If you want to set selection bounds using richedit-like parameters (SelStart and SelLength), use RVSetSelection from RVLinear unit instead.

lovemit 发表于 2023-3-20 16:43
 楼主| 冥界3大法王 发表于 2023-3-20 20:23
lovemit 发表于 2023-3-20 16:43
这么多英文好复杂啊。

找个没人的地方高声朗读10遍英语,竟然懂了。
lovemit 发表于 2023-3-20 22:12
本帖最后由 lovemit 于 2023-3-20 23:33 编辑

[Delphi] 纯文本查看 复制代码
var
  lineNum, colNum: integer;
  searchStr: string;
begin
  searchStr := 'delphi';
  RichViewEdit1.Clear;
  RichViewEdit1.AllowSelection := true;
  RichViewEdit1.SetItemTextEdW(0, 'adlfadfadsfadfdelphiadslfjaldjf');
  RichViewEdit1.GetCurrentLineCol(lineNum, colNum);
  ShowMessageFmt('光标所在行:%s,列:%s', [lineNum.ToString, colNum.ToString]);   // 光标所在行和列。
  if not RichViewEdit1.SearchText(searchStr, [rvseoDown]) then // 查找到字符串【delphi】后自动选择
  begin
    ShowMessageFmt('未找到字符串:%s', [searchStr]);
  end;
end;


搜索测试:https://wwgp.lanzoue.com/iS2sY0qn2i4j


免费评分

参与人数 1吾爱币 +4 热心值 +1 收起 理由
冥界3大法王 + 4 + 1 用心讨论,共获提升!

查看全部评分

您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-24 23:25

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表