回避策はありますが、非常に汚れています。クラッカー クラスを使用して、 TPopupMenu.Itemsメニュー項目プロパティのFHandleプライベート メンバーへのアクセスを取得します。
クラッカー クラスでは、目的のプライベート メンバーまでターゲット クラスのプライベート ストレージ レイアウトを再現し、型キャストを使用して、その型をコンテキスト内のターゲット型のインスタンスに「オーバーレイ」します。ターゲットの内部ストレージにアクセスします。
この場合、ターゲット オブジェクトはTMenuItemのインスタンスであるTPopupMenuのItemsプロパティです。 TMenuItemはTComponentから派生するため、TMenuItemのFHandleへのアクセスを提供するクラッカー クラスは次のとおりです。
type
// Here be dragons...
TMenuItemCracker = class(TComponent)
private
FCaption: string;
FChecked: Boolean;
FEnabled: Boolean;
FDefault: Boolean;
FAutoHotkeys: TMenuItemAutoFlag;
FAutoLineReduction: TMenuItemAutoFlag;
FRadioItem: Boolean;
FVisible: Boolean;
FGroupIndex: Byte;
FImageIndex: TImageIndex;
FActionLink: TMenuActionLink;
FBreak: TMenuBreak;
FBitmap: TBitmap;
FCommand: Word;
FHelpContext: THelpContext;
FHint: string;
FItems: TList;
FShortCut: TShortCut;
FParent: TMenuItem;
FMerged: TMenuItem;
FMergedWith: TMenuItem;
FMenu: TMenu;
FStreamedRebuild: Boolean;
FImageChangeLink: TChangeLink;
FSubMenuImages: TCustomImageList;
FOnChange: TMenuChangeEvent;
FOnClick: TNotifyEvent;
FOnDrawItem: TMenuDrawItemEvent;
FOnAdvancedDrawItem: TAdvancedMenuDrawItemEvent;
FOnMeasureItem: TMenuMeasureItemEvent;
FAutoCheck: Boolean;
FHandle: TMenuHandle;
end;
注:この手法はターゲット クラスの内部ストレージ レイアウトの正確な再現に依存しているため、異なる Delphi バージョン間での内部レイアウトの変更に対応するために、クラッカー宣言に$IFDEFバリエーションを含める必要がある場合があります。上記の宣言はDelphi XE4 では正しいので、他の Delphi バージョンとの正確性についてTMenuItemソースと照合する必要があります。
そのクラッカー クラスを使用して、ユーティリティ プロシージャを提供して、これが提供するアクセスを使用して実行する厄介なトリックをまとめることができます。この場合、通常どおりメニュー項目をクリアできますが、クラッカー キャストを使用して自分自身でDestroyMenu()を呼び出してFHandleメンバー変数を 0 で上書きすることもできます。これは、FHandle メンバー変数が無効になり、 TPopupMenuに強制的にメニューを再作成させるために 0 にする必要があるためです。次に必要なとき:
procedure ResetPopupMenu(const aMenu: TPopupMenu);
begin
aMenu.Items.Clear;
// Here be dragons...
DestroyMenu(aMenu.Items.Handle);
TMenuItemCracker(aMenu.Items).FHandle := 0;
end;
サンプル コードでは、Button2ClickハンドラーのPopupMenu1.Items.Clearへの呼び出しをResetPopupMenu(PopupMenu1)への呼び出しに置き換えるだけです。
これが極端に危険なのは言うまでもありません。クラスのプライベート ストレージ内をハッキングするというまったくの狂気は別として、この特定のケースでは、たとえば、マージされたメニューのマージを解除することについては考慮されていません。
しかし、回避策があるかどうかを尋ねましたが、ここに少なくとも 1 つの回避策があります。:)
単純にTPopupMenuを破棄して再作成するよりも、これを多かれ少なかれ実用的または望ましいと考えるかどうかは、あなた次第です。クラスクラッキングは、他の方法では解決できないジャムから抜け出すのに役立つテクニックですが、間違いなく「最後の手段」と見なす必要があります。