Delphi Programming / Object Pascal
[掲載 2014年12月25日] [更新 2014年12月27日] Delphi サンプルプログラム集 |
207_TRichEdit の背景を画像にする |
動作確認等 |
Windows 7 U64(SP1) + Delphi XE(UP1) Pro |
|
207_RichEdit_Background.zip [2,434 KB] 2014年12月27日版 (EXE 同梱) |
- 2014年12月27日
- 透明部分を持つ画像を背景に表示する場合,透明部分を TRichEdit の背景色にするようにした
|
Delphi の TRichEdit コントロールの背景に画像を描画するテストプログラムです.
以下のページからダウンロードした TransparentRichEdit.pas のコードを元に,コンポーネントを作成して使用しています.Transparent となっていますが,透明な TRichEdit として利用できるわけではありません.透明化の処理のコードを利用して,背景に画像を表示します.
スクロールの際に,背景の画像はほとんどチラつきません.テキストの編集の際は,編集内容によってはチラつきが発生します.アルファチャンネル付きの画像等,透明部分がある JPEG, PNG, GIF 画像等は,透明な部分は Color プロパティの値の色で塗り潰すようにしています.
|
TRichEdit と同等,あるいは機能を拡張したコントロール,コンポーネントは,サードパーティからも多く提供されています.ネット上を検索してみてください.必ずしも RichEdit という名前が付いているとは限りませんっ.RichView 等の名前の場合もあります.また,Memo という名前が付いているコンポーネントでも,実際にはテキストの属性等が設定できるリッチエディットのこともあります.
サンプルの [206_TEdit や TMemo の背景を画像にする] で,TEdit, TMemo の背景に画像を表示していますが,TEdit, TMemo は,Windows のエディットコントロールを使用しています.
一方,TRichEdit は,Windows のリッチエディットコントロールを使用しています.基本的に,同じ方法は使用できません.
|
[備考]
TRichEdit に限らず,Windows 2000 以前の時代に開発されたものであれば,透明化の機能を実装したコンポーネントがネット上で入手できます.
Windows XP ではスキンというテーマが導入され,Windows Vista では描画の仕組みが大きく変わりました.そのため,Windows 2000 以前では期待通りに動作していた,背景の透明または半透明用のコンポーネント,あるいはネット上のサンプルコードの多くは,Windows XP 以降では期待通りに動作しない場合があります.
Delphi XE2 で導入された FireMonkey であれば,コントロールの透明度の設定が可能です.
VCL で開発する場合,コントロールの半透明化や透明化の実装が,本当に必要なのかを再検討する必要があるかも知れません.
|
作成したコンポーネントの基本的なテストです.基本的と言っても,画像を表示するだけですから,画像の設定方法だけです.
背景に表示する画像は,フォーム生成時に設定しています. |
|
図1
設計時画面
- コンポーネントを配置
- その他のテスト用のボタンを配置
|
|
図2
EXE の起動直後の画面 |
|
図3
フォームのサイズを大きくしたところ
- 背景の画像は,元のサイズなので,そのサイズを超えた部分は,元の TRichEdit の背景色となる
|
|
図4
背景画像を StretchDraw で描画した場合 |
|
図5
別の画像を背景の画像にする |
リスト1
リッチエディットコントロールの背景を画像にするコンポーネントのテスト |
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, plBackPictRichEdit, ComCtrls, JPEG;
type
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
Button3: TButton;
Button4: TButton;
plRichEdit: TplBackPictRichEdit;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
procedure Button4Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Private 宣言 }
public
{ Public 宣言 }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
//=============================================================================
// フォーム生成時の処理
// フォームに配置したTplBackPictRichEditの設定
//=============================================================================
procedure TForm1.FormCreate(Sender: TObject);
var
i : Integer;
Pict : TWICImage;
begin
if Assigned(plRichEdit) then begin
plRichEdit.Font.Size := 15;
//テスト用のテキストをセット
plRichEdit.Lines.Clear;
plRichEdit.Lines.BeginUpdate;
for i := 0 to 19 do begin
plRichEdit.Lines.Add('TplBackPictRichEdit');
end;
plRichEdit.Lines.EndUpdate;
//背景画像用の画像を読み込む
Pict := TWICImage.Create;
try
Pict.LoadFromFile('Cat.jpg');
plRichEdit.BackPicture := TPicture(Pict);
finally
FreeAndNil(Pict);
end;
end;
end;
//=============================================================================
// 画像をストレッチ描画して,クライアント領域全体に表示
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
begin
if Assigned(plRichEdit) then begin
plRichEdit.BackPictStretch := True;
end;
end;
//=============================================================================
// 背景の画像を元のサイズで表示する
//=============================================================================
procedure TForm1.Button2Click(Sender: TObject);
begin
if Assigned(plRichEdit) then begin
plRichEdit.BackPictStretch := False;
end;
end;
//=============================================================================
// 背景に画像を表示しない
//=============================================================================
procedure TForm1.Button3Click(Sender: TObject);
begin
if Assigned(plRichEdit) then begin
plRichEdit.BackPicture := nil;
end;
end;
//=============================================================================
// 別の画像を背景にする
//=============================================================================
procedure TForm1.Button4Click(Sender: TObject);
var
Pict : TPicture;
begin
if Assigned(plRichEdit) then begin
Pict := TPicture.Create;
try
Pict.LoadFromFile('e316.bmp');
plRichEdit.BackPicture := Pict;
finally
FreeAndNil(Pict);
end;
end;
end;
end.
コンポーネントを実行時に生成して利用する場合の参考コードです.
テストの内容は,前項のサンプルと全く同じです. |
|
図6
設計時画面
|
|
図7
EXE の起動直後の画面 |
リスト2
リッチエディットコントロールの背景を画像にするコンポーネントのテスト
コンポーネントを実行時に生成する場合 |
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, plBackPictRichEdit, JPEG;
type
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
Button3: TButton;
Button4: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
procedure Button4Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Private 宣言 }
plRichEdit: TplBackPictRichEdit;
public
{ Public 宣言 }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
//=============================================================================
// フォーム生成時の処理
// TplBackPictRichEditを生成して,背景に表示する画像を読み込み
//=============================================================================
procedure TForm1.FormCreate(Sender: TObject);
var
Pict : TWICImage;
i : Integer;
begin
//TplBackPictRichEditを生成
plRichEdit := TplBackPictRichEdit.Create(Self);
plRichEdit.Parent := Self;
plRichEdit.Left := 0;
plRichEdit.Top := Button1.Top + Button1.Height + 5;
plRichEdit.Width := Self.ClientWidth;
plRichEdit.Height := Self.ClientHeight - plRichEdit.Top;
plRichEdit.Anchors := [akLeft, akTop, akRight, akBottom];
plRichEdit.Font.Size := 14;
plRichEdit.ScrollBars := ssVertical;
//テスト用にテキストをセット
plRichEdit.Lines.BeginUpdate;
for i := 0 to 19 do
begin
plRichEdit.Lines.Add('TplBackPictRichEdit');
end;
plRichEdit.Lines.EndUpdate;
//背景に描画する画像を指定
plRichEdit.BackPicture := nil;
plRichEdit.Update;
Pict := TWICImage.Create;
try
Pict.LoadFromFile('Cat.jpg');
plRichEdit.BackPicture := TPicture(Pict);
finally
FreeAndNil(Pict);
end;
end;
//=============================================================================
// 画像をストレット描画する
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
begin
if Assigned(plRichEdit) then begin
plRichEdit.BackPictStretch := True;
end;
end;
//=============================================================================
// 背景の画像を元のサイズで表示する
//=============================================================================
procedure TForm1.Button2Click(Sender: TObject);
begin
if Assigned(plRichEdit) then begin
plRichEdit.BackPictStretch := False;
end;
end;
//=============================================================================
// 背景に画像を表示しない
//=============================================================================
procedure TForm1.Button3Click(Sender: TObject);
begin
if Assigned(plRichEdit) then begin
plRichEdit.BackPicture := nil;
end;
end;
//=============================================================================
// 別の画像を背景にする
//=============================================================================
procedure TForm1.Button4Click(Sender: TObject);
var
Pict : TPicture;
begin
if Assigned(plRichEdit) then begin
Pict := TPicture.Create;
try
Pict.LoadFromFile('e316.bmp');
plRichEdit.BackPicture := Pict;
finally
FreeAndNil(Pict);
end;
end;
end;
end.
03_TRichEdit の背景をパターンブラシ状にする |
このコンポーネントは,背景の画像を WM_ERASEBKGND メッセージ内で描画しています.
このメッセージ内でブラシを指定して描画すると,非常にチラつきが激しくなります.そこで,本サンプルでは,1 つの画像から,パターンブラシのビットマップを作成し,それを背景に描画します.
|
|
図8
設計時画面 |
|
図9
EXE の起動直後の画面 |
リスト3
TRichEdit の背景をパターンブラシ状にする |
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, plBackPictRichEdit, ComCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
plRichEdit: TplBackPictRichEdit;
procedure FormCreate(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
{ Private 宣言 }
procedure CreateLike_PatternBrush;
public
{ Public 宣言 }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
//=============================================================================
// フォーム生成時の処理
//=============================================================================
procedure TForm1.FormCreate(Sender: TObject);
var
i : Integer;
begin
if Assigned(plRichEdit) then begin
plRichEdit.Font.Size := 15;
//テスト用にテキストをセット
plRichEdit.Lines.Clear;
plRichEdit.Lines.BeginUpdate;
for i := 0 to 19 do begin
plRichEdit.Lines.Add('TplBackPictRichEdit');
end;
plRichEdit.Lines.EndUpdate;
//パターンブラシもどきを作成
CreateLike_PatternBrush;
end;
end;
//=============================================================================
// 背景に画像を表示しない
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
begin
if Assigned(plRichEdit) then begin
plRichEdit.BackPicture := nil;
end;
end;
//=============================================================================
// 背景に画像を表示する
//=============================================================================
procedure TForm1.Button2Click(Sender: TObject);
begin
if Assigned(plRichEdit) then begin
CreateLike_PatternBrush;
end;
end;
//-----------------------------------------------------------------------------
// パターンブラシもどきの画像を作成
//-----------------------------------------------------------------------------
procedure TForm1.CreateLike_PatternBrush;
var
LBitmap : TBitmap;
TempBmp : TBitmap;
Pict : TWICImage;
begin
if Assigned(plRichEdit) then begin
LBitmap := TBitmap.Create;
TempBmp := TBitmap.Create;
Pict := TWICImage.Create;
try
Pict.LoadFromFile('e316.bmp');
TempBmp.Assign(Pict);
LBitmap.SetSize(Screen.Width, Screen.Height);
LBitmap.Canvas.Brush.Style := bsClear;
LBitmap.Canvas.Brush.Bitmap := TempBmp;
LBitmap.Canvas.Pen.Color := clWhite;
LBitmap.Canvas.Rectangle(0, 0, LBitmap.Width, LBitmap.Height);
plRichEdit.BackPicture := TPicture(LBitmap);
finally
FreeAndNil(TempBmp);
FreeAndNil(LBitmap);
FreeAndNil(Pict);
end;
end;
end;
end.
04_TRichEdit の背景をハッチブラシ状にする |
このコンポーネントは,背景の画像を WM_ERASEBKGND メッセージ内で描画しています.
このメッセージ内でブラシを指定して描画すると,非常にチラつきが激しくなります.そこで,本サンプルでは,1 つの画像から,ハッチブラシのビットマップを作成し,それを背景に描画します. |
|
図10
設計時画面 |
|
図11
EXE の起動直後の画面 |
リスト4
TRichEdit の背景をハッチブラシ状にする |
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, plBackPictRichEdit, ComCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
plRichEdit: TplBackPictRichEdit;
procedure FormCreate(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
{ Private 宣言 }
procedure CreateLike_HatchBrush;
public
{ Public 宣言 }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
//=============================================================================
// フォーム生成時の処理
//=============================================================================
procedure TForm1.FormCreate(Sender: TObject);
var
i : Integer;
begin
if Assigned(plRichEdit) then begin
plRichEdit.Font.Size := 15;
//テスト用にテキストをセット
plRichEdit.Lines.Clear;
plRichEdit.Lines.BeginUpdate;
for i := 0 to 19 do begin
plRichEdit.Lines.Add('TplBackPictRichEdit');
end;
plRichEdit.Lines.EndUpdate;
//ハッチブラシもどきを作成
CreateLike_HatchBrush;
end;
end;
//=============================================================================
// 背景に画像を表示しない
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
begin
if Assigned(plRichEdit) then begin
plRichEdit.BackPicture := nil;
end;
end;
//=============================================================================
// 背景に画像を表示する
//=============================================================================
procedure TForm1.Button2Click(Sender: TObject);
begin
if Assigned(plRichEdit) then begin
CreateLike_HatchBrush;
end;
end;
//-----------------------------------------------------------------------------
// ハッチブラシもどきの画像を作成
//-----------------------------------------------------------------------------
procedure TForm1.CreateLike_HatchBrush;
var
LBitmap : TBitmap;
begin
if Assigned(plRichEdit) then begin
LBitmap := TBitmap.Create;
try
LBitmap.SetSize(Screen.Width, Screen.Height);
LBitmap.Canvas.Brush.Style := bsCross;
LBitmap.Canvas.Brush.Color := $00FFE7B5;
LBitmap.Canvas.Pen.Color := clWhite;
LBitmap.Canvas.Rectangle(0, 0, LBitmap.Width, LBitmap.Height);
plRichEdit.BackPicture := TPicture(LBitmap);
finally
FreeAndNil(LBitmap);
end;
end;
end;
end.
05_背景に画像を表示できる TRichEdit コンポーネント |
本ページのサンプルで使用したコンポーネントのソースコードです.
透明部分を持つ JPEG, PNG, GIF 画像等は.透明部分は Color プロパティの値で塗り潰すようになっています.
このコンポーネントは,自身の DoubleBuffered プロパティを True にすると,テキストが正常に表示できなくなります.
|
凡例 |
■ published
□ public
▲ ReadOnly |
□ BackPicture |
TPicture |
背景に描画する画像のオブジェクト |
□ BackPictStretch |
Boolean |
元のサイズで描画するのか,ストレッチ描画するかの指定
デフォルトは False で,元のサイズで描画する |
リスト5
背景を画像にできる TRichEdit コンポーネント |
unit plBackPictRichEdit;
interface
uses
Windows, Messages, SysUtils, Classes, Controls, StdCtrls, ComCtrls,
Graphics, forms;
type
TplBackPictRichEdit = class (TRichEdit)
private
procedure SetBackPicture(const Value: TPicture);
procedure SetBackPictStretch(const Value: Boolean);
protected
FCanvas : TControlCanvas;
FBitmap : TBitmap;
FBackPicture : TPicture;
FBackPictStretch : Boolean;
FBackPictFlag : Boolean;
procedure CreateWnd; override;
procedure WMEraseBkgnd(var Message: TWMEraseBkgnd); message WM_ERASEBKGND;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
property BackPicture : TPicture read FBackPicture write SetBackPicture;
property BackPictStretch : Boolean read FBackPictStretch write SetBackPictStretch;
published
end;
procedure Register;
implementation
{ TplBackPictRichEdit }
//-----------------------------------------------------------------------------
// コンポーネントのコンストラクタ
// 背景に画像を描画する際に使用するTCanvasを生成
// その画像用のTPictureオブジェクトを生成
//-----------------------------------------------------------------------------
constructor TplBackPictRichEdit.Create(AOwner: TComponent);
begin
inherited;
FCanvas := TControlCanvas.Create;
FBackPicture := TPicture.Create;
FBackPictStretch := False;
FBackPictFlag := False;
FBitmap := TBitmap.Create;
FBitmap.Transparent := False;
end;
//-----------------------------------------------------------------------------
// コンポーネントのデストラクタ
//-----------------------------------------------------------------------------
destructor TplBackPictRichEdit.Destroy;
begin
FBitmap.Free;
FBackPicture.Free;
FCanvas.Free;
inherited;
end;
//-----------------------------------------------------------------------------
// CreateWnd処理
// CreateWndはウィンドウが生成される時に実行されるメソッド
//-----------------------------------------------------------------------------
procedure TplBackPictRichEdit.CreateWnd;
var
ExtStyle : Cardinal;
begin
inherited;
if not (csDesigning in ComponentState) then begin
ExtStyle := GetWindowLong(Handle, GWL_EXSTYLE);
if FBackPicture.Graphic = nil then begin
SetWindowLong(Handle, GWL_EXSTYLE, ExtStyle and not WS_EX_TRANSPARENT);
end else begin
SetWindowLong(Handle, GWL_EXSTYLE, ExtStyle or WS_EX_TRANSPARENT);
end;
end;
end;
//-----------------------------------------------------------------------------
// BackPicture(TPicture)プロパティの設定用メソッド
//-----------------------------------------------------------------------------
procedure TplBackPictRichEdit.SetBackPicture(const Value: TPicture);
begin
FBackPicture.Assign(Value);
if not (csDesigning in ComponentState) then begin
FBitmap.Assign(nil);
if FBackPictStretch then begin
FBitmap.SetSize(FBackPicture.Width, FBackPicture.Height);
end else begin
FBitmap.SetSize(Screen.Width, Screen.Height);
end;
FBitmap.Canvas.Brush.Color := Color;
FBitmap.Canvas.FillRect(FBitmap.Canvas.ClipRect);
FBitmap.Canvas.Draw(0, 0, FBackPicture.Graphic);
FBackPictFlag := True;
RecreateWnd;
end;
end;
//-----------------------------------------------------------------------------
// BackPictStretchプロパティの設定用メソッド
// ストレッチで描画するか,元のサイズで描画するかの指定
//-----------------------------------------------------------------------------
procedure TplBackPictRichEdit.SetBackPictStretch(const Value: Boolean);
begin
FBackPictStretch := Value;
if not (csDesigning in ComponentState) then begin
FBitmap.Assign(nil);
if FBackPictStretch then begin
FBitmap.SetSize(FBackPicture.Width, FBackPicture.Height);
end else begin
FBitmap.SetSize(Screen.Width, Screen.Height);
end;
FBitmap.Canvas.Brush.Color := Color;
FBitmap.Canvas.FillRect(FBitmap.Canvas.ClipRect);
FBitmap.Canvas.Draw(0, 0, FBackPicture.Graphic);
FBackPictFlag := True;
RecreateWnd;
end;
end;
//-----------------------------------------------------------------------------
// WM_ERASEBKGNDメッセージ処理
// リージョンの更新が必要な領域を更新し,画像を描画する
// この処理のため,DoubleBufferedをTrueにするとテキストが正常に表示されない
//
// 背景を塗り潰してから画像を描画すれば透明部分がなくなる
// すると,透明部分がある画像でも,テキストの編集でテキストの描画が乱れない
// ただし,スクロールの際に画像がチラつく場合がある
// そこで,あらかじめ画像を描画したビットマップを表示するようにしている
//-----------------------------------------------------------------------------
procedure TplBackPictRichEdit.WMEraseBkgnd(var Message: TWMEraseBkgnd);
var
LRect : TRect;
Rgn : HRGN;
ToBeErased : Boolean;
Flags : Cardinal;
begin
if (FBackPicture.Graphic = nil) and (csDesigning in ComponentState) then begin
inherited;
exit;
end;
FCanvas.Handle := Message.DC;
Message.Result := 1;
//更新が必要なリージョンの最小矩形領域の取得
ToBeErased := False;
if not GetUpdateRect(Handle, LRect, ToBeErased) then begin
LRect := Rect(0, 0, ClientWidth, ClientHeight);
end;
Rgn := CreateRectRgn(LRect.Left, LRect.Top, LRect.Right, LRect.Bottom);
SelectClipRgn(FCanvas.Handle, Rgn);
if FBackPictStretch then begin
FCanvas.StretchDraw(ClientRect, FBitmap);
end else begin
FCanvas.Draw(0, 0, FBitmap);
end;
//RDW_FRAMEを指定して非クライアント領域を再描画
//画像が変わった時に,1回たけ実行する
if (FBackPictFlag) and Visible then begin
FBackPictFlag := False;
Flags := RDW_ERASE or RDW_INVALIDATE or RDW_FRAME;
RedrawWindow(Handle, nil, 0, Flags);
end;
end;
//-----------------------------------------------------------------------------
// コンポーネント登録情報
//-----------------------------------------------------------------------------
procedure Register;
begin
RegisterComponents('plXRAY', [TplBackPictRichEdit]);
end;
end.
|