2015-11-06

[PowerShell] フォームにメニューバーを付ける

PowerShellで作成したフォームにメニューバーを付ける方法をご紹介します。

メニューバーは大多数のソフトウェアで使用されています。
メモ帳でも、フォルダでも、Google Chromeでも、Excelでもです。

メニューバーを付けることによって、フォーム内に入りきれない情報や機能を盛り込むことができるようになります。

自分で作ったフォームにもメニューバーを設置して、さらに使い勝手を良くしていきましょう!!


<今回の完成品>


画像の中で「項目1」「項目2」となっている部分がメニューバーです。
それぞれの項目内には、さらに小分類を設置することができます。

それではスクリプトを記述します。


---------ここから-------------------------------------------------------------------------------------
# メニューバー

# アセンブリのロード
Add-Type -AssemblyName System.Windows.Forms

# フォーム
$form = New-Object System.Windows.Forms.Form
$form.Size = "200,200"
$form.StartPosition = "CenterScreen"
$form.Text = "メニューバー"
$form.TopLevel = $True
$form.MaximizeBox = $False
$form.MinimizeBox = $False

# メニューバー
$Menu = New-Object System.Windows.Forms.MenuStrip

# 項目1
$Item1 = New-Object System.Windows.Forms.ToolStripMenuItem
$Item1.Text = "項目1"

    # 項目1 - 子項目1      
    $SubMenu1 = New-Object System.Windows.Forms.ToolStripMenuItem
    $SubMenu1.Text = "メッセージ その1 を表示"
    $SubMenu1.ShortcutKeys = [System.Windows.Forms.Keys]::Control, [System.Windows.Forms.Keys]::L # ショートカットキーCtrl+L
    $Click01 = {
        [System.Windows.Forms.MessageBox]::Show("メッセージその1が選択されました", "成功")
    }
    $SubMenu1.Add_Click($Click01)

    # 子項目1の下にセパレーター(区切り線)を入れる
    $Sepa = New-Object System.Windows.Forms.ToolStripSeparator

    # 項目1 - 子項目2
    $SubMenu2 = New-Object System.Windows.Forms.ToolStripMenuItem
    $SubMenu2.Text = "閉じる"
    $SubMenu2.ShortcutKeys = [System.Windows.Forms.Keys]::Control, [System.Windows.Forms.Keys]::F12 # ショートカットキーCtrl+F12
    $Click02 = {
        $form.Close()
    }
    $SubMenu2.Add_Click($Click02)

    # 項目1に子項目を全て入れる
    $Item1.DropDownItems.AddRange(@($SubMenu1,$Sepa,$SubMenu2))

# 項目2
$Item2 = New-Object System.Windows.Forms.ToolStripMenuItem
$Item2.Text = "項目2"

    # 項目2 - 子項目1      
    $SubMenu3 = New-Object System.Windows.Forms.ToolStripMenuItem
    $SubMenu3.Text = "メッセージ その2 を表示"
    $SubMenu3.ShortcutKeys = [System.Windows.Forms.Keys]::Control, [System.Windows.Forms.Keys]::G # ショートカットキーCtrl+G
    $Click03 = {
        [System.Windows.Forms.MessageBox]::Show("メッセージその2が選択されました", "成功")
    }
    $SubMenu3.Add_Click($Click03)

    # 項目2 - 子項目2
    $SubMenu4 = New-Object System.Windows.Forms.ToolStripMenuItem
    $SubMenu4.Text = "メッセージ その3 を表示"
    $SubMenu4.ShortcutKeys = [System.Windows.Forms.Keys]::Control, [System.Windows.Forms.Keys]::T # ショートカットキーCtrl+T
    $Click04 = {
        [System.Windows.Forms.MessageBox]::Show("メッセージその3が選択されました", "成功")
    }
    $SubMenu4.Add_Click($Click04)

    # 項目2に子項目を全て入れる
    $Item2.DropDownItems.AddRange(@($SubMenu3,$SubMenu4))

