MainMenu の全てのアイテムを PopupMenu に動的に追加

解決


てる  2012-03-25 09:11:07  No: 41818

MainMenu にある全てのアイテムを Popup でもアクセス出来るようにしたいのですが
Assign は出来ないようで再帰を使ってみたのですがうまくいきません

OnPopup で全てクリアしてその度に調べてメニューを追加したいのですが
「同じメニューを二度追加した」とエラーが出ます
再帰する方の手続きではどのように考えればよいのでしょうか


  2012-03-25 20:51:47  No: 41819

TmenuItemを動的生成して単純にぶらさげていくだけかと。
Captionとかショートカットとか、OnClickイベントとかは元のやつと
まったく同じものを指定してやれば動くのでは?

https://www.petitmonte.com/bbs/answers?question_id=5949

イメージはこんな感じ。


Mr.XRAY  2012-03-25 22:30:22  No: 41820

こんにちは,Mr.XRAYです.

>「同じメニューを二度追加した」とエラーが出ます

1つのメニューアイテムを、同時に2つのメニューに結び付ける事は出来ないようです.

>MainMenu の全てのアイテムを PopupMenu に動的に追加

疑問があるのですが,

(1) アプリ実行開始時は,PopupMenuは独自のメニュー
(2) 実行中の,ある時期に最初のPopupMenuは消去
    MainMenuのItemを,サブItemも含めて全て,1つのPopUpMenuに追加する
    
ということなのでしょうか?  
最初からではなく?
全てのアイテムですか.
すると,この後,このPopupMenuはそのままなのでしようか?
う〜む.どういう仕様のアプリなんだろう.

最初からであれば,TActionManagerの使用も考えられそうな気もしますが...
古いDelphiにはないのかな.


てる  2012-03-26 02:10:12  No: 41821

>(1) アプリ実行開始時は,PopupMenuは独自のメニュー

いえ、最初から最後までメインメニューをポップアップさせるだけのモノです

>(2) 実行中の,ある時期に最初のPopupMenuは消去
>   MainMenuのItemを,サブItemも含めて全て,1つのPopUpMenuに追加する

その通りです

メインメニューはいろんなところで動的にサブメニューを
追加している部分がありますのでポップアップさせる時点で判断しないと
いけないと思いまして
また、設定で普段使わない(メイン)メニューは非表示に出来るように
なっていますので新機能が追加された時(例えばそれが
「ツール」傘下のサブメニュー「新機能」の場合)
ユーザーはその機能を試すためにわざわざ「ツール」メニューを
表示する設定に変えなければいけないので今回のような質問になりました

秀丸で「その他」メニューに「コマンド一覧」というものがあるので
つけてみようと思った次第です
今やってみましたエラーは出なくなりましたがメニューが別れてくれません
メインメニューにはテンプレートから「ファイル」「ヘルプ」の二つの
親メニューを追加しています
そして
PopupMenu にメニュー「PopUpListMenu」を作ってその下にメインメニューを
並べようとしています
procedure TForm1.Button1Click(Sender: TObject);
  procedure AddPopUp(Item:TMenuItem;SendMenu:TMenuItem);
  var
    i:integer;
    NewMenu:TMenuItem;
  begin
    for i:=0 to Item.Count-1 do
    begin
      NewMenu:=TMenuItem.Create(Item);
      NewMenu.Caption:=Item[i].Caption;
      NewMenu.OnClick:=Item[i].OnClick;
      SendMenu.Add(NewMenu);
      if Item[i].Count>0 then AddPopUp(Item[i],SendMenu);
    end;
  end;
var
  i:integer;
begin
  with PopUpListMenu do
  begin
    for i:=Count-1 downto 0 do
      Items[i].Free;
  end;
  with MainMenu do
  begin
    for i:=0 to Items.Count-1 do
      AddPopUp(Items[i],PopUpListMenu);
  end;
  PopupMenu.Popup(0,0);
end;


Mr.XRAY  2012-03-26 02:34:56  No: 41822

こんにちは,Mr.XRAYです.

外しているかも知れませんが,上の文章から判断すると,おそらくTActionManagerとその
類似コンポーネントを使用した方がいいと思われます.
環境の記載がないので判断はできませんが,最近のDelphiであればあります.

