角丸の四角形に文字を表示することを考えています。
その文字を、四角形の領域に合わせて折り返し複数行表示したいのです。
シンプルに実現できるなら、四角形のサイズや表示文字数は固定にしてもかまいません。
どのような方法が考えられるでしょうか?
現在、角丸の四角形は、別スレッドでアドバイスいただいた情報をもとに次の2つの方法で実現できています。
1)Win32のリージョンAPIを使ってDelphiのコンポーネントを変形させたTPanel
2)TLabelのPaintメソッド内でRoundRectを使い描画する
このあと、文字列を複数行表示させる方法がわからずにおります。
1)はTPanelのキャプションを複数行に表示できればよいのかな?と想像しています。
2)で試したところ、角丸四角形を塗りつぶすとCaptionが消えてしまい、描画後にCaptionを設定すると描画が消えてしまいます。
どうぞ、アドバイスをいただけますか?
よろしくお願いします。
APIのDrawTextを使うのは、どうでしょう?
TLabelを使う場合、WordWrap プロパティをTrueにするとか。
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.
訂正:
//参考ページ:http://www2.ocn.ne.jp/~mizu/api/d/d0001.htm←感謝m(__)m
URLを手打ちして確認を忘れてました。
訂正いたします。
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.
ツイート | ![]() |