# メニューバーに項目1・項目2を入れる
$Menu.Items.AddRange(@($Item1,$Item2))

#閉じるボタン
$Button = New-Object System.Windows.Forms.Button
$Button.Location = "50,80"
$Button.size = "80,30"
$Button.text  = "閉じる"
$Button.FlatStyle = "popup"
$Button.DialogResult = [System.Windows.Forms.DialogResult]::Cancel

$form.Controls.AddRange(@($Menu,$Button))

$form.Showdialog()
---------ここまで-------------------------------------------------------------------------------------

上記内容をコピーし、PowerShell ISEに貼り付けて、実行してみてください。
完成品と同じものが表示されるはずです。


それでは解説をしていきます。
また過去の記事で解説した部分については割愛致します。


内容をご確認いただきたい場合は【ユーザーフォーム - 基礎編 -】をご覧ください。


*****解説*****************************************************************************

# メニューバー
$Menu = New-Object System.Windows.Forms.MenuStrip

ここではメニューバーを使用するための宣言を行っています。
この段階ではまだ空の状態であり、フォーム上にも設置されていません。


# 項目1
$Item1 = New-Object System.Windows.Forms.ToolStripMenuItem
$Item1.Text = "項目1"

次に、メニューバーの中にいれるアイテム(項目)を作成しています。
Textプロパティに指定した文字列がメニューバー上に表示されることになります。
よく見かけるのは「ファイル」「編集」「表示」などですね。


# 項目1 - 子項目1      
$SubMenu1 = New-Object System.Windows.Forms.ToolStripMenuItem
$SubMenu1.Text = "メッセージ その1 を表示"
$SubMenu1.ShortcutKeys = [System.Windows.Forms.Keys]::Control, [System.Windows.Forms.Keys]::L # ショートカットキーCtrl+L
$Click01 = {
[System.Windows.Forms.MessageBox]::Show("メッセージその1が選択されました", "成功")
}
$SubMenu1.Add_Click($Click01)

ここでは、先ほど作成した項目1の中に入れる項目(子項目と呼ぶことにします)を作成しています。
子項目1の機能としては、「選択されるとメッセージボックスを表示させる」というものです。
また便利な機能として、ショートカットキーを設定しています。
ShortcutKeysプロパティを設定することで、任意のキーを指定することができます。
なお、ShortcutKeysプロパティにキーを設定すると、自動的に子項目1の文字列の右側にそのキーが表示されるようになります。


# 子項目1の下にセパレーター(区切り線)を入れる
$Sepa = New-Object System.Windows.Forms.ToolStripSeparator

ここでは、子項目1と子項目2の間に、セパレーター(区切り線)を挿入しています。
これはあってもなくても問題ありません。


# 項目1に子項目を全て入れる
$Item1.DropDownItems.AddRange(@($SubMenu1,$Sepa,$SubMenu2))

項目1の最後には、項目1の中に設置する子項目を入れるよう記述します。


# メニューバーに項目1・項目2を入れる
$Menu.Items.AddRange(@($Item1,$Item2))

更に、作成した項目をメニューバーの中に入れるよう記述します。


$form.Controls.AddRange(@($Menu,$Button))

そして最後に、フォームにメニューバーを入れるよう記述します。

つまり順番としては、
子項目を項目に入れる
  ↓
項目をメニューバーに入れる
  ↓
メニューバーをフォームに入れる という流れになります。

*******************************************************************************************************

メニューバーを設置し、内容を充実させることによって、そのフォームはますます機能が増え、使い勝手が向上します。

どんな機能を持たせるかは、作成者次第ですので、いろいろな使い方を検討してみてください。

=======================================================================
本投稿に関する疑問や質問には可能な限りお答えさせていただきます。
お気軽にコメントやメールをお送りください。
(リクエストも歓迎します)
メール:tkk-powershell@gmail.com
また、間違いのご指摘・アドバイス等も歓迎いたします。
=======================================================================
Google+、Twitterで更新情報をお届けしています!
ぜひフォローをお願い致します!           
=======================================================================
スポンサーリンク


