Как динамически создать PopupMenu

На форме имеется кнопка Button1, для которой будем создавать меню и TMemo (Memo1), в котором будем проверять действие команд меню.
Исходный код:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls,
Forms, Dialogs, StdCtrls, ExtCtrls, Menus;
const
//наши ID сообщений
WM_1TEST = WM_USER + 101;
WM_2TEST = WM_USER + 102;
WM_3TEST = WM_USER + 103;
type
TForm1 = class(TForm)
Button1: TButton;
Memo1: TMemo;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
protected
procedure WMCommand(
var Msg: TWMCommand); message WM_COMMAND;
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
{ TForm1 }
procedure TForm1.WMCommand(var Msg: TWMCommand);
begin
case Msg.ItemID of //<- Msg.ItemID содержит WM_USER + x
WM_1TEST : Memo1.Lines.Add('Command 1');
WM_2TEST : Memo1.Lines.Add('Command 2');
WM_3TEST : Memo1.Lines.Add('Command 3');
end;
inherited; //<- Важно для Windows-MessageHandling
end;
procedure TForm1.Button1Click(Sender: TObject);
var
MyPopUpMenu : TPopUpMenu;
MyMsg : LongBool;
begin
MyPopUpMenu := TPopUpMenu.Create(Self);
MyPopUpMenu.AutoPopup := FALSE;
MyPopUpMenu.AutoHotkeys := maManual;
{ Создаем пункты меню
AppendMenu здесь достаточно, если просто обрабатывать OnClickEvent
можно даже использовать с if или case, если не хотите обрабатывать все
пункты каждый раз }
AppendMenu(MyPopUpMenu.Handle
, MF_POPUP //<- каждый пункт на отдельной строке
// иначе используйте
// MF_MENUBREAK для столбцов с пунктами меню (все на одной строке)
// MF_MENUBARBREAK для столбцов с разделителем
or MF_STRING or MF_UNCHECKED
, WM_1TEST //<- Важно WM_USER+x идентифицирует Msg в WMCommand
, 'Test1'); // Заголовок пункта меню
AppendMenu(MyPopUpMenu.Handle
, MF_POPUP or MF_STRING or MF_UNCHECKED
, WM_2TEST //<- Важно WM_USER+x идентифицирует Msg в WMCommand
, 'Test2');
AppendMenu(MyPopUpMenu.Handle
, MF_POPUP or MF_STRING or MF_UNCHECKED
, WM_3TEST //<- Важно WM_USER+x идентифицирует Msg в WMCommand
, 'Test3');
MyMsg := TrackPopupMenuEx(MyPopUpMenu.Handle // PopUpMenu для показа
// Определяем точку выравнивания!
// горизонталь вертикаль
, TPM_LEFTALIGN or TPM_BOTTOMALIGN
//в этом случае слева вверху
//, TPM_LEFTALIGN or TPM_TOPALIGN
//, TPM_LEFTALIGN or TPM_VCENTERALIGN
//, TPM_RIGHTALIGN or TPM_BOTTOMALIGN
//, TPM_RIGHTALIGN or TPM_TOPALIGN
//, TPM_RIGHTALIGN or TPM_VCENTERALIGN
//, TPM_CENTERALIGN or TPM_BOTTOMALIGN
//, TPM_CENTERALIGN or TPM_TOPALIGN
//, TPM_CENTERALIGN or TPM_VCENTERALIGN
//or TPM_VERTICAL or TPM_HORIZONTAL
//Вы могли определить область перекрытия PopUpMenu
//но Вы должны определить структуру TPMPARAMS(~TRect) (last Param)
or TPM_RETURNCMD //Возвращает идентификатор пункта, по которому щелкнули
//or TPM_NONOTIFY //никакое сообщение не посылается
or TPM_LEFTBUTTON //выбор левой кнопкой
//or TPM_RIGHTBUTTON //выбор правой кнопкай
//or TPM_LEFTBUTTON or TPM_RIGHTBUTTON// или обеими
or TPM_HORPOSANIMATION or TPM_VERNEGANIMATION
//^эти настройки смотрятся лучше всего с TPM_LEFTALIGN и TPM_BOTTOMALIGN
//может также быть:
//TPM_NOANIMATION
//or TPM_HORNEGANIMATION or TPM_VERPOSANIMATION
, TControl(Sender).ClientOrigin.x //Origin of Menu X
//+TControl(Sender).Width //используйте TPM_RIGHTALIGN и TPM_BOTTOMALIGN
, TControl(Sender).ClientOrigin.y //начало меню Y
//Левая верхняя точка управления, где Вы хотите разместить меню
, Self.Handle //<- Дескриптор Window/Application
, nil); //<- структура TPMPARAMS, nil , заставляем PopUp Menu быть слева и вверху
if MyMsg then //<- TrackPopUpMenuEx возвращает TRUE если все хорошо
SendMessage(Self.Handle //<- посылаем сообщение окну
, WM_COMMAND //<- Тип сообщения
, Integer(MyMsg) //<- Param, т.е. ReturnValue TrackPopUpMenuEx
, 0);
MyPopUpMenu.Free; //<- уничтожаем созданное PopUpMenu
MyPopUpMenu := nil;
end;
end.
Комментарии