--- a/trunk/Src/FmBase.pas
+++ b/trunk/Src/FmBase.pas
@@ -25,7 +25,7 @@
  * The Initial Developer of the Original Code is Peter Johnson
  * (http://www.delphidabbler.com/).
  *
- * Portions created by the Initial Developer are Copyright (C) 2005-2011 Peter
+ * Portions created by the Initial Developer are Copyright (C) 2005-2012 Peter
  * Johnson. All Rights Reserved.
  *
  * Contributor(s)
@@ -49,7 +49,6 @@
 
 
 type
-
   {
   TBaseForm:
     Base class for all forms in application. Sets a unique window class name for
@@ -60,6 +59,7 @@
     procedure FormDestroy(Sender: TObject);
     procedure FormShow(Sender: TObject);
     procedure FormCreate(Sender: TObject);
+    procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
   strict private
     var
       fCtrlStateMgr: TControlStateMgr;  // Enables/disables all form's controls
@@ -79,6 +79,10 @@
       handled just after form is shown.
         @param Msg [in/out] Unused.
       }
+    procedure ActivateContextMenu;
+      {Activates any context menu associated with active control or any of its
+      parents.
+      }
   strict protected
     procedure CreateParams(var Params: TCreateParams); override;
       {Sets window class name to that provided by WindowClassName method if not
@@ -135,15 +139,57 @@
 
 uses
   // Delphi
-  SysUtils, Windows,
+  SysUtils, Windows, Menus,
   // Project
-  UAppInfo, UBaseObjects, UFontHelper, UNulFormAligner, UStrUtils;
-
+  UAppInfo, UBaseObjects, UFontHelper, UKeysHelper, UMenuHelper,
+  UNulFormAligner, UStrUtils;
 
 {$R *.dfm}
 
+type
+  ///  <summary>Class helper that provides information about, and access to, the
+  ///  protected PopupMenu property of TControl.</summary>
+  TControlHelper = class helper for TControl
+  public
+    ///  <summary>Gets reference to pop-up menu assigned to protected PopupMenu
+    ///  property.</summary>
+    function GetPopupMenu: TPopupMenu;
+    ///  <summary>Checks if protected PopupMenu property is assigned.</summary>
+    function HasPopupMenu: Boolean;
+  end;
 
 { TBaseForm }
+
+procedure TBaseForm.ActivateContextMenu;
+  {Activates any context menu associated with active control or any of its
+  parents.
+  }
+var
+  Ctrl: TControl;       // active control or a parent that supports pop-up menu
+  MenuIntf: IPopupMenu; // interface reference to controls supporting IPopupMenu
+  PopupPos: TPoint;     // pop-up position of menu in screen co-ords
+begin
+  // search active control parents to try to find if pop-up menu supported
+  Ctrl := ActiveControl;
+  if not Assigned(Ctrl) then
+    Ctrl := Self;
+  while Assigned(Ctrl)
+    and (Ctrl <> Self)
+    and not Ctrl.HasPopupMenu
+    and not (Supports(Ctrl, IPopupMenu, MenuIntf) and MenuIntf.HasPopup) do
+    Ctrl := Ctrl.Parent;
+  if not Assigned(Ctrl) then
+    Exit;
+  // we use an arbitrary pop-up position: may be able to improve on this
+  PopupPos := Ctrl.ClientToScreen(
+    Point(40, 40)
+  );
+  // show pop-up menu, either via PopupMenu property or via IPopupMenu interface
+  if Ctrl.HasPopupMenu then
+    Ctrl.GetPopupMenu.Popup(PopupPos.X, PopupPos.Y)
+  else if Supports(Ctrl, IPopupMenu, MenuIntf) and MenuIntf.HasPopup then
+    MenuIntf.Popup(PopupPos);
+end;
 
 procedure TBaseForm.AfterShowForm;
   {Used to perform any actions that need to occur after the form has been shown
@@ -237,6 +283,17 @@
   }
 begin
   FreeAndNil(fCtrlStateMgr);
+end;
+
+procedure TBaseForm.FormKeyDown(Sender: TObject; var Key: Word;
+  Shift: TShiftState);
+begin
+  inherited;
+  if (Key = VK_F10) and (ExtractShiftKeys(Shift) = [ssAlt]) then
+  begin
+    outputdebugstring('Alt+F10 pressed');
+    ActivateContextMenu;
+  end;
 end;
 
 procedure TBaseForm.FormShow(Sender: TObject);
@@ -318,5 +375,17 @@
   AfterShowForm;
 end;
 
+{ TControlHelper }
+
+function TControlHelper.GetPopupMenu: TPopupMenu;
+begin
+  Result := PopupMenu;
+end;
+
+function TControlHelper.HasPopupMenu: Boolean;
+begin
+  Result := Assigned(PopupMenu);
+end;
+
 end.