>ヒントウィンドウ等も表示した方がいいかも知れません.
残念ながら,TPopupMenu は Delphi のコントロールではなく,
Windows API の TrackPopupMenu を実行しています.
したがって,そのままではヒントウィドウを表示できません.
ヒントプロパティを実装すればできるかも知れませんが,確認していません.
TPopupMenu あるいは TMenuItem が TPanel のようにコンテナにできれば,
自由に他のコントロールが配置できるのですが...
下の図は,サンプルプログラム集の [261_マウスカーソル位置に画像を表示] を
実行してから,次のコードを実行したものです.
カエルの画像の代わりに,文字列を表示すれば,ヒントウィンドウの代わりに
なるかと思います.
文字列は,Item の画像の位置,つまりマウスカーソルの位置によって変更します.
そのためには,マウスカーソルの位置を知る必要があります.
そこで,マウスのローカルフックを実行しています.
フックは,アプリ開始と同時に開始して,終了時に終了してもいいのですが,
ポップアップメニュー表示開始時にフック開始とし,閉じたらフック終了に
することにしています.
TPopupMenu には,ポップアップウィンドウ以外の場所をクリックして閉じた時の
イベントがありません.
そこで,TPopupList.WndProc で,WM_EXITMENULOOP を検出しています.
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls, Menus, ImgList;
type
TPopupListEx = class(TPopupList)
protected
procedure WndProc(var Message: TMessage) ; override;
end;
TForm1 = class(TForm)
Button1: TButton;
PopupMenu1: TPopupMenu;
Item_0: TMenuItem;
Item_1: TMenuItem;
Item_2: TMenuItem;
Item_3: TMenuItem;
N1: TMenuItem;
ImageList1: TImageList;
Panel1: TPanel;
procedure Item_0AdvancedDrawItem(Sender: TObject; ACanvas: TCanvas;
ARect: TRect; State: TOwnerDrawState);
procedure Item_0MeasureItem(Sender: TObject; ACanvas: TCanvas; var Width,
Height: Integer);
procedure Item_0Click(Sender: TObject);
procedure PopupMenu1Popup(Sender: TObject);
private
{ Private 宣言 }
RectImage : array [0..3] of TRect;
protected
procedure WMExitMenuLoop(var Message: TWMExitMenuLoop);
message WM_EXITMENULOOP;
public
{ Public 宣言 }
procedure WMApp100(var Message: TMessage); message WM_APP+100;
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
var
hMouseHook : HHOOK;
//-----------------------------------------------------------------------------
// マウスフックのコールバック関数
// Form1にメッセージを送る
//-----------------------------------------------------------------------------
function MouseHookProc(nCode: Integer; wPar: WPARAM; lPar:LPARAM):
Integer; stdcall;
var
MousePos : TPoint;
begin
if nCode < 0 then begin
Result := CallNextHookEx(hMouseHook, nCode, wPar, lPar);
end else begin
if nCode = HC_ACTION then begin
MousePos := PMouseHookStruct(lPar)^.pt;
PostMessage(Form1.Handle, WM_APP+100, wPar, MakeLParam(MousePos.X, MousePos.Y));
end;
Result := CallNextHookEx(hMouseHook, nCode, wPar, lPar);
end;
end;
//-----------------------------------------------------------------------------
// PopupMenuを表示した時のイベント処理
// マウスフックを開始する
//-----------------------------------------------------------------------------
procedure TForm1.PopupMenu1Popup(Sender: TObject);
begin
if hMouseHook = 0 then
hMouseHook := SetWindowsHookEx(WH_MOUSE, @MouseHookProc, 0, GetCurrentThreadID);
end;
//-----------------------------------------------------------------------------
// PopupMenuが閉じた時のメッセージ処理
// マウスフックを終了する
//-----------------------------------------------------------------------------
procedure TForm1.WMExitMenuLoop(var Message: TWMExitMenuLoop);
begin
if hMouseHook <> 0 then begin
UnhookWindowsHookEx(hMouseHook);
hMouseHook := 0;
end;
Panel1.Caption := '閉じた';
end;
//-----------------------------------------------------------------------------
// PopupMenu1のItem_0項目のOnAdvancedDrawItemイベント処理
// ImageListに格納してあるビットマップ画像を表示
//
// PopupMenu1のOwnerDrawプロパティをTrueにしておく
//-----------------------------------------------------------------------------
procedure TForm1.Item_0AdvancedDrawItem(Sender: TObject; ACanvas: TCanvas;
ARect: TRect; State: TOwnerDrawState);
var
aBitmap : TBitmap;
ItemWidth : Integer;
ItemHeigh : Integer;
aLeft : Integer;
aPos : TPoint;
infMargin : Integer;
i : Integer;
begin
ItemWidth := ImageList1.Width + 5;
ItemHeigh := ImageList1.Height + 10;
aPos := PopupMenu1.PopupPoint;
aBitmap := TBitmap.Create;
try
infMargin := -5;
InflateRect(ARect, infMargin, infMargin);
aLeft := ARect.Left + 5;
aPos.X := aPos.X + 5 - infMargin;
for i := 0 to Length(RectImage) - 1 do begin
RectImage[i] := Rect(aPos.X, aPos.Y, aPos.X + ItemWidth, aPos.Y + ItemHeigh);
aBitmap.Assign(nil);
ImageList1.GetBitmap(i, aBitmap);
ACanvas.Draw(aLeft, ARect.Top, aBitmap);
aLeft := aLeft + ItemWidth;
aPos.X := aPos.X + ItemWidth;
end;
finally
aBitmap.Free;
end;
end;
//-----------------------------------------------------------------------------
// PopupMenu1のItem_0項目のOnMeasureItemイベント処理
// 項目の幅と高さを設定
//-----------------------------------------------------------------------------
procedure TForm1.Item_0MeasureItem(Sender: TObject; ACanvas: TCanvas; var Width,
Height: Integer);
begin
Height := ImageList1.Height + 10;
Width := (ImageList1.Width + 5) * Length(RectImage);
end;
//-----------------------------------------------------------------------------
// PopupMenu1のItem_0項目のOnClickイベント処理
// クリックした画像を,マウスクカーソルの位置から判定する
//-----------------------------------------------------------------------------
procedure TForm1.Item_0Click(Sender: TObject);
var
aPos : TPoint;
i : Integer;
begin
if TMenuItem(Sender) = Item_0 then begin
GetCursorPos(aPos);
for i := 0 to Length(RectImage) - 1 do begin
if PtInRect(RectImage[i], aPos) then begin
ShowMessage(IntToStr(i + 1) + ' 番目の画像クリック');
break;
end;
end;
if hMouseHook <> 0 then begin
UnhookWindowsHookEx(hMouseHook);
hMouseHook := 0;
end;
end;
Panel1.Caption := '閉じた';
end;
end;
//-----------------------------------------------------------------------------
// ローカルマウスフックのメッセージを受信
// マウスカーソルの座標値を取得して表示
//-----------------------------------------------------------------------------
procedure TForm1.WMApp100(var Message: TMessage);
var
X : Integer;
Y : Integer;
begin
X := LOWORD(Message.LParam);
Y := HIWORD(Message.LParam);
Panel1.Caption := 'X: ' + IntToStr(X) + ' Y: ' + IntToStr(Y);
end;
//-----------------------------------------------------------------------------
// PopupMenuが閉じるとWM_EXITMENULOOPメッセージを発行する
// このメッセージを受信したら,アプリのアクティブなフォームにメッセージを送る
//-----------------------------------------------------------------------------
{ TPopupListEx }
procedure TPopupListEx.WndProc(var Message: TMessage);
begin
if Screen.Activeform <> nil then begin
if Message.Msg = WM_EXITMENULOOP then begin
Screen.ActiveForm.Perform(WM_EXITMENULOOP, Message.WParam, Message.LParam);
end;
end;
inherited;
end;
initialization
Popuplist.Free;
PopupList:= TPopupListEx.Create;
end.
|