سؤال

لدي Delphi 2007 Trichedit مع عدة خطوط فيه. أرغب في تمرير الغريميت رأسياً بحيث يكون رقم سطر معين إذا كان يتركز تقريبًا في منطقة العرض المرئية/الشاشة في Richedit. على سبيل المثال ، أريد أن أكتب رمز CenterLineInrichedit في هذا المثال:

procedure CenterLineInRichEdit(Edit: TRichEdit; LineNum: Integer);
begin
  ...
  Edit.ScrollTo(...);
end;

procedure TForm1.FormCreate(Sender: TObject);
var
  REdit: TRichEdit;
  i: Integer;
begin
  REdit := TRichEdit.Create(Self);
  REdit.Parent := Self;
  Redit.ScrollBars := ssVertical;
  REdit.SetBounds(10, 10, 200, 150);
  for i := 1 to 25 do
    REdit.Lines.Add('This is line number ' + IntToStr(i));
  CenterLineInRichEdit(REdit, 13);
end;

لقد بحثت في استخدام رسالة WM_VSCROLL ، ويسمح بالتمرير لأعلى/لأسفل سطر واحد ، وما إلى ذلك ، ولكن لا يتم التمرير إلى مركز محدد.

هل كانت مفيدة؟

المحلول

جرب هذا.

procedure VertCenterLine(RichEdit: TRichEdit; LineNum: Integer);
// I don't know the reason but the RichEdit 2 control in VCL does not
// respond to the EM_SCROLLCARET in Richedit.h but it does so to the
// constant in WinUser.h
const
  EM_SCROLLCARET  = $00B7;
var
  TextPos: lResult;
  Pos: TSmallPoint;
begin
  TextPos := SendMessage(RichEdit.Handle, EM_LINEINDEX, LineNum, 0);

  if TextPos <> -1 then begin
    // Go to top
    SendMessage(RichEdit.Handle, EM_SETSEL, 0, 0);
    SendMessage(RichEdit.Handle, EM_SCROLLCARET, 0, 0);

    // Get the coordinates for the beginning of the line
    Longint(Pos) := SendMessage(RichEdit.Handle, EM_POSFROMCHAR, TextPos, 0);

    // Scroll from the top
    SendMessage(RichEdit.Handle, WM_VSCROLL,
        MakeWParam(SB_THUMBPOSITION, Pos.y - RichEdit.ClientHeight div 2), 0);

    // Optionally set the caret to the beginning of the line
    SendMessage(RichEdit.Handle, EM_SETSEL, TextPos, TextPos);
  end;
end;

فيما يلي بديل من حيث أنه يركز على حدث أول سلسلة بدلاً من رقم السطر ؛

procedure VertCenterText(RichEdit: TRichEdit; Text: string);
const
  EM_SCROLLCARET  = $00B7;
var
  FindText: TFindText;
  TextPos: lResult;
  Pos: TSmallPoint;
begin
  FindText.chrg.cpMin := 0;
  FindText.chrg.cpMax := -1;
  FindText.lpstrText := PChar(Text);
  TextPos := SendMessage(RichEdit.Handle, EM_FINDTEXT,
      FR_DOWN or FR_WHOLEWORD, Longint(@FindText));

  if TextPos <> -1 then begin
    SendMessage(RichEdit.Handle, EM_SETSEL, 0, 0);
    SendMessage(RichEdit.Handle, EM_SCROLLCARET, 0, 0);

    Longint(Pos) := SendMessage(RichEdit.Handle, EM_POSFROMCHAR, TextPos, 0);
    SendMessage(RichEdit.Handle, WM_VSCROLL,
        MakeWParam(SB_THUMBPOSITION, Pos.y - RichEdit.ClientHeight div 2), 0);

    SendMessage(RichEdit.Handle, EM_SETSEL, TextPos, TextPos);
  end;
end;

نصائح أخرى

بناءً على الأفكار هنا ، توصلت إلى حل واحد. يفترض أن جميع الخطوط الموجودة في Richedit هي نفس الارتفاع وأن الخط الافتراضي لـ Richedit يشير إلى ارتفاعه بشكل صحيح ، لكنه قد يكون مفيدًا لبعض الناس:

type
  TCustomEditHack = class(TCustomEdit);

procedure CenterLineInEdit(Edit: TCustomEdit; LineNum: Integer);
var
  VisibleLines: Integer;
  TopLine: Integer;
  FirstLine: Integer;
begin
  FirstLine := Edit.Perform(EM_GETFIRSTVISIBLELINE, 0, 0);
  VisibleLines := Round(Edit.ClientHeight / Abs(TCustomEditHack(Edit).Font.Height));

  if VisibleLines <= 1 then
    TopLine := LineNum
  else
    TopLine := Max(LineNum - Round((VisibleLines/2)) + 1, 0);

  if FirstLine <> TopLine then
    Edit.Perform(EM_LINESCROLL, 0, TopLine - FirstLine);
end;

لقد اختبرت هذا مع Trichedit ، لكنه قد يعمل مع TMEMO أيضًا.

أرسل رسالة em_linescroll إلى Richedit:

SendMessage(REdit.Handle, EM_LINESCROLL, 0, NumberOfVerticalLinesToScroll);

انظر em_linescroll msdn topic.

ستحتاج إلى استخدام بضع رسائل Windows لمعالجة هذا الجانب من سيطرتك بطريقة عامة:

  • em_getfirstvisibleline لاسترداد رقم السطر المرئي الحالي ، أعلى (0)
  • em_linescroll لتمرير النص لأعلى/لأسفل بعدد محدد من الخطوط

ستحتاج إلى حساب عدد الخطوط التي يجب التمرير لأعلى/لأسفل من الخط العلوي الحالي لجلب رقم السطر المطلق المطلوب في العرض ، ولكن سيتعين عليك حساب عدد الخطوط المرئية في التحكم بنفسك (باستخدام مقاييس الخط والتحكم ارتفاع).

لاحظ أنه من خلال عنصر تحكم غني ، قد يختلف ارتفاع كل سطر وفقًا للخطوط المطبقة على النص في عنصر التحكم ، لذلك من المحتمل أن يكون أي نهج يعتمد على أرقام الأسطر وحدها دقيقة تقريبًا. كما أنني لست متأكدًا من أنه من الممكن تحديد النطاق المرئي الحالي لعنصر التحكم (أي عدد الخطوط المرئية حاليًا) مباشرةً ، لذا فإن حسابه بنفسك ضروري.

من الذاكرة ، تحكم متزامن يوفر بعض التحكم الإضافي في مثل هذه الأشياء ، مما يوفر قراءة/كتابة على حد سواء السطر العلوي الممتلكات وكذلك أ LinesInwindow منشأه. ومع ذلك ، أعتقد أن Synedit ليس نصًا غنيًا قادرًا ، ولكن إذا لم يكن هذا في الواقع مصدر قلق في تطبيقك (أي يمكنك استخدام خط متسق لجميع الخطوط في المحتوى) ، فقد يكون بديلاً جذابًا أو مناسبًا.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top