2

今、私はこのコードを持っています。

procedure TForm1.Memo1Change(Sender : TObject);
begin
  SendMessage(Informacje.Handle, EM_LINESCROLL, 0, Memo1.Lines.Count);
end;

問題は、新しい行が追加されたときにメモ行を上にスクロールできないことです。スクロールアップ時にカーソルを最後に移動するのをやめ、スクロールバーが一番下にあるときにカーソルを最後に移動し始めます。助けてくれてありがとう。
言い換えれば。Memo との IRC チャットがあるとします。新しいメッセージです。キャレットは最後のメッセージの末尾にあります。今、スクロールバー(上)を使用して以前のメッセージを読みたいのですが、キャレットを下に戻す新しいメッセージがあるとは限りません。マウスのホイールを上に上げて停止し、メッセージを読み、その後、下にスクロールするときに前の状態に戻ります (新しいメッセージの最後にキャレットをもう一度)。

4

1 に答える 1

5

一番下までスクロールするかどうかを決定する条件が必要です。以下は簡単なテストで動作するようです。一番上の行と、メモが表示できる行の数を合計して、最後の行が表示されているかどうかを確認します。

procedure TForm1.Memo1Change(Sender: TObject);
var
  LineCount, TopLine: Integer;
begin
  LineCount := Memo1.Perform(EM_GETLINECOUNT, 0, 0) - 1;
  TopLine := Memo1.Perform(EM_GETFIRSTVISIBLELINE, 0, 0);
  if (TopLine + GetVisibleLineCount(Memo1)) >= LineCount then
    SendMessage(Memo1.Handle, EM_LINESCROLL, 0, LineCount);
end;

どこ

function GetVisibleLineCount(Memo: TMemo): Integer;
var
  DC: HDC;
  SaveFont: HFONT;
  TextMetric: TTextMetric;
  EditRect: TRect;
begin
  DC := GetDC(0);
  SaveFont := SelectObject(DC, Memo.Font.Handle);
  GetTextMetrics(DC, TextMetric);
  SelectObject(DC, SaveFont);
  ReleaseDC(0, DC);

  Memo.Perform(EM_GETRECT, 0, LPARAM(@EditRect));
  Result := (EditRect.Bottom - EditRect.Top) div TextMetric.tmHeight;
end;

(メモの変更ごとに計算する必要がないように、表示されている行数をキャッシュすることができます。)

ただし、コードをさらに微調整する必要がある場合があります.fiは、メモに表示できる行が少ない場合です. また、このコードはキャレットの位置を考慮していません。

于 2013-07-17T20:58:46.197 に答える