Comment sélectionner un Élément de Menu sans fermer le Menu?
par défaut lorsque vous sélectionnez un élément D'un TMainMenu ou D'un TPopupMenu etc, le menu se ferme après qu'il a été cliqué. Je voudrais changer ce comportement de sorte que lorsque je sélectionne sur un élément de menu, le menu ne se ferme pas mais reste visible et ouverte à l'endroit où il a été cliqué pour la dernière fois, ce qui rend plus facile de sélectionner un autre élément de menu si vous le souhaitez. Bien sûr, changer de focus sur un autre contrôle devrait cacher le menu comme normal, mais si le focus est toujours sur le menu, gardez-le visible.
Si ce est possible, je voudrais que ce comportement ne fonctionne que sur des éléments de menu spécifiés. En d'autres termes, si je peux faire fonctionner tous les éléments du menu comme la normale, mais si je spécifie un ou deux éléments du menu, ceux-ci ne fermeront pas le menu une fois sélectionné.
la raison pour laquelle je veux faire ceci est comme ceci, j'ai un formulaire de préférences dans mon Application où beaucoup d'options peuvent être configurées, les choses habituelles etc, mais aussi dans la forme principale j'ai quelques-unes des options les plus fréquemment utilisées définies dans un TMainMenu. Ils options communes dans mon menu je voudrais pouvoir sélectionner sans fermer le menu, de sorte que d'autres options peuvent être sélectionnées par exemple sans avoir à naviguer à travers les éléments du menu.
Existe-t-il une façon normalisée d'y parvenir?
Merci
Craig.
4 réponses
dans le code ci-dessous, quand droit cliqué sur le panneau sur le formulaire, un menu popup avec trois articles est lancé. Le premier item se comporte normalement, les deux autres items déclenchent aussi leurs évènements de clic mais le menu popup n'est pas fermé.
le popup est lancé avec 'TrackPopupMenu', si à la place vous souhaitez utiliser' OnPopup ' événements, ou besoin d'utiliser des sous-menus ayant des éléments non-closing, se référer au lien dans le commentaire que j'ai posté à votre question. Adapter le code pour un menu principal ne serait pas être difficile..
Je ne commente pas le code pour ne pas promouvoir l'usage de l'approche puisqu'il fait usage d'un message non documenté, aussi je sens qu'il est un peu alambiqué..
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, Menus, ExtCtrls;
type
TForm1 = class(TForm)
PopupMenu1: TPopupMenu;
Item1Normal1: TMenuItem;
Item2NoClose1: TMenuItem;
Item3NoClose1: TMenuItem;
Panel1: TPanel;
procedure Panel1ContextPopup(Sender: TObject; MousePos: TPoint;
var Handled: Boolean);
private
FGetPopupWindowHandle: Boolean;
FPopupWindowHandle: HWND;
OrgPopupWindowProc, HookedPopupWindowProc: Pointer;
FSelectedItemID: UINT;
procedure WmInitMenuPopup(var Msg: TWMInitMenuPopup); message WM_INITMENUPOPUP;
procedure WmEnterIdle(var Msg: TWMEnterIdle); message WM_ENTERIDLE;
procedure WmMenuSelect(var Msg: TWMMenuSelect); message WM_MENUSELECT;
procedure PopupWindowProc(var Msg: TMessage);
procedure MenuSelectPos(Menu: TMenu; ItemPos: UINT; out CanClose: Boolean);
procedure MenuSelectID(Menu: TMenu; ItemID: UINT; out CanClose: Boolean);
public
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.Panel1ContextPopup(Sender: TObject; MousePos: TPoint;
var Handled: Boolean);
var
Pt: TPoint;
begin
Pt := (Sender as TPanel).ClientToScreen(MousePos);
TrackPopupMenu(PopupMenu1.Handle, 0, Pt.X, Pt.Y, 0, Handle, nil);
end;
procedure TForm1.WmInitMenuPopup(var Msg: TWMInitMenuPopup);
begin
inherited;
if Msg.MenuPopup = PopupMenu1.Handle then
FGetPopupWindowHandle := True;
end;
procedure TForm1.WmEnterIdle(var Msg: TWMEnterIdle);
begin
inherited;
if FGetPopupWindowHandle then begin
FGetPopupWindowHandle := False;
FPopupWindowHandle := Msg.IdleWnd;
HookedPopupWindowProc := classes.MakeObjectInstance(PopupWindowProc);
OrgPopupWindowProc := Pointer(GetWindowLong(FPopupWindowHandle, GWL_WNDPROC));
SetWindowLong(FPopupWindowHandle, GWL_WNDPROC, Longint(HookedPopupWindowProc));
end;
end;
procedure TForm1.WmMenuSelect(var Msg: TWMMenuSelect);
begin
inherited;
if Msg.Menu = PopupMenu1.Handle then
FSelectedItemID := Msg.IDItem;
end;
const
MN_BUTTONDOWN = ED;
procedure TForm1.PopupWindowProc(var Msg: TMessage);
var
NormalItem: Boolean;
begin
case Msg.Msg of
MN_BUTTONDOWN:
begin
MenuSelectPos(PopupMenu1, UINT(Msg.WParamLo), NormalItem);
if not NormalItem then
Exit;
end;
WM_KEYDOWN:
if Msg.WParam = VK_RETURN then begin
MenuSelectID(PopupMenu1, FSelectedItemID, NormalItem);
if not NormalItem then
Exit;
end;
WM_DESTROY:
begin
SetWindowLong(FPopupWindowHandle, GWL_WNDPROC, Longint(OrgPopupWindowProc));
classes.FreeObjectInstance(HookedPopupWindowProc);
end;
end;
Msg.Result := CallWindowProc(OrgPopupWindowProc, FPopupWindowHandle,
Msg.Msg, Msg.WParam, Msg.LParam);
end;
procedure TForm1.MenuSelectID(Menu: TMenu; ItemID: UINT; out CanClose: Boolean);
var
Item: TMenuItem;
begin
CanClose := True;
Item := Menu.FindItem(ItemID, fkCommand);
if Assigned(Item) then begin
// Menu Item is clicked
Item.Click;
// Panel1.Caption := Item.Name;
CanClose := Item = Item1Normal1;
end;
end;
procedure TForm1.MenuSelectPos(Menu: TMenu; ItemPos: UINT; out CanClose: Boolean);
begin
MenuSelectID(Menu, GetMenuItemID(Menu.Handle, ItemPos), CanClose);
end;
end.
basé sur le code de @Sertac et d'autres ressources, j'ai fait une petite unité qui fait une classe D'Interposer de TPopupMenu
et TMainMenu
(également pour les versions TNT).
il gère également les sous-menus (chaque fois qu'un sous-menu est activé, une nouvelle fenêtre de menu est créée avec une nouvelle poignée de menu).
l'idée était de créer un crochet défini par l'application (WH_CALLWNDPROC
) avec une durée de vie aussi courte que possible. Le crochet ne sera actif que tant que le menu boucle modale est actif. Une fois l' hook détecte une nouvelle poignée de fenêtre Popup (via WM_ENTERIDLE
), il la sous-classe ensuite jusqu'à ce qu'elle soit détruite.
{.$DEFINE TNT}
unit AppTrackMenus;
interface
uses
Windows, Messages, SysUtils, Classes, Controls, Forms, Contnrs, Menus
{$IFDEF TNT}, TntMenus{$ENDIF};
type
TTrackMenuNotifyEvent = procedure(Sender: TMenu; Item: TMenuItem; var CanClose: Boolean) of object;
TPopupMenu = class(Menus.TPopupMenu)
private
FTrackMenu: Boolean;
FOnTrackMenuNotify: TTrackMenuNotifyEvent;
public
procedure Popup(X, Y: Integer); override;
property TrackMenu: Boolean read FTrackMenu write FTrackMenu;
property OnTrackMenuNotify: TTrackMenuNotifyEvent read FOnTrackMenuNotify write FOnTrackMenuNotify;
end;
{$IFDEF TNT}
TTntPopupMenu = class(TntMenus.TTntPopupMenu)
private
FTrackMenu: Boolean;
FOnTrackMenuNotify: TTrackMenuNotifyEvent;
public
procedure Popup(X, Y: Integer); override;
property TrackMenu: Boolean read FTrackMenu write FTrackMenu;
property OnTrackMenuNotify: TTrackMenuNotifyEvent read FOnTrackMenuNotify write FOnTrackMenuNotify;
end;
{$ENDIF}
TMainMenu = class(Menus.TMainMenu)
private
FTrackMenu: Boolean;
FOnTrackMenuNotify: TTrackMenuNotifyEvent;
public
property TrackMenu: Boolean read FTrackMenu write FTrackMenu;
property OnTrackMenuNotify: TTrackMenuNotifyEvent read FOnTrackMenuNotify write FOnTrackMenuNotify;
end;
{$IFDEF TNT}
TTntMainMenu = class(TntMenus.TTntMainMenu)
private
FTrackMenu: Boolean;
FOnTrackMenuNotify: TTrackMenuNotifyEvent;
public
property Hook: Boolean read FTrackMenu write FTrackMenu;
property OnTrackMenuNotify: TTrackMenuNotifyEvent read FOnTrackMenuNotify write FOnTrackMenuNotify;
end;
{$ENDIF}
procedure FormMainMenuWndProcMessage(var Msg: TMessage; AForm: TCustomForm);
implementation
const
{ Undocumented Menu Messages }
MN_SETHMENU = E0;
MN_GETHMENU = E1;
MN_SIZEWINDOW = E2;
MN_OPENHIERARCHY = E3;
MN_CLOSEHIERARCHY = E4;
MN_SELECTITEM = E5;
MN_CANCELMENUS = E6;
MN_SELECTFIRSTVALIDITEM = E7;
MN_GETPPOPUPMENU = EA;
MN_FINDMENUWINDOWFROMPOINT = EB;
MN_SHOWPOPUPWINDOW = EC;
MN_BUTTONDOWN = ED;
MN_MOUSEMOVE = EE;
MN_BUTTONUP = EF;
MN_SETTIMERTOOPENHIERARCHY = F0;
MN_DBLCLK = F1;
var
ActiveHookMenu: TMenu = nil;
type
TPopupWndList = class;
TPopupWnd = class
private
FHandle: THandle;
FMenuHandle: HMENU;
FOrgPopupWindowProc, FHookedPopupWindowProc: Pointer;
FSelectedItemPos: Integer;
FSelectedItemID: UINT;
FHooked: Boolean;
FPopupWndList: TPopupWndList;
function GetHMenu: HMENU;
procedure PopupWindowProc(var Msg: TMessage);
procedure Hook;
procedure UnHook;
procedure MenuSelectPos(Menu: TMenu; ItemPos: UINT; out CanClose: Boolean);
procedure MenuSelectID(Menu: TMenu; ItemID: UINT; out CanClose: Boolean);
public
property Handle: THandle read FHandle write FHandle;
property MenuHandle: HMENU read FMenuHandle;
constructor Create(APopupWndList: TPopupWndList; AHandle: THandle); overload;
destructor Destroy; override;
end;
TPopupWndList = class(TObjectList)
public
function FindHookedPopupHWnd(MenuWindow: HWND): TPopupWnd;
function FindHookedPopupHMenu(Menu: HMENU): TPopupWnd;
end;
{ TPopupWnd }
constructor TPopupWnd.Create(APopupWndList: TPopupWndList; AHandle: THandle);
begin
inherited Create;
FHandle := AHandle;
FMenuHandle := GetHMenu;
FPopupWndList := APopupWndList;
Hook;
end;
destructor TPopupWnd.Destroy;
begin
if FHooked then // JIC: normally UnHook is called in PopupWindowProc WM_DESTROY
UnHook;
inherited;
end;
procedure TPopupWnd.Hook;
begin
FOrgPopupWindowProc := Pointer(GetWindowLong(FHandle, GWL_WNDPROC));
FHookedPopupWindowProc := MakeObjectInstance(PopupWindowProc);
SetWindowLong(FHandle, GWL_WNDPROC, Longint(FHookedPopupWindowProc));
FHooked := True;
end;
procedure TPopupWnd.UnHook;
begin
SetWindowLong(FHandle, GWL_WNDPROC, Longint(FOrgPopupWindowProc));
FreeObjectInstance(FHookedPopupWindowProc);
FHooked := False;
end;
procedure TPopupWnd.PopupWindowProc(var Msg: TMessage);
var
NormalItem: Boolean;
begin
case Msg.Msg of
MN_SELECTITEM:
begin
// -1 ($FFFF) => mouse is outside the menu window
FSelectedItemPos := Integer(Msg.wParam); // HiWord(Msg.wParam)
end;
MN_DBLCLK:
begin
Exit; // eat
end;
MN_BUTTONDOWN:
begin
MenuSelectPos(ActiveHookMenu, UINT(Msg.WParamLo), NormalItem);
if not NormalItem then
Exit;
end;
WM_KEYDOWN:
if (Msg.WParam = VK_RETURN) and (FSelectedItemPos <> -1) and (FSelectedItemID <> 0) then begin
MenuSelectID(ActiveHookMenu, FSelectedItemID, NormalItem);
if not NormalItem then
Exit;
end;
WM_DESTROY:
begin
UnHook;
end;
end;
Msg.Result := CallWindowProc(FOrgPopupWindowProc, FHandle, Msg.Msg, Msg.WParam, Msg.LParam);
end;
procedure TPopupWnd.MenuSelectPos(Menu: TMenu; ItemPos: UINT; out CanClose: Boolean);
begin
MenuSelectID(Menu, GetMenuItemID(GetHMenu, ItemPos), CanClose);
end;
function GetMenuItemPos(Menu: HMENU; ItemID: UINT): Integer;
var
I: Integer;
MenuItemInfo: TMenuItemInfo;
begin
Result := -1;
if IsMenu(Menu) then
for I := 0 to GetMenuItemCount(Menu) do
begin
FillChar(MenuItemInfo, SizeOf(MenuItemInfo), 0);
MenuItemInfo.cbSize := SizeOf(MenuItemInfo);
MenuItemInfo.fMask := MIIM_ID;
if (GetMenuItemInfo(Menu, I, True, MenuItemInfo)) then
if MenuItemInfo.wID = ItemID then
begin
Result := I;
Exit;
end;
end;
end;
procedure TPopupWnd.MenuSelectID(Menu: TMenu; ItemID: UINT; out CanClose: Boolean);
var
Item: TMenuItem;
NotifyEvent: TTrackMenuNotifyEvent;
R: TRect;
begin
CanClose := True;
Item := Menu.FindItem(ItemID, fkCommand);
if Assigned(Item) then
begin
NotifyEvent := nil;
{$IFDEF TNT}
if Menu is TTntPopupMenu then
NotifyEvent := TTntPopupMenu(Menu).FOnTrackMenuNotify
else
{$ENDIF}
if Menu is TPopupMenu then
NotifyEvent := TPopupMenu(Menu).FOnTrackMenuNotify
else
{$IFDEF TNT}
if Menu is TTntMainMenu then
NotifyEvent := TTntMainMenu(Menu).FOnTrackMenuNotify
else
{$ENDIF}
if Menu is TMainMenu then
NotifyEvent := TMainMenu(Menu).FOnTrackMenuNotify;
if Assigned(NotifyEvent) then
NotifyEvent(Menu, Item, CanClose);
if not CanClose then
begin
Item.Click;
if GetMenuItemRect(FHandle, FMenuHandle, GetMenuItemPos(FMenuHandle, ItemID), R) then
begin
MapWindowPoints(0, FHandle, R, 2);
InvalidateRect(FHandle, @R, False);
end else
InvalidateRect(FHandle, nil, False);
end;
end;
end;
function TPopupWnd.GetHMenu: HMENU;
begin
Result := SendMessage(FHandle, MN_GETHMENU, 0, 0);
end;
{ TPopupWndList }
function TPopupWndList.FindHookedPopupHWnd(MenuWindow: HWND): TPopupWnd;
var
I: Integer;
PopupWnd: TPopupWnd;
begin
Result := nil;
for I := 0 to Count - 1 do
begin
PopupWnd := TPopupWnd(Items[I]);
if (PopupWnd.FHooked) and (PopupWnd.Handle = MenuWindow) then
begin
Result := PopupWnd;
Exit;
end;
end;
end;
function TPopupWndList.FindHookedPopupHMenu(Menu: HMENU): TPopupWnd;
var
I: Integer;
PopupWnd: TPopupWnd;
begin
Result := nil;
for I := 0 to Count - 1 do
begin
PopupWnd := TPopupWnd(Items[I]);
if (PopupWnd.FHooked) and (PopupWnd.MenuHandle{GetHMenu} = Menu) then
begin
Result := PopupWnd;
Exit;
end;
end;
end;
var
PopupWndList: TPopupWndList = nil;
MenuCallWndHook: HHOOK = 0;
SelectedItemID: UINT = 0;
NeedPopupWindowHandle: Boolean = False;
InitMenuPopupCount: Integer = 0;
function CallWndHookProc(nCode: Integer; wParam: WPARAM; Msg: PCWPStruct): LRESULT; stdcall;
var
Menu: HMENU;
MenuWnd: HWND;
PopupWnd: TPopupWnd;
begin
if (nCode = HC_ACTION) then
begin
case Msg.message of
WM_INITMENUPOPUP:
begin // TWMInitMenuPopup
Inc(InitMenuPopupCount);
NeedPopupWindowHandle := True;
SelectedItemID := 0;
if PopupWndList = nil then
begin
PopupWndList := TPopupWndList.Create(True); // OwnsObjects
end;
end;
WM_UNINITMENUPOPUP:
begin
Dec(InitMenuPopupCount);
end;
WM_ENTERIDLE:
begin
if (Msg.wParam = MSGF_MENU) and NeedPopupWindowHandle then
begin
NeedPopupWindowHandle := False;
MenuWnd := HWND(Msg.lParam);
if Assigned(PopupWndList) and (PopupWndList.FindHookedPopupHWnd(MenuWnd) = nil) then
PopupWndList.Add(TPopupWnd.Create(PopupWndList, MenuWnd));
end;
end;
WM_MENUSELECT:
begin
// MSDN: If the high-order word of wParam contains 0xFFFF and the lParam parameter contains NULL, the system has closed the menu.
if (Msg.lParam = 0) and (HiWord(Msg.wParam) = $FFFF) then // Menu Closed
begin
FreeAndNil(PopupWndList);
end
else
begin
Menu := HMENU(Msg.lParam);
if HiWord(Msg.wParam) and MF_POPUP <> 0 then // fkHandle
SelectedItemID := GetSubMenu(Menu, LoWord(Msg.WParam))
else // fkCommand
SelectedItemID := LoWord(Msg.wParam); // TWMMenuSelect(Msg).IDItem;
if Assigned(PopupWndList) then
begin
PopupWnd := PopupWndList.FindHookedPopupHMenu(Menu);
if Assigned(PopupWnd) then
begin
PopupWnd.FSelectedItemID := LoWord(Msg.wParam);
end;
end;
end;
end;
end;
end;
Result := CallNextHookEx(MenuCallWndHook, nCode, WParam, Longint(Msg));
end;
procedure InstallMenuCallWndHook(Menu: TMenu);
begin
ActiveHookMenu := Menu;
MenuCallWndHook := SetWindowsHookEx(WH_CALLWNDPROC, @CallWndHookProc, 0, GetCurrentThreadId);
end;
procedure UnInstallMenuCallWndHook;
begin
if MenuCallWndHook <> 0 then
UnHookWindowsHookEx(MenuCallWndHook);
MenuCallWndHook := 0;
ActiveHookMenu := nil;
PopupWndList := nil;
end;
{ TPopupMenu }
procedure TPopupMenu.Popup(X, Y: Integer);
begin
if not FTrackMenu then
inherited
else
try
InstallMenuCallWndHook(Self);
inherited;
finally
UnInstallMenuCallWndHook;
end;
end;
{ TTntPopupMenu }
{$IFDEF TNT}
procedure TTntPopupMenu.Popup(X, Y: Integer);
begin
if not FTrackMenu then
inherited
else
try
InstallMenuCallWndHook(Self);
inherited;
finally
UnInstallMenuCallWndHook;
end;
end;
{$ENDIF}
function GetMenuForm(Menu: TMenu): TCustomForm;
var
LForm: TWinControl;
begin
Result := nil;
if Menu.WindowHandle <> 0 then
begin
LForm := FindControl(Menu.WindowHandle);
if (LForm <> nil) and (LForm is TCustomForm) then
Result := LForm as TCustomForm;
end;
end;
function FormMainMenuIsValid(AForm: TCustomForm): Boolean;
begin
Result := False;
if Assigned(AForm) and Assigned(AForm.Menu) then
begin
{$IFDEF TNT}
if (AForm.Menu is TTntMainMenu) then
Result := TTntMainMenu(AForm.Menu).FTrackMenu
else
{$ENDIF}
if (AForm.Menu is TMainMenu) then
Result := TMainMenu(AForm.Menu).FTrackMenu;
end;
end;
procedure FormMainMenuWndProcMessage(var Msg: TMessage; AForm: TCustomForm);
begin
if not FormMainMenuIsValid(AForm) then
Exit;
case Msg.Msg of
WM_INITMENU:
begin
// MSDN: Sent when a menu is about to become active. It occurs when the user clicks an item on the menu bar or presses a menu key.
// A window receives this message through its WindowProc function
// A WM_INITMENU message is sent only when a menu is first accessed; only one WM_INITMENU message is generated for each access.
// For example, moving the mouse across several menu items while holding down the button does not generate new messages
InstallMenuCallWndHook(AForm.Menu);
end;
WM_MENUSELECT:
begin
// MSDN: If the high-order word of wParam contains 0xFFFF and the lParam parameter contains NULL, the system has closed the menu.
if (Msg.lParam = 0) and (HiWord(Msg.wParam) = $FFFF) then // Menu Closed
begin
UnInstallMenuCallWndHook;
end;
end;
end;
end;
end.
Utilisation:
Goutte TPopupMenu
et/ou TMainMenu
sur le formulaire. dans le uses
include AppTrackMenus
aprèsMenus
. Créer des éléments de menu et pour chaque élément de menu que vous voulez ne pas être fermé lorsque cliqué, définir Tag
=666 (pour cet exemple). Vous pouvez assigner chacun de ces éléments un OnClick
gestionnaire d'événements CheckNoCloseClick
.
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
Menus, AppTrackMenus;
TForm1 = class(TForm)
...
procedure CheckNoCloseClick(Sender: TObject);
protected
procedure WndProc(var Msg: TMessage); override; // for TMainMenu
private
procedure TrackMenuNotifyHandler(Sender: TMenu; Item: TMenuItem; var CanClose: Boolean);
end;
implementation
procedure TForm1.FormCreate(Sender: TObject);
begin
PopupMenu1.TrackMenu := True;
PopupMenu1.OnTrackMenuNotify := TrackMenuNotifyHandler;
MainMenu1.TrackMenu := True;
MainMenu1.OnTrackMenuNotify := TrackMenuNotifyHandler;
end;
procedure TForm1.CheckNoCloseClick(Sender: TObject);
begin
TMenuItem(Sender).Checked := not TMenuItem(Sender).Checked;
end;
procedure TForm1.TrackMenuNotifyHandler(Sender: TMenu; Item: TMenuItem; var CanClose: Boolean);
begin
Caption := Sender.ClassName + '-' + Item.ClassName + '-' + Item.Name;
CanClose := Item.Tag <> 666;
end;
procedure TForm1.WndProc(var Msg: TMessage); // for TMainMenu
begin
FormMainMenuWndProcMessage(Msg, Self);
inherited;
end;
TMainMenu
Interposer pourrait être amélioré en sous-classant sa forme à l'exécution, sur demande (en mettant un nouveau Form.WindowProc
) sans qu'il soit nécessaire de remplacer WndProc
pour chaque formulaire. Mais, il n'y a habituellement qu'un seul menu principal par application. Peut-être la prochaine version... :)
testé dans XP/Vista / Win7
à mon avis, Bien que cela soit acceptable, vous devriez probablement envisager d'écrire votre propre système de menu, en utilisant des panneaux ou des formulaires, ou un ensemble complet de contrôle/composant personnalisé, et de ne pas utiliser le TPopupMenu standard ou TMainMenu du tout si vous voulez faire cela.
si vous voulez du code source de démarrage, je commencerais par quelque chose comme les Sources Toolbar2000+SpTBX. Je suis assez sûr que vous seriez en mesure d'accomplir ceci en utilisant ceux, mais pas avec TMainMenu et TPopupMenu, parce que ils enveloppent certains Win32 builtins qui auront des comportements (y compris la fermeture lorsque vous ne voulez pas) qu'il n'est pas possible de modifier.
vous pourriez aussi être en mesure de faire quelque chose comme ça avec les composants de la barre D'outils Developer Express.
j'ai eu le même besoin récemment et j'ai trouvé que TMS Smooth controls a des menus "arraché" qui ont une fonction similaire mais qui exigent (comme indiqué par le nom) que le menu soit, um, arraché! Je n'ai jamais regardé dans, parce que mon besoin n'était pas assez forte pour justifier le temps, de l'argent, ou l'utilisation d'un produit tiers. Mais j'ai utilisé d'autres trucs qui étaient de première qualité.
Je ne suis pas sûr que leurs menus arrachés répondraient à vos besoins, mais vous pourriez vouloir regarder dedans.