Memoで縦位置を中央揃えするには?

解決


かんとく  2010-06-19 01:08:24  No: 38677

お世話になっております。

XP,Delphi2007です。

Memoで、縦位置を中央揃えすることはできますか?

例えば、縦サイズが大きいMemoに文字を入力する場合、Memoの縦位置の中央で入力できるようにしたいです。

よろしくお願いします。


かんとく  2010-06-19 01:50:38  No: 38678

Memoって書きましたが、RichEditでも同じように縦位置を中央揃えしたいです。

よろしくお願いします。


tor  2010-06-19 03:43:10  No: 38679

コントロールにEM_SETRECTを送ると編集領域の位置や大きさを設定できるので
文字列が中央にくるように変更してやればよいかと。
と言っても文字列のサイズを求めるのがちょっと面倒そうですけれど、とりあえずやっつけで……

type
  TDummyMemo = class(TCustomMemo); // TCustomMemoのprotectedプロパティにアクセスするのに使う

procedure TForm1.vcenter_memo(memo: TCustomMemo);
var
  rc: TRect;
  tmp_canvas: TCanvas;
  line_count, char_index: Integer;
  y_start, y_end: Integer;
  hi: Integer;
begin
  // 現在の文字列の高さを計算
  tmp_canvas := Canvas; // 文字サイズを求めるためTForm.Canvasを借りる
  tmp_canvas.Font.Assign(TDummyMemo(memo).Font);

  if memo is TRichEdit then
  begin
    // 段落ごとにフォントが異なっていたりすると単純には計算できないので
    // 文字の座標を問い合わせ、そこから全体の高さを求める
    line_count := memo.Perform(EM_GETLINECOUNT, 0, 0);
    char_index := memo.Perform(EM_LINEINDEX, line_count - 1, 0);
    y_start := HIWORD(memo.Perform(EM_POSFROMCHAR, 0, 0)); // 最初の行のY座標を...
    y_end := HIWORD(memo.Perform(EM_POSFROMCHAR, char_index, 0)); // 最後の行のY座標から引いて...
    hi := y_end - y_start + tmp_canvas.TextHeight(' '); // さらに最後の行の高さを足す
  end
  else // TMemoの場合
  begin
    // memo.Lines.Countだと最後の行が空白の時に正しく計算できないので
    // EM_GETLINECOUNTで問い合わせる
    hi := tmp_canvas.TextHeight(' ') * memo.Perform(EM_GETLINECOUNT, 0, 0);
  end;

  // テキストが中央にくるよう、編集領域の範囲を計算
  rc := memo.ClientRect;
  rc.Top := (rc.Top + rc.Bottom - hi) div 2;
  rc.Bottom := rc.Top + hi;
  // 境界線の分を引いておく
  // TRichEditだと、BorderStyleにかかわらず引いておかないといけないみたい
  InflateRect(rc, 0, GetSystemMetrics(SM_CYEDGE));

  // 領域を設定する
  memo.Perform(EM_SETRECT, 0, LParam(@rc));
end;

こんな感じのメソッドを作って、OnChangeとかOnResizeのタイミングで呼んでみてはどうでしょう。


かんとく  2010-06-21 23:17:40  No: 38680

ありがとうございます。

OnChangeから、教えていただいたメソッドを呼び出して、思い通りになりました。

ありがとうございました。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加