5 件のコメント:

  1. 記事、拝見致しました。

    突然ですが、1点ご教示頂けますでしょうか。

    子項目のclickイベントで、他の記事にあったフォルダー選択を呼び出し、
    その戻り値を、適当な変数に格納しました。
    その変数値を、ラベルやテキストボックスに、その場で代入すれば
    期待したとおりの値が確認できます。

    問題は、clickイベントで取得した変数を、フォーム上の
    他の処理で参照できない現象に遭遇しております。

    ご教授頂けますと幸いです。

    ~~~~中略~~~~~

    ## UI:フォルダー選択
    function UI-FolderSelect ([string]${DiagMsg})
    {
    # COMオブジェクトの読み込み
    ${shell} = New-Object -com shell.Application

      ~~記事で掲載されている内容~~

    # パス情報を戻す
    return ${folderPath}.Self.Path

    }
    ~~~~中略~~~~~

    ## 項目1 - 子項目3
    ${SubMenu3} = New-Object System.Windows.Forms.ToolStripMenuItem
    ${SubMenu3}.Text = "バックアップ保存先"
    ${Click03} = {
    ${oBKPath} = UI-FolderSelect -DiagMsg "バックアップ保存先のフォルダーを選択してください。"
    }
    ${SubMenu3}.Add_Click(${Click03})

    ~~~~中略~~~~~


    # ボタンA
    $ButtonA = New-Object System.Windows.Forms.Button
    $ButtonA.Location = "50,20"
    $ButtonA.size = "80,30"
    $ButtonA.text = "ボタンA"
    $ButtonA.FlatStyle = "popup"
    $form.Controls.Add($ButtonA)

    # ボタンAのクリックイベント
    $ButtonA.Add_Click({[System.Windows.Forms.MessageBox]::Show("$(${oBKPath})", "結果")})

    ~~以下略~~



    以上、よろしくお願い申し上げます。

    返信削除
    返信
    1. コメントありがとうございます。

      スクリプトを拝見させていただきました。
      結論から申し上げますと、$SubMenu3のクリックイベント内容を下記のように変更すれば期待通りの結果が得られると思われます。

      変更前
      ${oBKPath} = UI-FolderSelect -DiagMsg "バックアップ保存先の~(略)"

      変更後
      ${script:oBKPath} = UI-FolderSelect -DiagMsg "バックアップ保存先の~(略)"

      変数には「スコープ」というものがあります。
      スコープとは簡単にいうと「有効範囲」です。

      PowerShellでは変数を作成すると、自動的にスコープが「ローカル」に設定されます。
      ローカルスコープは"そのブロック内のみ"で参照できるものと考えてください。

      今回のスクリプトで言いますと、変数$oBKPathは$SubMenu3のクリックイベントというブロック内で作成されたものであるため、そのブロック内でのみ有効であり、そのブロックを出てしまうと、参照できません。

      そこで変数$oBKPathの有効範囲(スコープ)を「script」に設定するようにしています。
      「script」に設定すれば、そのスクリプト内のどこからでも参照できるようになります。
      ※スコープは他にも「global」や「private」があります。

      以上、ご参考ください。

      削除
    2. ご教示ありがとうございました。

      ご指摘どおり、スコープ設定が不足していたようです。

      ブロックというのは、{と}の囲まれた範囲を意味されますか?
      今回のようなエラーケースは初めてでして・・・。ついでで申し訳ありませんが、
      よろしくお願い致します。

      削除
    3. 返信ありがとうございます。

      仰る通り、今回は{ から }までの部分をひとつの固まりとして捉える意味で「ブロック」という表現を使用致しました。(この呼称が正確かどうかは不明です)

      削除
    4. ありがとうございました。
      内容、承知しました。

      削除

疑問・質問・リクエスト お気軽にどうぞ (^O^)/