Delphi Programming / Object Pascal
[掲載 2008年08月30日] [更新 2019年08月27日] Delphi サンプルプログラム集
910_Glyph 用ビットマップの作成
動作確認等
Windows 7 U64(SP1) + Delphi XE(UP1) Pro
910_DisableBitmap.zip [3,413 KB] 2019年08月27日版 (EXE 同梱)
2014年06月30日
ビットマップの減色とグレイスケール化の記事を,新規にページを作成して移動
2018年01月24日 (これより前の履歴は省略)
コンポーネントのアイコン作成支援プログラムに Glyph 用ビットマップ作成の機能を追加したので,関係記事とサンプルの掲載を中止
Glyph 用ビットマップと Disable 用のグレイスケールビットマップ
本ページで扱っている Glyph (グリフ) は,TSpeedButton, TBitBtn 等の Glyph プロパティのことです.この Glyph プロパティは TBitmap 型です.
Glyph のビットマップは,正方のビットマップを複数格納する形式になっていて,最大 4 つまで格納できます.Glyph にビットマップを設定すると TSpeedButton, TBitBtn 等に画像を表示できます.2 番目の画像があると,それらのコントロールの Enabled プロパティを False にした時の画像となります.2 番目のビットマップ画像が存在しない場合は Enabled プロパティの値を False にしても画像は表示されません.
下図は Delphi に付属している Glyph 用の 16 x 16 サイズのビットマップの例です.
透過処理はビットマップのデフォルトの設定で行われます.各々の正方のビットマップ画像の左下のピクセルの色が透過色となります.
図1
Delphi に付属の Glyph 用ビットマップ画像の例
図2
透過状態を確認した画像
[備考 1]
Delphi 7 等の旧い Delphi には各種の形式の画像が作成,編集可能なイメージエディタが付属していましたが,現在の Delphi にはこのようなイメージエディタは付属していません.
[備考 2]
TToolBar では,Glyph 用のビットマップを作成しなくても Images, DisabledImages, HotImages プロパティで個別のビットマップが設定できるようになっています.これらは TImageList 型のプロパティです.
01_ Glyph 用ビットマップは正方サイズの画像を結合して作成する
前項の説明,あるいはオンラインヘルプの説明で分かるように,Glyph 用のビットマップ画像は,正方サイズのビットマップを複数結合したビットマップです.
結合する画像の数に応じた幅と高さのビットマップを作成して,そこに表示するビットマップを描画して作成します.以下はその例です.
このサンプルでは 4 つのビットマップ画像を結合した Glyph 用のビットマップを作成しています.元となるビットマップ画像はディスクから読み込みます.元の画像は 32 x 32 の 24 ビットのビットマップなので,作成した Glyph 用ビットマップは 128 x 32
のサイズとなります.
フォームには TBitBtn と TSpeedButton を各々 1
つづつ配置して,作成したビットマップを Glyph プロパティのビットマップとしています.
Glyph 用ビットマップの 4 番目の画像は TSpeedButton の Down プロパティ用ですが,このサンプルでは使われません.
[備考 1]
Glyph 用のビットマップに 2 番目の画像がないと Enabled プロパティが False の時に画像は表示されません.3, 4 番目の画像がない場合は,代わりに 1 番目の画像が表示されます.
3 番目の画像が無効の場合,4 番目の画像が有効でも 3, 4 番目共に無効となります.
[備考 2]
本テストで使用しているビットマップ画像は,添付の PNG 画像から以下のプログラムを使用して作成しています.
図3
設計時画面
[Glyph 作成] ボタンの下が TBitBtn
その下が TSpeedButton
図4
EXE を実行して [Glyph 作成] をクリック
1 番目の画像が表示される
右が作成した Glyph 用のビットマップ画像
元の画像は 32 x 32 の 24 ビットのビットマップ
図5
TSpeedButton でマウスの左ボタンを押下した状態
図6
マウスの左ボタンを離した状態
図7
Enabled プロパティの値を False にした状態
copy code
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, Buttons, ExtCtrls;
type
TForm1 = class (TForm)
BitBtn1: TBitBtn;
Button1: TButton;
CheckBox1: TCheckBox;
Image1: TImage;
SpeedButton1: TSpeedButton;
procedure FormCreate(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure CheckBox1Click(Sender: TObject);
private
{ Private 宣言 }
public
{ Public 宣言 }
end ;
var
Form1: TForm1;
implementation
{$R *.dfm}
// =============================================================================
// フォーム生成時の処理
// =============================================================================
procedure TForm1.FormCreate(Sender: TObject);
begin
CheckBox1.Checked := True;
Image1.Center := True;
end ;
// =============================================================================
// Glyph用ビットマップを作成して表示,保存
// 添付の4つのビットマップ画像から作成する
// 添付のビックマップ画像は 32x32の24ビットのビットマップ画像ファイル
// =============================================================================
procedure TForm1.Button1Click(Sender: TObject);
var
LStrList : TStringList;
LGlyphBmp : TBitmap;
LBitmap : TBitmap;
LWidh : Integer;
LHeight : Integer;
LIndex : Integer;
LRect : TRect;
begin
LWidh := 0 ;
LHeight := 0 ;
LStrList := TStringList.Create;
LGlyphBmp := TBitmap.Create;
LBitmap := TBitmap.Create;
try
// Glyph用ビットマップ画像ファイルのパス名を設定
LStrList.Add('EMOTION_1_UP.bmp' );
LStrList.Add('EMOTION_2_DISABLE.bmp' );
LStrList.Add('EMOTION_3_CLICK.bmp' );
LStrList.Add('EMOTION_4_DOWN.bmp' );
for LIndex := 0 to LStrList.Count - 1 do begin
LBitmap.LoadFromFile(LStrList[LIndex]);
if LBitmap.PixelFormat = pf32bit then begin
LBitmap.AlphaFormat := afDefined;
LBitmap.Transparent :=False;
end else begin
LBitmap.Transparent :=True;
end ;
// 最初のビットマップ画像の情報を取得
// 全てのビットマップのサイズは同じでなければならない
if LIndex = 0 then begin
LWidh := LBitmap.Width;
LHeight := LBitmap.Height;
// Glyph用ビットのマップのサイズを決定
LGlyphBmp.AlphaFormat := LBitmap.AlphaFormat;
LGlyphBmp.Transparent := LBitmap.Transparent;
LGlyphBmp.SetSize(LWidh * LStrList.Count, LHeight);
end ;
// Glyph用ビットマップのCanvasに読み込んだビットマップ画像を描画する
// 左から順番にCopyRectメソッドを使用してコピー
LRect := Rect(LWidh * LIndex, 0 , LWidh * (LIndex + 1 ), LHeight);
LGlyphBmp.Canvas.CopyRect(LRect,
LBitmap.Canvas,
Rect(0 , 0 , LBitmap.Width, LBitmap.Height));
end ;
// TBitBtnの設定
BitBtn1.NumGlyphs := LStrList.Count;
BitBtn1.Glyph.Assign(LGlyphBmp);
// TSpeedButtonの設定
SpeedButton1.NumGlyphs := LStrList.Count;
SpeedButton1.Glyph.Assign(LGlyphBmp);
Image1.Picture.Assign(LGlyphBmp);
// Glpy用ビットマップの保存
LGlyphBmp.SaveToFile('emotion_glyph.bmp' );
finally
FreeAndNil(LStrList);
FreeAndNil(LGlyphBmp);
FreeAndNil(LBitmap);
end ;
end ;
// =============================================================================
// Enabledプロパティの切り換え
// =============================================================================
procedure TForm1.CheckBox1Click(Sender: TObject);
begin
BitBtn1.Enabled := CheckBox1.Checked;
SpeedButton1.Enabled := CheckBox1.Checked;
end ;
end .
02_ Glyph 用ビットマップと TSpeedButton の Down プロパティ
Glyph 用ビットマップの 4 番目の画像は TSpeedButton の Down プロパティ用です.
TSpeedButton の GroupIndex プロパティの値を 1 以上にすると,GroupIndex プロパティの値が同じボタンは,1 つだけが Down プロパティの値を True にできます.この機能により,どの TSpeedButton が押されているかを判定することが可能になります.同じ GroupIndex のボタンであれば,クリックしたボタンが自動的に Down プロパティが True になり,他のボタンは全て False になります.
Down プロパティの値が True の時に使われるのが Glyph 用ビットマップの 4 番目の画像です.
本サンプルはこのことを確認するためのテスト用です.
TSpeedButton を 2 つ配置し,どちらも GroupIndex の値を 1 にしています.
[備考]
GroupIndex の値が 0 の TSpeedButton は Down プロパティの値を True にできません.
TBitBtn には Down プロパティはありません.
図8
TSpeedButton でマウスの左ボタンを押下した状態
図9
マウスの左ボタンを離した状態
4 番目の画像が表示される
他の TSpeedButton には 1 番目の画像が表示される
図10
下の TSpeedButton をクリックした状態
下のボタンには 4 番目の画像が表示される
その他のボタンには 1 番目の画像が表示される
図11
Enabled プロパティの値を False にした状態
Down プロパティの値に関係なく,2 番目の画像が表示される
Down プロパティは,ボタンが Down (ダウン) していることを意味しますが,上の図ではグラデーション描画となっていてフレームが太くなっているだけになっています.
下図はテーマを無効にして実行した結果ですが.テーマという概念がない Windows の時代には,実際に下図のように下がった状態になりました.
図12
テーマを無効にした時の Dwon プロパティが True のボタンの表示状態
リスト2
Glyph 用ビットマップと TSpeedButton の Down プロパティ
copy code
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, Buttons, ExtCtrls;
type
TForm1 = class (TForm)
Button1: TButton;
CheckBox1: TCheckBox;
Image1: TImage;
SpeedButton1: TSpeedButton;
SpeedButton2: TSpeedButton;
procedure FormCreate(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure CheckBox1Click(Sender: TObject);
private
{ Private 宣言 }
public
{ Public 宣言 }
end ;
var
Form1: TForm1;
implementation
{$R *.dfm}
// =============================================================================
// フォーム生成時の処理
// =============================================================================
procedure TForm1.FormCreate(Sender: TObject);
begin
CheckBox1.Checked := True;
Image1.Center := True;
end ;
// =============================================================================
// Glyph用ビットマップを作成して表示,保存
// TSpeedButtonのDownプロパティの動作確認
//
// 添付の4つのビットマップ画像から作成する
// 添付のビックマップ画像は 32x32の24ビットのビットマップ画像ファイル
// =============================================================================
procedure TForm1.Button1Click(Sender: TObject);
var
LStrList : TStringList;
LGlyphBmp : TBitmap;
LBitmap : TBitmap;
LWidh : Integer;
LHeight : Integer;
LIndex : Integer;
LRect : TRect;
begin
LWidh := 0 ;
LHeight := 0 ;
// GroupIndexの値が1以上でないとDownプロパティは機能しない
SpeedButton1.GroupIndex := 1 ;
SpeedButton2.GroupIndex := 1 ;
LStrList := TStringList.Create;
LGlyphBmp := TBitmap.Create;
LBitmap := TBitmap.Create;
try
// Glyph用ビットマップ画像ファイルのパス名を設定
LStrList.Add('EMOTION_1_UP.bmp' );
LStrList.Add('EMOTION_2_DISABLE.bmp' );
LStrList.Add('EMOTION_3_CLICK.bmp' );
LStrList.Add('EMOTION_4_DOWN.bmp' );
for LIndex := 0 to LStrList.Count - 1 do begin
// ビットマップ画像ファイルを読み込む
LBitmap.LoadFromFile(LStrList[LIndex]);
if LBitmap.PixelFormat = pf32bit then begin
LBitmap.AlphaFormat := afDefined;
LBitmap.Transparent :=False;
end else begin
LBitmap.Transparent :=True;
end ;
// 最初のビットマップ画像の情報を取得
// 全てのビットマップのサイズは同じでなければならない
if LIndex = 0 then begin
LWidh := LBitmap.Width;
LHeight := LBitmap.Height;
// Glyph用ビットのマップのサイズを決定
LGlyphBmp.AlphaFormat := LBitmap.AlphaFormat;
LGlyphBmp.Transparent := LBitmap.Transparent;
LGlyphBmp.SetSize(LWidh * LStrList.Count, LHeight);
end ;
// Glyph用ビットマップのCanvasに読み込んだビットマップ画像を描画する
// 左から順番にCopyRectメソッドを使用してコピー
LRect := Rect(LWidh * LIndex, 0 , LWidh * (LIndex + 1 ), LHeight);
LGlyphBmp.Canvas.CopyRect(LRect,
LBitmap.Canvas,
Rect(0 , 0 , LBitmap.Width, LBitmap.Height));
end ;
// TSpeedButtonの設定
// GroupIndexの値は0でない値にしないとDownプロパティは機能しない
SpeedButton1.NumGlyphs := LStrList.Count;
SpeedButton1.Glyph.Assign(LGlyphBmp);
SpeedButton2.NumGlyphs := LStrList.Count;
SpeedButton2.Glyph.Assign(LGlyphBmp);
Image1.Picture.Assign(LGlyphBmp);
// Glpy用ビットマップの保存
LGlyphBmp.SaveToFile('emotion_glyph.bmp' );
finally
FreeAndNil(LStrList);
FreeAndNil(LGlyphBmp);
FreeAndNil(LBitmap);
end ;
end ;
// =============================================================================
// TSpeedButtonのEnabledプロパティの切り換え
// =============================================================================
procedure TForm1.CheckBox1Click(Sender: TObject);
begin
SpeedButton1.Enabled := CheckBox1.Checked;
SpeedButton2.Enabled := CheckBox1.Checked;
end ;
end .
03_ Glyph 用ビットマップとアルファチャンネル付きビットマップ
ここまでのサンプルでは 24 ビットのビットマップで Glyph 用ビットマップを作成しています.
Glyph 用のビットマップとしては,32 ビットのアルファチャンネル付きの半透明のビットマップ画像も使用できます.ただし,透明色は「黒」になります.また,半透明のピクセルは半透明ではなくなります.つまり,アルファチャンネルの値は無視されます.下図はその実際の結果です.使用している元のビットマップは 32 x 32 の 32 ビットのアルファチャンネル付きのビットマップです.
[備考]
TToolBar ではボタンを追加して使用します.このボタンのクラス名は TToolButton です.それらのボタンの画像は TImageList で設定します.Delphi 2009 以降の TmageList では,アルファチャンネル付きの PNG 画像やアルファチャンネル付きビットマップ画像も指定でき,TToolButton にアルファチャンネル付きの画像として描画できます.
Delphi 2009 からは TImage もアルファチャンネル付きの画像の描画が可能となっています.下図の結果でも,Glyph 用ビットマップの半透明ピクセルが半透明で描画されています.
図13
アルファチャンネルの値は無視される
右の TImage では,アルファチャンネル付きの画像が正常に描画されている
32 ビットのビットマップを,以下のように 24 ビットのビットマップすれば,これまでのサンプルとほぼ同じ結果になります.24 ビットと 32 ビットのビットマップの違いは,アルファチャンネルを使用するかしないかの違いてす.
アルファチャンネルを使用したビットマップ画像には半透明のピクセルがあります.TBitmap.PixelFormat プロパティによる減色は簡易的なものです.画質を考慮するのであれば他の減色処理が必要です.
// ビットマップ画像ファイルを読み込む
LBitmap.LoadFromFile(LStrList[LIndex]);
if LBitmap.PixelFormat = pf32bit then begin
LBitmap.PixelFormat := pf24bit;
LBitmap.Transparent := True;
end else begin
LBitmap.Transparent :=True;
end ;
図14
24 ビットのビットマップにした場合
04_ アイコン画像編集ソフトを使用した Glyph 用ビットマップ作成
Glyph 用のビットマップ画像の 2 番目の画像は一般的にグレイスケールの画像です.
この Disable な画像としてのグレイスケールな画像も含めて,Glyph 用のビットマップ画像はアイコン画像の作成編集用のソフトでも作成できます.画像編集ソフトの多くには画像のグレイスケール化の機能が実装されています.
まず,元の画像を作成します.その画像をグレイスケール化した画像を作成します.必要に応じて明るさやコントラストを調整します.次に高さが同じで幅が元の画像の 2 倍の画像を新規に作成します.その画像に元の画像とグレイスケール化した画像をコピーして貼り付けます.
保存する時はビットマップ形式で保存します.
下記の GIGAZINE で紹介しているサイトからダウンロードしたアイコン集には,Disable な画像に使用できるグレイスケールのアイコンが含まれています.それらは PNG 形式の画像です.
図15
KH IconStudio を使用しても Glyph 用のビットマップ画像が作成できる
[備考]
手元の KH IconStudio では [グレイスケール 256 色] を選択してもグレイスケールにできませんでした.上の図は,[ツール] [色相・彩度・明度調整] のダイアログで [彩度] の値を 0 % にして作成しています.
05_ 実行時における Glyph プロパティの設定と取得と無効化
Glyph プロパティの型は TBitmap です.
したがって,例えば以下のようなコードで実行時に設定したり取得できます.
テストで使用したビットマップ画像は,上のサンプルで作成した Glyph 画像です.円の内部の一部が透過色と同じ色になってしまい,透過状態になっています.テスト使用したような単色に近い色で構成されていて,使用している色数が少ない画像の時はこのような現象が発生することがあります.
このような場合は背景を別の色で塗り潰せば透過しなくなります.背景のピクセルは必ずしも連続しているとは限らないので,自動で処理するのは難しそうです.
図16
設計時画面
図17
[Glyph 設定] ボタンクリック
図18
[Glyph 取得] ボタンをクリック
図19
Enabled プロパティの値を Flase にした状態
TBitBtn に Glyph の 2 番目のビットマップ画像が表示される
2 番目の画像がない場合は,画像は表示されない
この画像の場合,円の内部の一部が透過色と同じ色になってしまい,透過している
図20
Glyph プロパティを無効にした状態
リスト3
Glyph プロパティを実行時に設定または取得あるいは無効にする
copy code
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, Buttons, ExtCtrls;
type
TForm1 = class (TForm)
Button1: TButton;
Button2: TButton;
Button3: TButton;
BitBtn1: TBitBtn;
CheckBox1: TCheckBox;
Image1: TImage;
procedure FormCreate(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure CheckBox1Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
private
{ Private 宣言 }
public
{ Public 宣言 }
end ;
var
Form1: TForm1;
implementation
{$R *.dfm}
// =============================================================================
// フォーム生成時の処理
// =============================================================================
procedure TForm1.FormCreate(Sender: TObject);
begin
CheckBox1.Checked := True;
end ;
// =============================================================================
// Glyphプロパティを設定
// =============================================================================
procedure TForm1.Button1Click(Sender: TObject);
var
LFilePath : string ;
LBitmap : TBitmap;
begin
LFilePath := ExpandFileName('..\Images\Test_Glyph.bmp' );
LBitmap := TBitmap.Create;
try
LBitmap.LoadFromFile(LFilePath);
BitBtn1.Glyph.Assign(LBitmap);
finally
FreeAndNil(LBitmap);
end ;
end ;
// =============================================================================
// Glyphのビットマップを取得
// =============================================================================
procedure TForm1.Button2Click(Sender: TObject);
begin
Image1.Picture.Bitmap := BitBtn1.Glyph;
end ;
// =============================================================================
// Glyphプロパティのビットマップを削除
// ボタンにGlyphの画像を表示しなくする
// =============================================================================
procedure TForm1.Button3Click(Sender: TObject);
begin
BitBtn1.Glyph.Assign(nil );
end ;
// =============================================================================
// TBitBtnのEnabledプロパティの切り換え
// =============================================================================
procedure TForm1.CheckBox1Click(Sender: TObject);
begin
BitBtn1.Enabled := CheckBox1.Checked;
end ;
end .
06_ TImageList を使用した Glyph 用ビットマップの設定
TImageList を使用する方法です.
設計時に TImageList に必要なビットマップ画像をセットしておいて,実行時に,それらの画像を取り出して Glyph 用のビットマップを作成します.この方法は,あらかじめ Glyph 用としてのビットマップを作成しておく必要がありません
最初の TImageList には通常表示用の画像を格納します.次の TImageList には Disable な状態を表示するための画像を格納します.このようにすると,TToolBar で TToolButton の画像を設定する方法と設計時の手順が同じになり,TToolBar で使用する TImageList と共有することも可能になります.また,TToolButton への移行も容易になります.
TImageList には PNG 形式,ICO 形式の画像も格納できますが,TBitBtn, TSpeedButton ではアルファチャンネル付きの画像は正常に描画できません.
Glyph 用のビットマップを作成しなくても,Enabled プロパティ等が変更された時に,TImageList から必要なビットマップ画像を Glyph プロパティに,以下のようにセットすることもできます.
このコードでは ImageList1 の Lindex 番目 (0 ベース) の画像を取得して SpeedButton.Glyph のビットマップとして設定します.
ImageList1.GetBitmap(LIndex, SpeedButton1.Glyph);
図21
設計時画面
TSpeedButton を 2 つ配置
TImageList を 2 つ配置
図22
TImageList の設定
サイズと ColorDepth を使用するビットマップと同じにする
上の図で示すような設定をしたら,TImageList に必要なビットマップ画像をセットします.画像を読み込んでからサイズや色数 ( ColorDepth) を変更すると,読み込んだ画像が消去されてしまいます.
図23
ImaeList1 に通常表示用としてのビットマップ画像を読み込む
図24
ImaeList2 に Disable な画像としてグレイスケールのビットマップ画像をセットする
図25
実行結果
図26
Enabled プロパティの値を False にした状態
リスト4
TImageList を使用して Glyph 用ビットマップを設定する
copy code
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, Buttons, ExtCtrls, ImgList;
type
TForm1 = class (TForm)
CheckBox1: TCheckBox;
SpeedButton1: TSpeedButton;
SpeedButton2: TSpeedButton;
ImageList1: TImageList;
ImageList2: TImageList;
procedure FormCreate(Sender: TObject);
procedure CheckBox1Click(Sender: TObject);
private
{ Private 宣言 }
procedure SetGlyphFromTImageList(AImgListUp, AImgListDisable, AImgListClick,
AImgListDown: TImageList; AButton: TObject; AImgIndex: Integer);
public
{ Public 宣言 }
end ;
procedure SetBitmapAlpha(ABitmap: TBitMap);
var
Form1: TForm1;
implementation
{$R *.dfm}
// =============================================================================
// フォーム生成時の処理
// TImageListに格納したビットマップをGlyph用のビットマップして使用する方法
// =============================================================================
procedure TForm1.FormCreate(Sender: TObject);
begin
CheckBox1.Checked := True;
// 背景色は元のビットマップにはない色にする
ImageList1.BkColor := clBlue;
ImageList2.BkColor := clBlue;
SetGlyphFromTImageList(ImageList1, ImageList2, nil , nil , SpeedButton1, 0 );
SetGlyphFromTImageList(ImageList1, ImageList2, nil , nil , SpeedButton2, 1 );
end ;
// =============================================================================
// TSpeedButtonのEnabledプロパティの切り換え
// =============================================================================
procedure TForm1.CheckBox1Click(Sender: TObject);
begin
SpeedButton1.Enabled := CheckBox1.Checked;
SpeedButton2.Enabled := CheckBox1.Checked;
end ;
// -----------------------------------------------------------------------------
// TImageListに格納されている画像からGlyph用のビットマップを作成してセットする
//
// AImgListUp : 通常表示する画像を格納したTImageList
// AImgListDisable : Disableな状態を表す画像を格納したTImageList
// AImgListClick : マウスの左ボタン押下時に表示示する画像を格納したTImageList
// AImgListDown : DownプロパティがTrueの時に表示する画像を格納したTImageList
// AButtton : TSpeedButtonまたはTBitBtn
// AImgIndex : TimageListの何番目の画像を使用するかの指定(0ベース)
// -----------------------------------------------------------------------------
procedure TForm1.SetGlyphFromTImageList(AImgListUp, AImgListDisable, AImgListClick,
AImgListDown: TImageList; AButton: TObject; AImgIndex: Integer);
procedure CopyTImgListBmpToGlyphCanvas(AImgList : TImageList; AGlyph: TBitmap;
ANo: Integer);
var
LBitmap : TBitmap;
LRect : TRect;
begin
if AImgList = nil then exit;
LBitmap := TBitmap.Create;
try
// GetBitmap は 透明ピクセルを処理しない (TBitmap として取得する場合)
// そこで TBitmap を完全に透明なビットマップにしておく
if AImgList.ColorDepth = cd32Bit then begin
LBitmap.AlphaFormat := afDefined;
LBitmap.SetSize(AImgList.Width, AImgList.Height);
SetBitmapAlpha(LBitmap);
end ;
if AImgList.GetBitmap(AImgIndex, LBitmap) then begin
// Glyph用ビットマップのCanvasにビットマップとして取得した画像を描画する
LRect := Rect(LBitmap.Width * ANo, 0 , LBitmap.Width * (ANo + 1 ), LBitmap.Height);
AGlyph.Canvas.CopyRect(LRect,
LBitmap.Canvas,
Rect(0 , 0 , LBitmap.Width, LBitmap.Height));
end ;
finally
FreeAndNil(LBitmap);
end ;
end ;
var
LGlphBmp : TBitmap;
LImgCount : Integer;
begin
if AImgListUp = nil then exit;
LGlphBmp := TBitmap.Create;
try
// Glyph用ビットマップのサイズを設定
LImgCount := 1 ;
if AImgListDisable <> nil then LImgCount := 2 ;
if AImgListClick <> nil then LImgCount := 3 ;
if AImgListDown <> nil then LImgCount := 4 ;
LGlphBmp.SetSize(AImgListUp.Width * LImgCount, AImgListUp.Height);
LGlphBmp.Canvas.FillRect(LGlphBmp.Canvas.ClipRect);
// TImageListの画像をビットマップとして取得して,GlyphのCanvasに追加していく
CopyTImgListBmpToGlyphCanvas(AImgListUp, LGlphBmp, 0 );
CopyTImgListBmpToGlyphCanvas(AImgListDisable, LGlphBmp, 1 );
CopyTImgListBmpToGlyphCanvas(AImgListClick, LGlphBmp, 2 );
CopyTImgListBmpToGlyphCanvas(AImgListDown, LGlphBmp, 3 );
// Glyphプロパティを設定
if AButton is TSpeedButton then begin
TSpeedButton(AButton).Glyph := LGlphBmp;
end ;
if AButton is TBitBtn then begin
TBitBtn(AButton).Glyph := LGlphBmp;
end ;
finally
FreeAndNil(LGlphBmp);
end ;
end ;
// ----------------------------------------------------------------------------
// 透明なビットマップ画像の作成
// アルファチャンネルのビットマップのピクセル値のクリア
// Red,Gree, Blue, Alphi 値を全て0 にしたビットマップにする
// ----------------------------------------------------------------------------
procedure SetBitmapAlpha(ABitmap: TBitMap);
type
TRGBQArray = array [0 ..High(Integer) div 4 - 1 ] of RGBQUAD;
PRGBQArray = ^TRGBQArray;
var
LPosY : Integer;
LPosX : Integer;
LScanArray : PRGBQArray;
begin
ABitmap.Canvas.Lock;
ABitmap.PixelFormat := pf32bit;
for LPosY := 0 to ABitmap.Height - 1 do begin
LScanArray := ABitmap.ScanLine[LPosY];
for LPosX := 0 to ABitmap.Width - 1 do begin
LScanArray[LPosX].rgbRed := 0 ;
LScanArray[LPosX].rgbGreen := 0 ;
LScanArray[LPosX].rgbBlue := 0 ;
LScanArray[LPosX].rgbReserved := 0 ;
end ;
end ;
ABitmap.Canvas.Unlock;
end ;
end .
07_ 単独の TSpeedButton で Down 状態のトグル機能
TSpeedButton の Down プロパティは GroupIndex の値が 1 以上の時に有効となります.
複数の TSpeedButton をグループ化して,その 1 だけを Down プロパティを True に,つまり押したままの状態にすることができます.以下のサンプルは,複数の TSpeedButton を配置している状態で各々の TSpeedButton 単独で Down プロパティを有効にする方法です.この動作は TCheckBox と同じように,クリックする度に状態が入れ換わるトグル機能です.
配置した各々の GroupIndex のそれぞれ異なる値にします.そして AllowAllUp の値を True にします.これらのプロパティの値はオブジェクト・インスペクタで設定できます.
[備考]
本サンプルでの TSpeedButton は,クリックする度に Down プロパティの値が自動で変わります.
TCheckBox はクリックする度にチェックマークを表示したり非表示にしますが,TSpeedButton では下がった状態と上がった状態で色が変わります.
上の方に図を掲載していますが,昔は本当に下がった状態になりました.
図27
サンプルの EXE を実行した画面<
全ての TSpeedButto.Dow が False の状態
図28
全ての TSpeedButton を押した状態
各々の TSpeedButton をクリックした結果
全ての TSpeedButton.Down の値が True の状態
右のボタンでも Down 状態のトグル操作が可能
図29
上の図の状態で真ん中の TSpeedButton をクリック
リスト5
TSpeedButton 単独で Down 状態のトグル機能を実現する
copy code
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, Buttons, StdCtrls;
type
TForm1 = class (TForm)
SpeedButton1: TSpeedButton;
SpeedButton2: TSpeedButton;
SpeedButton3: TSpeedButton;
Button1: TButton;
Button2: TButton;
Button3: TButton;
procedure FormCreate(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
procedure SpeedButton1Click(Sender: TObject);
private
{ Private 宣言 }
public
{ Public 宣言 }
end ;
var
Form1: TForm1;
implementation
{$R *.dfm}
// =============================================================================
// フォーム生成時の処理
// =============================================================================
procedure TForm1.FormCreate(Sender: TObject);
begin
SpeedButton1.GroupIndex := 1 ;
SpeedButton2.GroupIndex := 2 ;
SpeedButton3.GroupIndex := 3 ;
SpeedButton1.AllowAllUp := True;
SpeedButton2.AllowAllUp := True;
SpeedButton3.AllowAllUp := True;
end ;
// =============================================================================
// TSpeedButtonのクリックイベント
// =============================================================================
procedure TForm1.SpeedButton1Click(Sender: TObject);
begin
if TSpeedButton(Sender).Down then begin
// DownプロパティがTrueになった時の処理
// ボタンが下がった状態になった時の処理
end else begin
// DownプロパティがFalseになった時の処理
// ボタンが上がった状態になった時の処理
end ;
end ;
// =============================================================================
// SpeedButton1のDown状態の変更
// トグル操作
// =============================================================================
procedure TForm1.Button1Click(Sender: TObject);
begin
SpeedButton1.Down := not SpeedButton1.Down;
end ;
// =============================================================================
// SpeedButton2のDown状態の変更
// トグル操作
// =============================================================================
procedure TForm1.Button2Click(Sender: TObject);
begin
SpeedButton2.Down := not SpeedButton2.Down;
end ;
// =============================================================================
// SpeedButton3のDown状態の変更
// トグル操作
// =============================================================================
procedure TForm1.Button3Click(Sender: TObject);
begin
SpeedButton3.Down := not SpeedButton3.Down;
end ;
end .