프로그램/바로쓰는델파이

[펌]TPopUp Menu 에 동적메뉴추가 하가

mulderu 2008. 1. 21. 01:10

How to Dynamically Add Items (Holding Custom Properties) to a TPopUp Menu

From Zarko Gajic,
Your Guide to Delphi Programming.
FREE Newsletter. Sign Up Now!

When working with Menus or PopUp menus in Delphi applications, in most scenarios, you create the menu items at design-time. Each menu item is represented by a TMenuItem Delphi class. When a user selects (clicks) an item, the OnClick event is fired for you (as a developer) to grab the event and respond to it.

There may be situations when the items of the menu are not known at design time, but need to be added at run-time (dynamically instantiated).

Add TMenuItem at Run-Time

Suppose there is a TPopupMenu component named "PopupMenu1" on a Delphi form, to add an item to the popup menu you could write a piece of code as:
var
  menuItem : TMenuItem;
begin
 menuItem := TMenuItem.Create(PopupMenu1) ;

 menuItem.Caption := 'Item added at ' + TimeToStr(now) ;

 menuItem.OnClick := PopupItemClick;

 //assign it a custom integer value..
 menuItem.Tag := GetTickCount;

 PopupMenu1.Items.Add(menuItem) ;
end;
Notes: In the above code, one item is added to the PopupMenu1 component.

Important: when dynamically added item is clicked, the "PopupItemClick" will be executed. In order to differentiate between one or more run-time added items (all executing the code in PopupItemClick) we can use the Sender parameter:
procedure TMenuTestForm.PopupItemClick(Sender: TObject) ;
var
  menuItem : TMenuItem;
begin
  if NOT (Sender is TMenuItem) then
  begin
    ShowMessage('Hm, if this was not called by Menu Click, who called this?!') ;
    ShowMessage(Sender.ClassName) ;
    exit;
  end;

  menuItem := TMenuItem(sender) ;
  ShowMessage(Format('Clicked on "%s", TAG value: %d',[menuItem.Name, menuItem.Tag])) ;

end;
The "PopupItemClick" method first checks if the Sender is actually a TMenuItem object. If the method is executed as a result of a menu item OnClick event handler we simply show a dialog message with the Tag value being assigned when the menu item was added to the menu.

Custom String in (run-time created) TMenuItem?

In real world applications, you might/would need more flexibility. Let's say that each item will "represent" a web page - a string value would be required to hold the URL of the web page. When the user selects this item you could open the default web browser and navigate to the URL assigned with the menu item.

Here's a custom TMenuItemExtended class equipped with a custom string "Value" property:

type
  TMenuItemExtended = class(TMenuItem)
  private
   fValue: string;
  published
   property Value : string read fValue write fValue;
  end;
Here's how to add this "exetended" menu item to a PoupMenu1:
var
  menuItemEx : TMenuItemExtended;
begin
  menuItemEx := TMenuItemExtended.Create(PopupMenu1) ;

  menuItemEx.Caption := 'Extended added at ' + TimeToStr(now) ;

  menuItemEx.OnClick := PopupItemClick;

  //assign it a custom integer value..
  menuItemEx.Tag := GetTickCount;

  //this one can even hold a string value
  menuItemEx.Value := 'http://delphi.about.com';

  PopupMenu1.Items.Add(menuItemEx) ;
end;
Now, the "PopupItemClick" must be modified to properly process this menu item:
procedure TMenuTestForm.PopupItemClick(Sender: TObject) ;
var
  menuItem : TMenuItem;
begin
  //...same as above

  if sender is TMenuItemExtended then
  begin
    ShowMessage(Format('Ohoho Extended item .. here''s the string value : %s',[TMenuItemExtended(Sender).Value])) ;
  end;
end;

Note: to actually open up the default Web Browser you can use the Value property as a parameter to a ShellExecuteEx API function.

That's all. It's up to you to extend the TMenuItemExtended as per your needs. The Creating custom Delphi components is where to look for help on creating your own classes/components.

Source Code

Download