Delphiでメニューを美しくする
Windows の多くのプログラムには、Windows の「スタート」メニューの左側に上から下まで長い Windows バナーや、Word のような各メニュー バーの左側にある小さなアイコンなど、非常に美しいメニューがあります。これらのクールなメニュー、自分のメニューが退屈だと感じていませんか?サードパーティ製のコントロールは必要なく、上記の機能は Delphi を使用して実現できます。
カスタム メニューを実装する場合は、メニューを描画するときに、メニューに描画されるグラフィックに合わせてメニューのサイズを変更し、必要なメニュー効果を描画する必要があります。 Delphi では、各メニュー項目は TmenuItem コントロールに対応します。カスタム メニューを実装するには、まず次の 2 つのイベントを導入する必要があります。
OnMeasureItem イベントは次のように定義されます。
type TMenuMeasureItemEvent = PROcedure (送信者: TObject; ACanvas: TCanvas;
var オブジェクトの幅、高さ: 整数)。
プロパティ OnMeasureItem: TMenuMeasureItemEvent;
このイベントは、メニュー バーが自身のサイズを監視するときに生成されます。パラメータ Acanvas は描画される描画オブジェクトを定義し、パラメータWidth と Height はこれら 2 つの定義の前にあることに気づきましたか?処理関数でこれら 2 つの値を変更すると、メニューのサイズが変更されることになります。
OnDrawItem イベントは次のように定義されます。
type TMenuDrawItemEvent = プロシージャ (送信者: TObject; ACanvas: TCanvas;
ARect: TRect 選択済み: ブール値) のオブジェクト。
プロパティ OnDrawItem: TMenuDrawItemEvent;
このイベントは、メニューが描画されるときにトリガーされます。パラメータ Acanvas はメニュー描画オブジェクトを定義し、パラメータ Arect はメニューの描画領域を指定し、パラメータ Selected は現在のメニュー項目が選択されているかどうかを定義します。
上記の紹介からわかるように、カスタマイズされたメニューを実装するには、メニュー項目のサイズを変更するコードを OnMeasureItem イベントに記述してから、必要な効果を OnDrawItem イベントで描画するだけです。
以下に具体的な例を挙げて説明します。この例では、Windows のスタート メニューのようなバナー バー機能を独自のメニューに表示します。同時に、このプログラムは、選択したメニュー バーをグラデーション カラーで塗りつぶすこともできます (3721 中国語 Web サイト ソフトウェアのタスク バー メニューと同様)。プログラムの考え方は次のとおりです。まず長いビットマップを作成し、次にメニューに表示されるテキストと画像およびニーズに応じて、各メニュー バーの OnMeasureItem イベント内のメニュー項目の幅と高さを変更します。プログラムのビットマップの対応する部分を OnDrawItem イベントのメニュー項目にコピーします。メニューバーが選択されている場合、最初にAcanvasパラメータのブラシの色を変更し、次にメニューバーの対応する部分を順番に塗りつぶすことで、選択したメニューバーのグラデーションカラー塗りつぶしが実現します。最後に、テキストがメニューバーに出力されます。
具体的な手順を紹介します。まず、画像ソフトを使用して長いビットマップファイルを作成します(必要に応じて画像のアスペクト比を設定できます。私の画像では10:1です)。 Delphi で新しいプロジェクトを作成し、TImage コントロールを Form1 に追加し、コントロールの AutoSize プロパティを True に設定します。次に、TMainMenu コントロールを Form1 に追加し、その OwnerDraw プロパティを True に設定し (これは非常に重要です。そうしないとプログラムを実装できません)、TMainMenu の下に 6 つの TMenuItem オブジェクトを追加します (TMainMenu コントロールを右クリックし、ポップアップ メニュー メニュー デザイナー項目 (デザイン ウィンドウにメニュー バーを追加できます)、その Name プロパティをそれぞれ Caption1、Caption2、...、Caption6 に設定します。
以下は具体的なプログラムのリストです。
ユニットオーナーメニュー;
インタフェース
用途
ウィンドウ、メッセージ、SysUtils、クラス、グラフィックス、コントロール、フォーム、ダイアログ、
メニュー、ExtCtrls、StdCtrls、ImgList;
タイプ
TForm1 = クラス(TForm)
MainMenu1: TMainMenu;
Main1: TMenuItem;
キャプション 1: TMenuItem;
キャプション 2: TMenuItem;
キャプション 3: TMenuItem;
キャプション 4: TMenuItem;
キャプション 5: TMenuItem;
キャプション 6: TMenuItem;
画像1: T画像;
プロシージャ Caption1MeasureItem(Sender: TObject; ACanvas: TCanvas;
var 幅、高さ: 整数);
プロシージャ Caption2MeasureItem(Sender: TObject; ACanvas: TCanvas;
var 幅、高さ: 整数);
プロシージャ Caption3MeasureItem(Sender: TObject; ACanvas: TCanvas;
var 幅、高さ: 整数);
プロシージャ Caption4MeasureItem(Sender: TObject; ACanvas: TCanvas;
var 幅、高さ: 整数);
プロシージャ Caption5MeasureItem(Sender: TObject; ACanvas: TCanvas;
var 幅、高さ: 整数);
プロシージャ Caption6MeasureItem(Sender: TObject; ACanvas: TCanvas;
var 幅、高さ: 整数);
プロシージャ Caption1DrawItem(Sender: TObject; ACanvas: TCanvas;
ARect: TRect 選択済み: ブール値);
プロシージャ Caption2DrawItem(Sender: TObject; ACanvas: TCanvas;
ARect: TRect 選択済み: ブール値);
プロシージャ Caption3DrawItem(Sender: TObject; ACanvas: TCanvas;
ARect: TRect 選択済み: ブール値);
プロシージャ Caption4DrawItem(Sender: TObject; ACanvas: TCanvas;
ARect: TRect 選択済み: ブール値);
プロシージャ Caption5DrawItem(Sender: TObject; ACanvas: TCanvas;
ARect: TRect 選択済み: ブール値);
プロシージャ Caption6DrawItem(Sender: TObject; ACanvas: TCanvas;
ARect: TRect 選択済み: ブール値);
プライベート
{プライベート宣言}
公共
プロシージャ DrawItem(Sender: TMenuItem; ACanvas: TCanvas;ARect: TRect;
選択済み: ブール値;strOUt:String);
{公的宣言}
終わり;
変数
フォーム1: TForm1;
i、iH、Ind、iW、iRate:整数;
rTemp:TRect;
iG1、iG2:整数;
実装
{$R *.DFM}
プロシージャ TForm1.DrawItem(Sender: TMenuItem; ACanvas: TCanvas;ARect: TRect;
選択済み: ブール値;strOut:String);
変数
j:整数;
始める
i:=ARect.Bottom -ARect.Top; //テクスチャの高さと幅を取得します。
Ind:=Sender.MenuIndex;
iH:=Round(Image1.Height/6*Ind); //テクスチャ位置を取得します。
// 画像上の対応する位置にあるビットマップをメニューにコピーします
StretchBlt(ACanvas.Handle,ARect.Left,ARect.Top,iW,i,Image1.Canvas.Handle,0,iH,
Image1.Width,Round(Image1.Height/6),SRCCOPY);
if Selected then begin //メニュー項目が選択されています
ACanvas.Font.Color := clWhite;
rTemp:=ARect;
rTemp.Left := rTemp.left+iW;
iG1:=Round((rTemp.Right - rTemp.Left)/10);
rTemp.Right := rTemp.Left +iG1;
for j:= 0 to 9 do begin //ループを通じてカラーグラデーション効果を設定します
ACanvas.Brush.Color := RGB(0,0,j*25);
ACanvas.FillRect(rTemp);
rTemp.Left := rTemp.Left +iG1;
rTemp.Right := rTemp.Left +iG1;
終わり;
終わり
else begin //このメニュー項目は選択されていません
ACanvas.Brush.Color := cl3DLight // 背景色をライトグレーに設定します。
rTemp:=ARect;
rTemp.Left := rTemp.left+iW;
ACanvas.FillRect(rTemp);
ACanvas.Font.Color := clBlack;
終わり;
//キャンバス ブラシの塗りつぶしモードを透明に設定します。
ACanvas.Brush.Style:=bsClear;
//メニュー上のテキストを出力します
ACanvas.TextOut(ARect.Left+iW+5,ARect.Top,strOut);
終わり;
プロシージャ TForm1.Caption1MeasureItem(Sender: TObject; ACanvas: TCanvas;
var 幅、高さ: 整数);
始める
//OnMeasureItemイベントでメニューの幅と高さを変更する 以下の5つのプログラムは同じです。
// テキストが収まるようにメニューの幅と高さを変更します
高さ:=ACanvas.TextHeight('Caption1')+5;
幅:=ACanvas.TextWidth('Caption1')+5;
iRate:=Round(画像1.高さ/(高さ*6));
iW:=Round(Image1.Width /iRate);
width:=Width+iW; //追加のテキストに合わせて計算に基づいてメニューの幅を変更します。
終わり;
プロシージャ TForm1.Caption2MeasureItem(送信者: TObject; ACanvas: TCanvas;
var 幅、高さ: 整数);
始める
高さ:=ACanvas.TextHeight('Caption1')+5;
幅:=ACanvas.TextWidth('Caption1')+5;
iRate:=Round(画像1.高さ/(高さ*6));
iW:=Round(Image1.Width /iRate);
幅:=幅+iW;
終わり;
プロシージャ TForm1.Caption3MeasureItem(送信者: TObject; ACanvas: TCanvas;
var 幅、高さ: 整数);
始める
高さ:=ACanvas.TextHeight('Caption1')+5;
幅:=ACanvas.TextWidth('Caption1')+5;
iRate:=Round(画像1.高さ/(高さ*6));
iW:=Round(Image1.Width /iRate);
幅:=幅+iW;
終わり;
プロシージャ TForm1.Caption4MeasureItem(送信者: TObject; ACanvas: TCanvas;
var 幅、高さ: 整数);
始める
高さ:=ACanvas.TextHeight('Caption1')+5;
幅:=ACanvas.TextWidth('Caption1')+5;
iRate:=Round(画像1.高さ/(高さ*6));
iW:=Round(Image1.Width /iRate);
幅:=幅+iW;
終わり;
プロシージャ TForm1.Caption5MeasureItem(送信者: TObject; ACanvas: TCanvas;
var 幅、高さ: 整数);
始める
高さ:=ACanvas.TextHeight('Caption1')+5;
幅:=ACanvas.TextWidth('Caption1')+5;
iRate:=Round(画像1.高さ/(高さ*6));
iW:=Round(Image1.Width /iRate);
幅:=幅+iW;
終わり;
プロシージャ TForm1.Caption6MeasureItem(送信者: TObject; ACanvas: TCanvas;
var 幅、高さ: 整数);
始める
高さ:=ACanvas.TextHeight('Caption1')+5;
幅:=ACanvas.TextWidth('Caption1')+5;
iRate:=Round(画像1.高さ/(高さ*6));
iW:=Round(Image1.Width /iRate);
幅:=幅+iW;
終わり;
プロシージャ TForm1.Caption1DrawItem(Sender: TObject; ACanvas: TCanvas;
ARect: TRect 選択済み: ブール値);
始める
DrawItem(TMenuItem(Sender),ACanvas,ARect,Selected,'Caption1');
終わり;
プロシージャ TForm1.Caption2DrawItem(Sender: TObject; ACanvas: TCanvas;
ARect: TRect 選択済み: ブール値);
始める
DrawItem(TMenuItem(Sender),ACanvas,ARect,Selected,'Caption2');
終わり;
プロシージャ TForm1.Caption3DrawItem(送信者: TObject; ACanvas: TCanvas;
ARect: TRect 選択済み: ブール値);
始める
DrawItem(TMenuItem(Sender),ACanvas,ARect,Selected,'Caption3');
終わり;
プロシージャ TForm1.Caption4DrawItem(Sender: TObject; ACanvas: TCanvas;
ARect: TRect 選択済み: ブール値);
始める
DrawItem(TMenuItem(Sender),ACanvas,ARect,Selected,'Caption4');
終わり;
プロシージャ TForm1.Caption5DrawItem(送信者: TObject; ACanvas: TCanvas;
ARect: TRect 選択済み: ブール値);
始める
DrawItem(TMenuItem(Sender),ACanvas,ARect,Selected,'Caption5');
終わり;
プロシージャ TForm1.Caption6DrawItem(送信者: TObject; ACanvas: TCanvas;
ARect: TRect 選択済み: ブール値);
始める
DrawItem(TMenuItem(Sender),ACanvas,ARect,Selected,'Caption6');
終わり;
終わり。