DELPHIの不思議なメニューの作成
翻訳者: Li Junyu 電子メール: [email protected],[email protected]
カスタムメニュー、テキスト、線 / Delphi 4、5
カスタムメニュー、テキスト、行/Delphi 4、5
おしゃれなメニューなど
奇抜なメニューなど。
カスタムメニュー、回転テキスト、特殊行
カスタマイズされたメニュー、回転されたテキスト、および特殊な行
Delphi 4 より前は、オーナー描画 (カスタム描画) が Windows によって実装されていましたが、Delphi 4 以降は TMainMenu クラスによって公開されなかったため、メニューのカスタマイズ (ビットマップの追加、フォントの変更など) が困難でした。しかし、この状況は修正され、メニューを思い通りにできるようになりました。
Delphi 4 より前では、オーナー描画イベント (カスタム描画イベント) は Windows によって実行されますが、 TMainMenu クラス。Delphi 4 以降、
この状況は変わり、メニューをカスタマイズできるようになりました。
この記事では、Delphi アプリケーションのメニューの外観をカスタマイズするために使用できるいくつかのテクニックを紹介します。テキストの配置、メニューのサイズ変更、フォントの割り当て、およびメニューの外観を向上させるためのビットマップと図形の使用について説明します。この記事で説明するすべてのテクニックは、ダウンロード可能なプロジェクトで実証されています。
この記事では、DELPHI アプリケーションのメニューの外観をカスタマイズするために使用できるいくつかのテクニックに焦点を当て、テキストの配置、メニューのサイズ変更、フォント設定、BMP ファイルとメニューの表示効果の拡張について説明します。 。面白い目的で、この記事ではテキストとカスタム行を回転するテクニックもクローズアップして紹介します。この記事で説明するすべてのテクニックはプロジェクト ファイルでデバッグされており、オンラインでダウンロードできます。
カスタムフォントとサイズ
フォントとサイズを設定する
カスタム メニューを作成するには、メニュー コンポーネント -TMainMenu または TPopupMenu - の OwnerDraw プロパティを True に設定し、その OnDrawItem イベントおよび OnMeasureItem イベントのイベント ハンドラーを提供します。たとえば、OnMeasureItem イベント ハンドラーは次のように宣言されます。
カスタム メニューを作成するには、TmainMenu コンポーネントまたは TpopupMenu コンポーネントの OwnerDraw プロパティを TRUE に設定し、その OnDrawItem および OnMeasureItem イベント プロシージャを作成します。たとえば、OnMeasureItem イベント プロシージャは次のように宣言できます。
プロシージャ TForm1.Option1MeasureItem(送信者: TObject;
ACanvas: TCanvas; var 幅、高さ: 整数);
幅と高さの変数を設定して、メニュー項目のサイズを調整します。Times New Roman フォントを使用してメニュー オプションを描画するためのすべての作業は、ここで行われます。 、たとえば、次のようなことを行う必要があります。
上記のイベント プロシージャでメニュー項目の幅と高さの変数を適切なサイズに設定します。主な処理はすべて OnDrawItem イベントによってトリガーされます。ここでメニューを再描画し、特別な設定を行います。たとえば、Times New Roman フォントでメニュー項目を再描画するには、次の手順を実行します。
プロシージャ TForm1.Times1DrawItem(送信者: TObject;
ACanvas: TCanvas; ARect: TRect; ブール値);
始める
ACanvas.Font.Name := 'Times New Roman';
ACanvas.TextOut(ARect.Left+1, ARect.Top+1,
(TMenuItem).Caption として送信);
終わり;
ただし、このコードには欠陥があります。実行すると、メニューのキャプションがメニューの左側の境界線に合わせて描画されます。これは通常、メニューにビットマップとチェックマークを配置するためのスペースがあります。図 1 に示すようなコードを使用して、このチェックマークに必要なスペースを計算する必要があります。図 2 は、結果のメニューを示しています。
ただし、このコードには欠陥があります。このコードを実行すると、メニュー項目のキャプションがメニュー項目の左側に配置されます。これは Windows のデフォルトの動作ではありません。通常、メニューの左側には BMP 画像と選択範囲用のスペースがあります。マーク。したがって、図 1 に示すように、コードを使用して、選択フラグを配置するために必要なスペースを計算する必要があります。図 2 は、実際のメニューを示しています。
プロシージャ TForm1.Times2DrawItem(送信者: TObject;
ACanvas: TCanvas; ARect: TRect; ブール値);
変数
dwCheck : 整数;
メニューキャプション: 文字列;
始める
// チェックマークの寸法を取得します。
選択したロゴに必要なピクセル数を取得します
dwCheck := GetSystemMetrics(SM_CXMENUCHECK);
// 左の位置を調整します。
左の位置を調整する
ARect.Left := ARect.Left + LoWord(dwCheck) + 1;
MenuCaption := (TMenuItem として送信).Caption;
// フォント名はメニューのキャプションです。
ACanvas.Font.Name := 'Times New Roman';
// テキストを描画します。
テキストを描画する
DrawText(ACanvas.Handle, PChar(MenuCaption),
長さ(MenuCaption)、ARect、0);
終わり;
図 1: この OnDrawItem イベント ハンドラーは、メニュー項目のテキストを正しく配置します。
[翻訳者は図をすべて省略しました、以下同じ]
図 2: カスタム フォントで描画されたメニュー。
テキストが大きすぎてメニューに描画できない場合は、Windows によってテキストが収まるようにカットされます。そのため、すべてのテキストが描画できるようにメニュー項目のサイズを設定する必要があります。これが、図 3 に示す OnMeasureItem イベント ハンドラーの役割です。 。
テキストが長すぎる場合、Windows はテキストに合わせて自動的にトリミングします。したがって、すべてのテキストが表示できるようにメニューのサイズを変更する必要があります。図 3 に示すように、OnMeasureItem イベントにも同じことが当てはまります。
プロシージャ TForm1.Times2MeasureItem(送信者: TObject;
ACanvas: TCanvas; var 幅、高さ: 整数);
始める
ACanvas.Font.Name := 'Times New Roman';
ACanvas.Font.Style := [];
// 幅はメニューチェックのスペースです
この長さがメニュー選択マークの長さになります
// 項目テキストの幅を加えます。
メニュー項目の長さを加えたもの
幅 := GetSystemMetrics(SM_CXMENUCHECK) +
ACanvas.TextWidth((TMenuItem として送信者).Caption) + 2;
高さ := ACanvas.TextHeight(
(TMenuItem として送信).Caption) + 2;
終わり;
図 3: この OnMeasureItem イベント ハンドラーは、項目がメニューに収まることを保証します。
カスタムシェイプとビットマップ
グラフィックスとビットマップをセットアップする
ビットマップやその他の形状を含めてメニュー項目をカスタマイズすることもできます。ビットマップを追加するには、デザイン時にオブジェクト インスペクターを使用するか、実行時にコードを使用してビットマップ ファイルを割り当てるだけです。メニュー項目のキャプションとして、図 4 に示す OnDrawItem イベント ハンドラーを使用できます。図 5 に結果を示します。
ビットマップやその他のグラフィックを使用してメニューを設定することもできます。ビットマップを追加するには、設計時にオブジェクト インスペクターで BMP ファイルを TmenuItem の Bitmap プロパティに割り当てるか、実行時にコードを使用することもできます。メニュー タイトルを色付きの四角形に置き換えるには、図 4 に示すように OnDrawItem イベントを使用できます。結果を図 5 に示します。
プロシージャ TForm1.ColorDrawItem(送信者: TObject;
ACanvas: TCanvas; ARect: TRect; ブール値);
変数
dwCheck : 整数;
メニューカラー: TColor;
始める
// チェックマークの寸法を取得します。
dwCheck := GetSystemMetrics(SM_CXMENUCHECK);
ARect.Left := ARect.Left + LoWord(dwCheck);
// メニュー項目のキャプションを色に変換します。
メニュー項目のタイトルを色に変換する
メニューカラー :=
StringToColor((TMenuItem として送信).Caption);
// キャンバスのブラシの色を変更します。
キャンバスのブラシの色を変更する
ACanvas.Brush.Color := MenuColor;
// 項目が選択されている場合、長方形を描画します。
メニュー項目が選択されている場合は長方形を描画します
// 枠線を描きます。
境界線を引く
選択された場合
ACanvas.Pen.Style := psSolid
それ以外
ACanvas.Pen.Style := psClear;
ACanvas.Rectangle(ARect.Left, ARect.Top,
ARect.Right、ARect.Bottom);
終わり;
図 4: OnDrawItem イベントを使用してメニュー項目に色付きの四角形を描画します。
図 5: 項目として色付きの長方形を備えたメニュー。
Delphi 5 を使用している場合は、メニューの AutoHotkeys プロパティを maManual に設定する必要があります。これをデフォルトの maAutomatic のままにすると、Delphi によってキャプションにアンパサンド文字 (&) が追加されます。別の解決策は、StripHotKey 関数を使用してアンパサンドを削除することです。
より一般的なアプローチは、Delphi 5 を使用している場合、メニューの AutoHotkeys プロパティを maManual に設定するというものです。これを行わずにデフォルト値の maAutomatic のままにすると、Delphi は自動的にタイトルにアンパサンドを追加し、コードが中断されてしまいます。別の解決策は、StripHotKey 関数を使用してアンパサンドを削除することです。
OnDrawItem イベントと OnMeasureItem イベントを使用するもう 1 つの方法は、メニューにテキストを垂直に書き込むことです (図 7 を参照)。これを行うには、Windows API 関数 CreateFont または CreateLogFont を使用する場合にのみ可能です。この記事で後述する「回転テキスト」のヒントを参照してください)。このイベントは、メニュー項目が描画されるたびに発生します。項目が 20 個ある場合、20 回描画されます。これを高速化するために、メニュー項目が選択されている場合にのみ縦書きテキストが描画されます (一度に選択されるメニュー項目は 1 つだけであるため)。図 6 は、これがコードでどのように実装されるかを示しています。図 7 は実行時の結果を示しています。
OnDrawItem イベントと OnMeasureItem イベントのもう 1 つの用途は、メニューの横に縦書きテキストを書き込むことです (図 7 に示すように)。これを行うには、回転フォントを作成する必要があります。唯一の方法は、Windows API の CreateFont 関数または CreateLogFont 関数を使用することです (この記事で後述する「回転テキスト」テクニックを参照してください)。したがって、OnDrawItem イベントで再描画する必要があります。このイベントはメニュー項目が取り出されたときに実行されるため、メニューに項目が 20 個ある場合、20 回実行されることになります。高速化するために、メニュー項目が選択されるたびに縦書きテキストを再描画できます (ただし、一度に選択できるメニュー項目は 1 つだけです)。図 6 はコードがどのように実行されるかを示し、図 7 は結果を示します。
プロシージャ TForm1.VerticalDrawItem(送信者: TObject;
ACanvas: TCanvas; ARect: TRect; ブール値);
変数
lf : TLogFont;
古いフォント:HF フォント;
clFore、clBack: LongInt;
長方形: TRect;
dwCheck : LongInt;
MenuHeight : 整数;
始める
dwCheck := GetSystemMetrics(SM_CXMENUCHECK);
// これは項目が選択されたときに 1 回実行されます。
これはメニュー項目が選択されたときに実行されます
選択されている場合は開始します
// 回転フォントを作成します。
回転フォントを作成する
FillChar(lf, SizeOf(lf), 0);
lf.lfHeight := -14;
lf.lfエスケープメント := 900;
lf.lfOrientation := 900;
lf.lfWeight := Fw_Bold;
StrPCopy(lf.lfFaceName, 'Arial');
// 描画するフォントを選択します。
このフォントを選択して描画します
OldFont := SelectObject(ACanvas.Handle,
CreateFontIndirect(lf));
// 前景色と背景色を変更します。
前景色と背景色を変更する
clFore := SetTextColor(ACanvas.Handle, clSilver);
clBack := SetBkColor(ACanvas.Handle, clBlack);
// メニューの高さを取得します。
メニューの高さを取得する
メニュー高さ := (ARect.Bottom-ARect.Top) *
((TMenuItem として送信者).TMenuItem として親).Count;
Rectang := Rect(-1, 0, dwCheck-1, MenuHeight);
// テキストを描画します。
テキストを描画する
ExtTextOut(ACanvas.Handle, -1, MenuHeight, Eto_Clipped,
@Rectang、「Made in Borland」、15、なし);
// 元の状態に戻します。
元の状態に戻す
DeleteObject(SelectObject(ACanvas.Handle, OldFont));
SetTextColor(ACanvas.Handle, clFore);
SetBkColor(ACanvas.Handle, clBack);
終わり;
// 実際のメニューテキストを描画します。
実際のメニュー項目のテキストを描画する
ARect.Left := ARect.Left + LoWord(dwCheck) + 2;
DrawText(ACanvas.Handle,
PChar((TMenuItem として送信).Caption),
Length((TMenuItem としての送信者).Caption), ARect, 0);
終わり;
図 6: OnDrawItem を使用してメニュー上に縦書きテキストを描画します。
図 7: 縦書きテキストのメニュー。
難しい点の 1 つは、テキストの描画をメニューの最後の項目の下部から開始する必要があることです。その位置を取得するには、次を使用します。
どこからテキストの描画を開始するかを知っておく必要があります。メニューの最後の項目の一番下から開始する必要があります。この位置を取得するために、次のようにメニュー項目の高さを取得します。
ARect.Top - ARect.Bottom
そして、それにメニュー内の項目の数を掛けます。
さらにメニュー項目の数を掛けます。
(((TMenuItem としての送信者).TMenuItem としての親).Count)
回転したテキスト
回転されたテキスト
Windows API を使用すると、任意の角度でテキストを描画できます。これを Delphi で行うには、図 8 に示すように、API 関数 CreateFont または CreateFontIndirect を使用する必要があります。
Windows API を使用すると、任意の角度でテキストを描画できます。 Delphi でこれを行うには、CreateFont または CreateFontIndirect の 2 つの API 関数を使用する必要があります。図 8 は、CreateFont がどのように宣言されるかを示しています。
関数 CreateFont(
nHeight, // フォントの論理的な高さ。
nWidth, // 論理的な平均文字幅。
nエスケープメント, // エスケープメントの回転角度。
nOrientation, // ベースラインの方向角度。
fnWeight: Integer; // フォントのウェイトのサブプロパティ。
fdwItalic, // イタリック属性フラグ。イタリックですか?
fdwUnderline, // 下線属性フラグ。
fdwStrikeOut, // 取り消し線属性フラグ。
fdwCharSet // 文字セット識別子。
fdwOutputPrecision, // 出力精度。
fdwClipPrecision, // クリッピング精度。
fdwQuality, // 出力品質。
fdwPitchAndFamily: DWORD; ピッチとファミリー。
lpszFace: PChar // 書体名文字列へのポインタ。
): HFONT;
図 8: CreateFont Windows API 関数の Object Pascal 宣言。
この関数には多くのパラメータがありますが、通常はテキストの 1 つまたは 2 つの属性のみを変更する必要があります。このような場合は、図に示すように、引数を 1 つだけ取ります (TLogFont 型のレコード)。 9.
この関数は多くのパラメーターを受け取りますが、通常はテキストの 1 つまたは 2 つのプロパティを変更するだけで済みます。この場合、代わりに CreateFontIndirect 関数を使用します。必要なパラメータは 1 つだけです (図 9 に示すように、TlogFont のレコード タイプ パラメータ)。
tagLOGFONTA = パックされたレコード
lfHeight: 倍長整数;
lfWidth: 倍長整数;
lfエスケープメント: 倍長整数;
lfOrientation: 倍長整数;
lfWeight: 倍長整数。
lf斜体: バイト。
lfUnderline: バイト;
lfStrikeOut: バイト;
lfCharSet: バイト;
lfOutPrecision: バイト;
lfClipPrecision: バイト;
lfQuality: バイト;
lfPitchAndFamily: バイト;
lfFaceName: AnsiChar の配列 [0..LF_FACESIZE - 1];
終わり;
TLogFontA = タグLOGFONTA;
TLogFont = TLogFontA;
図 9: TLogFont レコード。
このレコードを見ると、そのメンバーが CreateFont 関数のパラメーターと一致していることがわかります。この関数とレコードの組み合わせを使用する利点は、GetObject API 関数を使用してレコードのメンバーを既知のフォントで埋め、メンバーを変更できることです。新しいフォントを作成します。
このレコード タイプをよく見ると、そのメンバーが CreateFont 関数のパラメーターに非常に似ていることがわかります。この関数とレコードの組み合わせを使用する利点は、GetObject API 関数を使用してこのレコードのメンバー値に既知のフォントを入力し、変更するメンバー値を変更して新しいフォントを生成できることです。
回転したテキストを描画するには、変更する必要があるメンバーは lfEscapement だけです。これは、テキストの角度を 10 分の 1 度で設定します。そのため、テキストを 45 度で描画したい場合は、lfEscapement を 450 に設定する必要があります。
回転されたテキストを描画するために変更する必要がある唯一のメンバーは、フォントの角度を 10 分の 1 度単位で設定する lfEscapement です。したがって、キャラクターを 45 度回転させたい場合は、次のように設定する必要があります。
エスケープメントは450です。
斜体、下線、取り消し線のテキストを描画するフラグはありますが、太字のテキストを描画するフラグはないことに注意してください。これは、lfWeight メンバー (0 から 1000 までの数値) で行われます。400 は通常のテキストで、これより上の値です。太字のテキストを描画し、その下の値は明るいテキストを描画します。
テキストを斜体にしたり、下線を引いたり、強調表示したりするためのマーカーは多数ありますが、テキストを太字にするためのマーカーがないことに注意してください。これは、代わりに lfWeight メンバーが使用され、このメンバーの値が 0 ~ 1000 であるためです。 400 が通常の値で、これを超えると太字になり、これより下になると細くなります。
図 10 のコードは、0 度から 360 度の範囲の角度で 20 度間隔でテキストを描画します。これはフォームの OnPaint イベント ハンドラーであるため、フォームが描画されるたびにテキストが再描画されます。その結果を図 11 に示します。
図 10 のコードは、0 度から 360 度まで 20 度ごとに文字を描画します。これはフォームの OnPaint イベントでトリガーされるため、フォームがペイントされるたびにテキストが再描画されます。その効果は図 11 で確認できます。
プロシージャ TForm1.FormPaint(送信者: TObject);
変数
古いフォント、新しいフォント: hFont;
ログフォント: TLogFont;
i : 整数。
始める
// キャンバスフォントのハンドルを取得します。
フォームフォントオブジェクトのハンドルを取得します。
OldFont := Canvas.Font.Handle;
i := 0;
// 透明な描画。
透明度プロパティを設定する
SetBkMode(Canvas.Handle, Transparent);
// LogFont 構造体に情報を入力します
LogFont 構造に情報を入力します。
// 現在のフォントから。
現在のフォントから
GetObject(OldFont, Sizeof(LogFont), @LogFont);
// 角度の範囲は 0 ~ 360 です。
0度から360度まで
私が 3600 未満のときに始めます
// 脱進機を新しい角度に設定します。
テキストの向きを新しい角度に設定する
LogFont.lfEscapement := i;
// 新しいフォントを作成します。
新しいフォントを作成する
新しいフォント := CreateFontIndirect(LogFont);
// 描画するフォントを選択します。
出力用のフォントを選択する
SelectObject(Canvas.Handle, NewFont);
// フォームの中央にテキストを描画します。
フォームの中央にテキストを出力する
TextOut(Canvas.Handle, ClientWidth div 2,
ClientHeight div 2、'回転テキスト'、21);
// 掃除。
クリア
DeleteObject(SelectObject(Canvas.Handle, OldFont));
// 角度を 20 度ずつ増やします。
20度ごとに増加
Inc(i, 200);
終わり;
終わり;
図 10: 20 度間隔で回転したテキストを描画するコード。
図 11: 360 度回転したテキスト。
フォームのフォントは、TrueType フォントである Arial に設定されています。このコードは TrueType フォントでのみ機能します。現在のフォント設定を取得して TLogFont 構造に入力するには、GetObject API 関数を使用する必要があります。図 12 のコードは、フォームのフォントの TLogFont 設定を入力して表示する方法を示しています。
このフォームのフォントは、TrueType フォントである Arial に設定されています。このコードは TrueType フォントでのみ実行されます。他のフォントはテキストの回転をサポートしません。現在のフォント設定を取得し、TlogFont 構造体に値を入力するには、GetObject API 関数を使用する必要があります。図 12 のコードでは、フォームに TlogFont 設定を入力して表示する方法がわかります。
プロシージャ TForm1.Info1Click(送信者: TObject);
変数
ログフォント: TLogFont;
始める
// LogFont 構造体に情報を入力します
LogFont構造体のメンバー値を入力します
// 現在のフォントから。
現在のフォントから
GetObject(Canvas.Font.Handle, Sizeof(LogFont), @LogFont);
// フォント情報を表示します。
フォント情報を表示する
LogFont を使用して ShowMessage(
'lfHeight: ' + IntToStr(lfHeight) + #13 +
'lfWidth: ' + IntToStr(lfWidth) + #13 +
'lfEscapement: '+IntToStr(lfEscapement) + #13 +
'lfOrientation: ' + IntToStr(lfOrientation) + #13 +
'lfWeight: ' + IntToStr(lfWeight) + #13 +
'lfItalic: ' + IntToStr(lfItalic) + #13 +
'lfUnderline: ' + IntToStr(lfUnderline) + #13 +
'lfStrikeOut: ' + IntToStr(lfStrikeOut) + #13 +
'lfCharSet: ' + IntToStr(lfCharSet) + #13 +
'lfOutPrecision: ' + IntToStr(lfOutPrecision) + #13 +
'lfClipPrecision: ' + IntToStr(lfClipPrecision) + #13 +
'lfQuality: ' + IntToStr(lfQuality) + #13 +
'lfPitchAndFamily: '+IntToStr(lfPitchAndFamily) + #13 +
'lfFaceName: ' + string(lfFaceName));
終わり;
図 12: フォント属性の取得と表示。
TLogFont 構造体に設定を行ったら、あとは lfEscapement を目的の角度に設定し、CreateFontIndirect で新しいフォントを作成するだけです。この新しいフォントを使用する前に、SelectObject でフォントを選択する必要があります。テキストを描画する前に、この新しいフォントをキャンバスのフォントのハンドルに追加する必要があります。テキストを描画した後、この作業を元に戻し、新しいフォントを削除する必要があります。が削除されていない場合、メモリ リークが発生し、ルーチンが何度も実行されると、Windows (特に 95/98) がリソースを使い果たし、クラッシュします。
TlogFont 構造を設定したら、あとは lfEscapement の値をターゲット値に変更し、CreateFontIndirect を使用して新しいフォントを生成するだけです。この新しいフォントを使用する前に、SelectObject を使用してフォントを選択する必要があります。もう 1 つの方法は、テキストを描画する前に、この新しいフォント オブジェクトのハンドルをフォームのキャンバスのフォント オブジェクトのハンドルに使用することです。テキストを描画した後、古いフォントを選択し、新しいフォントを削除する必要があります。新しいフォントが削除されないと、メモリ リークが発生し、-----プログラムが複数回実行されると、Windows (特に 95/98) のリソースが不足します。
クラッシュ。
スタイリッシュなライン
人気のライン
線を描画する場合、通常は個々のピクセルは重要ではなく、単に線のスタイルを設定するだけで Windows によって描画されますが、場合によっては、Windows が提供していない線のスタイルを描画する必要があります。図 13 で定義されている LineDDA という名前の Windows API 関数を使用します。
線を描画する場合、通常、個々のピクセルは重要ではありません。線の種類を設定するだけで、線の描画は Windows に任せられます。ただし、Windows が提供していない特殊な線種を使用したい場合もあります。これは、LineDDA と呼ばれる API 関数を使用して実現できます。その定義は図 13 に示されています。
関数 LineDDA(
nXStart, // 線の始点の x 座標。
X座標の始点
nYStart, // ラインの開始点の y 座標。
Y座標の始点
nXEnd, // 線の終点の x 座標。
X 座標の終点
YEnd : 整数; // ラインの終点の y 座標。
Y座標終点
// アプリケーション定義のコールバック関数のアドレス。
アプリケーション定義のコールバック関数のアドレス
lpLineFunc: TFNLineDDAProc;
lpData : LPARAM // アプリケーション定義データのアドレス。
アプリケーション定義データのアドレス
): BOOL;
図 13: Windows API 関数 LineDDA の Object Pascal 宣言。
最初の 4 つのパラメータは、線の開始点と終了点です。5 番目のパラメータは、描画ルーチンを配置するたびに呼び出されるコールバック関数です。コールバック関数には、LParam であるため、任意の整数またはポインタを渡すことができます (Win32 では、倍長整数に変換されます)。コールバック関数は、次の形式をとる必要があります。
最初の 4 つのパラメータは、ラインの始点と終点です。 5 番目のパラメーターは、ピクセルが描画されるたびに呼び出されるコールバック関数です。ここに描画プロセスについて書くことができます。最後のパラメータはユーザー定義であり、コールバック関数に渡すことができます。この関数には任意の整数またはポインタを渡すことができます。
Lparam 型 (WIN32 では、Longint 型として解釈されます)。このコールバック関数は次のような形式を使用する必要があります。
プロシージャ CallBackDDA(x, y: 整数;
UserParam: LParam);
ここで、x と y は描画された点の座標であり、UserParam は関数に渡されるパラメーターです。この関数は stdcall として宣言する必要があります。図 14 のルーチンはビットマップの線を描画し、その結果を図 15 に示します。
ここで、X と Y は描画される座標点であり、UserParam はパラメータです。この関数は stdcall としてサブ定義する必要があります。図 14 のプログラムは BMP ラインをプロットし、図 15 は結果を表示します。
タイプ
TForm1 = クラス(TForm)
ImageList1: TImageList;
プロシージャ FormPaint(Sender: TObject);
プロシージャ FormResize(Sender: TObject);
終わり;
変数
フォーム1: TForm1;
プロシージャ CallDDA(x, y: 整数; 形式: TForm1);
実装
{ $R *.DFM }
プロシージャ CallDDA(x, y: 整数; 形式: TForm1);
始める
x mod 13 = 0 の場合
Form.ImageList1.Draw(Form.Canvas, x, y, 0);
終わり;
プロシージャ TForm1.FormPaint(送信者: TObject);
始める
LineDDA(0, 0, クライアント幅, クライアント高さ,
@CallDDA、整数(自己));
終わり;
プロシージャ TForm1.FormResize(送信者: TObject);
始める
無効化します。
終わり;
図 14: ビットマップの線を描画するコード。
図 15: カスタム行を含むウィンドウ。
このルーチンはフォームの OnPaint イベントを処理し、LineDDA を呼び出します。そのため、フォームを描画する必要があるたびに線を再描画します。処理されるもう 1 つのイベントは OnResize です。これはフォームのクライアント領域を無効にするため、誰かが線を変更したときに線を再描画する必要があります。 LineDDA コールバック関数 CallDDA は非常に単純で、呼び出されるたびに、ImageList に格納されているビットマップが描画されます。コールバック関数を使用して、インスタンス データにアクセスできるようにします。
このプログラムは、フォームの OnPaint イベントを処理して LineDDA を呼び出し、フォームがペイントされるたびに線を再描画します。もう 1 つのイベントは OnResize です。これはフォームのクライアント領域を無効にし、誰かがサイズを変更したときに線が再描画されるようにします。 LineDDA コールバック関数と CallDDA は非常にシンプルです。 13 回呼び出されるたびに、ImageList に格納されているビットマップが描画されます。おそらく、SELF が最後のパラメータとしてコールバック関数に渡されるため、プログラムのデータにアクセスできることに気づいたかもしれません。
結論
結論は
Delphi 4 の TMainMenu でオーナー描画が公開されて以来、ここで説明したテクニックを使用して、カスタム テキスト、ビットマップ、色を使用して Delphi アプリケーションのメニューを簡単に強化することができます。
Delphi 4 の TmainMenu にオーナー描画が登場したため、メニュー機能を拡張するさまざまな方法が可能になりました。上で説明した手法を使用すると、カスタム テキスト、ビットマップ、色を使用して DELPHI アプリケーションのメニュー機能を簡単に強化できます。