角丸の四角形に複数行の文字列を表示するには?

解決


デル太  2006-03-31 00:17:00  No: 20746

角丸の四角形に文字を表示することを考えています。
その文字を、四角形の領域に合わせて折り返し複数行表示したいのです。
シンプルに実現できるなら、四角形のサイズや表示文字数は固定にしてもかまいません。

どのような方法が考えられるでしょうか?

現在、角丸の四角形は、別スレッドでアドバイスいただいた情報をもとに次の2つの方法で実現できています。

  1)Win32のリージョンAPIを使ってDelphiのコンポーネントを変形させたTPanel
  2)TLabelのPaintメソッド内でRoundRectを使い描画する

このあと、文字列を複数行表示させる方法がわからずにおります。

1)はTPanelのキャプションを複数行に表示できればよいのかな?と想像しています。
2)で試したところ、角丸四角形を塗りつぶすとCaptionが消えてしまい、描画後にCaptionを設定すると描画が消えてしまいます。

どうぞ、アドバイスをいただけますか?
よろしくお願いします。


igy  2006-03-31 00:50:58  No: 20747

APIのDrawTextを使うのは、どうでしょう?


igy  2006-03-31 01:06:54  No: 20748

TLabelを使う場合、WordWrap プロパティをTrueにするとか。


デル太  2006-03-31 03:09:26  No: 20749

igyさん、アドバイスありがとうございます!

> APIのDrawTextを使うのは、どうでしょう?

おかげさまで、TLableをベースにAPIを使ってテキストを描画し、複数行表示できました。
今回の手法は他の場面でも応用できそうです。ありがとうございます。

TLabelは角丸の外側領域が(親の?)背景色で描かれるみたいですね。
他のラベルと重なった場合に、ちょっと汚く見えてしまうので、できればその部分を改善したいと思います。
そのためには、1)のTPanel方式で複数行表示すればいいのかもしれません。引き続き検討してみます。

> TLabelを使う場合、WordWrap プロパティをTrueにするとか。

Captionに指定したテキストは、Canvas.RoundRectで塗りつぶされてしまうみたいなんです。
それで、直接文字を描画することを考えました。
ほんとうはCaptionを使えると、シンプルに考えられていいのですけど・・。

DrawTextを使ったコードを添付します。

//Win32APIのDrawTextを利用して実装した例20060330 byデル太
//参考ページ:http://www2.ocn.ne.jp/~mizu/api/d/d0001.html←感謝m(__)m
//他のラベルと重なると、角丸の外側が汚くなるのが課題

unit Unit1;

interface

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

type
  TMyLabel = class(TLabel)
  protected
    procedure Paint; override;
  end;

  TForm1 = class(TForm)
    Button1: TButton;
    Label1: TLabel; //重なったときの表示を確認するためのもの
    procedure Button1Click(Sender: TObject);
  private
    { Private 宣言 }
  public
    { Public 宣言 }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

{ TMyLabel }

procedure TMyLabel.Paint;
var
  ARect: TRect;
  S: String;
begin
  inherited;
  ARect := Rect(5,5,Width -5, Height -5);
  S := 'この日本語文をラベルの表面に表示します'+#13+'改行も使えます';
  with Self do
  begin
    Canvas.Brush.Color := clRed;                   //赤いブラシで
    Canvas.RoundRect(0,0,Width, Height, 10, 10);   //角丸の四角形を表示
    DrawText(Self.Canvas.Handle, PChar(S), -1, ARect, DT_WORDBREAK); //ワードラップを指定
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  ALabel: TMyLabel;
begin
  ALabel := TMyLabel.Create(Self);
  ALabel.Top := 20;
  ALabel.Left := 20;
  ALabel.Width := 200;
  ALabel.Height := 60;
  ALabel.Parent := Self;
end;

end.


デル太  2006-03-31 03:11:48  No: 20750

訂正:
//参考ページ:http://www2.ocn.ne.jp/~mizu/api/d/d0001.htm←感謝m(__)m

URLを手打ちして確認を忘れてました。
訂正いたします。


デル太  2006-03-31 03:50:03  No: 20751

Panelのリージョンを変形し複数行の文字を表示することもできました。
期待どおり、角丸の外側が他のコントロールに重なっても汚くなりません。
最終的に次のようなコードになりました。

本件について、アドバイスをいただいたigyさん、ありがとうございました。
今回作成した2つのコードは他のスレッドでMr.XRAYさん、ぽんちゃんさんがご提示くださったコードを参考にしています。
ありがとうございます。

以下、コードを掲載させていただきますね。

//Panelのリージョンを変形し複数行の文字を表示20060330 byデル太
//わかりやすいように角丸の丸みを強くしました
//角丸の外側には文字が表示されずクリックイベントも発生しないことを確認できます
//角丸の外側に他のPanelが重なっても汚くなりません
//参考ページ:http://yokohama.cool.ne.jp/chokuto/urawaza/windowrgn.html←感謝m(__)m

unit Unit1;

interface

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

type
  TMyPanel = class(TPanel)
  protected
    procedure Paint; override;
  end;

  TForm1 = class(TForm)
    Button1: TButton;
    Panel1: TPanel; //重なったときの表示を確認するためのもの
    Label1: TLabel; //      〃
    procedure Button1Click(Sender: TObject);
    procedure MyPanelClick(Sender: TObject); //APanel用イベントハンドラ
  private
    { Private 宣言 }
  public
    { Public 宣言 }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

{ TMyPanel }

procedure TMyPanel.Paint;
var
  ARect: TRect;
  S: String;
begin
  inherited;
  ARect := Rect(5,5,Width -5, Height -5);
  S := 'この日本語文をラベルの表面に表示します'+#13+'改行も使えます';
  with Self do
  begin
    DrawText(Self.Canvas.Handle, PChar(S), -1, ARect, DT_WORDBREAK); //ワードラップを指定
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  APanel: TMyPanel;
  rgn: HRGN;
begin
  APanel := TMyPanel.Create(Self);
  APanel.Top := 10;
  APanel.Left := 20;
  APanel.Width := 200;
  APanel.Height := 60;
  APanel.BevelOuter := bvNone; //デフォルトから変更
  APanel.OnClick := MyPanelClick; //クリックイベントをイベントハンドラへ結びつける
  APanel.Parent := Self; //フォーム上に表示

  rgn := CreateRoundRectRgn(0,0,APanel.Width-5,APanel.Height-5,70,50);

  APanel.Color := clRed;
  SetWindowRgn(APanel.Handle, rgn, true);
  DeleteObject(rgn);
end;

procedure TForm1.MyPanelClick(Sender: TObject);
begin
  ShowMessage('APanel Clicked!');
end;

end.


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

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






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