TActionManagerコンポで,あらかじめ,そのアプリで使われるかも知れない項目を作成しておきます.
TMainMenuやTPopupのメニュー項目は,そこから選択して項目を作成できます.
ボタンクリック,例えば[コピー]というボタンがあったとします.これもいちいちイベント
ハンドラを書かなくても,TActionManagerの項目から選択できます.アクションといいます.
もちろん,実行時に選択するようにしてもいいでしょう.

環境の記載は,質問の際に書いた方がいいですね.
実を言うと,OSのバージョン(最近はMacも含まれるようですが)やDelphiのバージョン
によって,コンパイルできなかったり,できても正常に動作しないことがあるんです.
ウソではありません.ホントの話です(笑)


Mr.XRAY  2012-03-26 02:53:38  No: 41823

TActionList,TActionManagerには,あらかじめ,[コピー][貼り付け]等の機能が組み込まれています.
これらの機能を使用すると,一行もコードを書かないでワードパッドのような
アプリケーションを作成することも可能です.

Youtubeに外国の方が作成過程を動画でUPしていたのですが,
今確認したら,その方のアカウントが削除されているため,見られませんでした.

http://www.youtube.com/watch?gl=JP&feature=related&hl=ja&v=iai_HNYARD4


てる  2012-03-26 03:58:09  No: 41824

ありがとうございます、何度もすみません
コンパイラはDelphi2009です
TActionListはD5のころからよく使っています
最近はTActionManagerも使うこともありますがどうにも使いづらいので
動的に生成しているメニューが多い場合はTActionの紐付けまでしか
していません(それもメニューアイコンやOnActionUpdateを使う場合に
限ってですが)
とりあえず取り出しは出来ていますので晩ご飯を食べてからもう少し頭をひねってみます


Mr.XRAY  2012-03-26 05:12:29  No: 41825

>TActionListはD5のころからよく使っています
>最近はTActionManagerも使うこともありますがどうにも使いづらいので

あらっ,それは大変失礼いたしまた.
えらい講釈をぶってしまいました.単なる赤っ恥でしたね.
ということは,全く役に立ちませんでしたね.


KHE00221  2012-03-26 05:41:08  No: 41826

procedure Add(MenuItem,SendItem: TMenuItem);
var
    I: Integer;
    NewItem: TMenuItem;
begin
    for I:=0 to SendItem.Count - 1 do
    begin
      NewItem := TMenuItem.Create(nil);
      NewItem.Caption := SendItem[I].Caption;
      NewItem.OnClick := SendItem[I].OnClick;
      MenuItem.Add(NewItem);
      if SendItem[I].Count <> 0 then
      begin
        Add(NewItem,SendItem[I]);
      end;
    end;
end;

procedure TForm3.Button1Click(Sender: TObject);
begin
    //まるごとコピー
    Add(PopupMenu1.Items,MainMenu1.Items);
end;


てる  2012-03-26 05:51:42  No: 41827

Ctrl+F7 で一つずつ見ていけば解決しました(^^;
procedure Tt.Button1Click(Sender: TObject);
  procedure AddPopUp(Item:TMenuItem;SendMenu:TMenuItem);
  var
    i:integer;
    NewMenu:TMenuItem;
  begin
    for i:=0 to Item.Count-1 do
    begin
      NewMenu:=TMenuItem.Create(Item);
      NewMenu.Caption:=Item[i].Caption;
      NewMenu.OnClick:=Item[i].OnClick;
      SendMenu.Add(NewMenu);
      if Item[i].Count>0 then AddPopUp(Item[i],SendMenu);
    end;
  end;
var
  i:integer;
  NewMenu:TMenuItem;
begin
  with PopUpListMenu do
  begin
    for i:=Count-1 downto 0 do
      Items[i].Free;
  end;
  with MainMenu do
  begin
    for i:=0 to Items.Count-1 do
    begin
      NewMenu:=TMenuItem.Create(MainMenu);
      NewMenu.Caption:=Items[i].Caption;
      PopUpListMenu.Add(NewMenu);
      AddPopUp(Items[i],NewMenu);
    end;
  end;
  PopupMenu.Popup(0,0);
end;

>あらっ,それは大変失礼いたしまた
いえ、こちらの情報が少なすぎたせいですので
悪いのは私です
「失礼いたしまた」と言わせてしまってごめんなさいです


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加