1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

■ PowerShellでメモ帳開発 ~スクリプトでも頑張るGUI開発~

Last updated at Posted at 2025-06-12

PowerShell_banner.png


こんにちは :star2:
好奇心で身を滅ぼすタイプ 零壱(ゼロイチ)テクトです。

VBSから乗り換えのため、PowerShellを弄っていますが
MsgboxすらGUI系の命令はなく、WindowsシステムやVBオブジェクト等
間接的に呼び出してGUIに触れる必要があると知りました。

であれば、MsgboxだけでなくGUI全体に触れてみようと考えた次第です。
そうなると、「PowerShell製のメモ帳」開発は誰もが思いつくと思います。

ですが、WEBやQiitaで探しても、見つからないか
リンクが消えていたので、勉強がてら作ったので公開します。

1.概要/仕様

・メモ帳の基本機能を踏襲
・コードを減らすため自分が使わない機能は削除
・少なくとも自分は業務に使うイメージで作成

2.コード

notepad.ps1
############################################
# PowerShell メモ帳
############################################

# GUI用アセンブリ読込
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName Microsoft.VisualBasic

# ファイルパス変数
$currentFilePath = ""

# アプリ名定義
$appName = "PowerShell メモ帳"

# 検索用:グローバル変数初期化
$global:searchText = ""
$global:searchIndex = 0

# タイトル更新関数
function Update-Title {
    if ([string]::IsNullOrWhiteSpace($currentFilePath)) {
        $form.Text = $appName
    } else {
        $fileName = [System.IO.Path]::GetFileName($currentFilePath)
        $form.Text = "$fileName - " + $appName
    }
}

# フォーム作成
$form = New-Object System.Windows.Forms.Form
$form.Text = $appName
$form.Size = New-Object System.Drawing.Size(800,600)
$form.StartPosition = "CenterScreen"

# テキストボックス(メイン)
$textBox = New-Object System.Windows.Forms.TextBox
$textBox.Multiline = $true
$textBox.Dock = "Fill"
$textBox.ScrollBars = "Both"
$textBox.Font = New-Object System.Drawing.Font("Consolas", 11)
$textBox.AcceptsTab = $true
$form.Controls.Add($textBox) | Out-Null

# メニューバー作成
$menu = New-Object System.Windows.Forms.MenuStrip
$form.MainMenuStrip = $menu
$form.Controls.Add($menu) | Out-Null

# メニュー:ファイル
$fileMenu = New-Object System.Windows.Forms.ToolStripMenuItem "ファイル"
$menu.Items.Add($fileMenu) | Out-Null

# 新規作成:Ctrl+N
$newItem = New-Object System.Windows.Forms.ToolStripMenuItem "新規作成"
$newItem.ShortcutKeys = "Control, N"
$newItem.Add_Click({ 
    $textBox.Clear()
    $currentFilePath = $null
    Update-Title 
})
$fileMenu.DropDownItems.Add($newItem) | Out-Null

# 開く:Ctrl+O
$openItem = New-Object System.Windows.Forms.ToolStripMenuItem "開く"
$openItem.ShortcutKeys = "Control, O"
$openItem.Add_Click({
    $openDialog = New-Object System.Windows.Forms.OpenFileDialog
    $openDialog.Filter = "Text Files (*.txt)|*.txt|All Files (*.*)|*.*"
    if ($openDialog.ShowDialog() -eq "OK") {
        $currentFilePath = $openDialog.FileName
        $textBox.Text = Get-Content $currentFilePath -Raw -Encoding UTF8
        Update-Title
    }
}) | Out-Null
$fileMenu.DropDownItems.Add($openItem) | Out-Null

# 保存(上書き):Ctrl+S
$saveItem = New-Object System.Windows.Forms.ToolStripMenuItem "保存"
$saveItem.ShortcutKeys = "Control, S"
$saveItem.Add_Click({
    $saveDialog = New-Object System.Windows.Forms.SaveFileDialog
    $saveDialog.Filter = "Text Files (*.txt)|*.txt|All Files (*.*)|*.*"
    if ($saveDialog.ShowDialog() -eq "OK") {
        $currentFilePath = $saveDialog.FileName
        [System.IO.File]::WriteAllText($currentFilePath, $textBox.Text)
        Update-Title
    }
})
$fileMenu.DropDownItems.Add($saveItem) | Out-Null

# 名前を付けて保存:Ctrl+Shift+S
$saveAsItem = New-Object System.Windows.Forms.ToolStripMenuItem "名前を付けて保存"
$saveAsItem.ShortcutKeys = "Control, Shift, S"
$saveAsItem.Add_Click({
    $saveDialog = New-Object System.Windows.Forms.SaveFileDialog
    $saveDialog.Filter = "Text Files (*.txt)|*.txt|All Files (*.*)|*.*"
    if ($saveDialog.ShowDialog() -eq "OK") {
        $currentFilePath = $saveDialog.FileName
        [System.IO.File]::WriteAllText($currentFilePath, $textBox.Text)
        Update-Title
    }
})
$fileMenu.DropDownItems.Add($saveAsItem) | Out-Null

# 区切り
$fileMenu.DropDownItems.Add((New-Object System.Windows.Forms.ToolStripSeparator)) | Out-Null

# メニュー:終了
$exitItem = New-Object System.Windows.Forms.ToolStripMenuItem "終了"
$exitItem.Add_Click({ $form.Close() })
$fileMenu.DropDownItems.Add($exitItem) | Out-Null

# メニュー:編集
$editMenu = New-Object System.Windows.Forms.ToolStripMenuItem "編集"
$menu.Items.Add($editMenu) | Out-Null

# 元に戻す:Ctrl+Z
$undoItem = New-Object System.Windows.Forms.ToolStripMenuItem "元に戻す"
$undoItem.ShortcutKeys = "Control, Z"
$undoItem.Add_Click({ $textBox.Undo() })
$editMenu.DropDownItems.Add($undoItem) | Out-Null

# 区切り
$editMenu.DropDownItems.Add((New-Object System.Windows.Forms.ToolStripSeparator)) | Out-Null

# 切り取り:Ctrl+X
$cutItem = New-Object System.Windows.Forms.ToolStripMenuItem "切り取り"
$cutItem.ShortcutKeys = "Control, X"
$cutItem.Add_Click({ $textBox.Cut() })
$editMenu.DropDownItems.Add($cutItem) | Out-Null

# コピー:Ctrl+C
$copyItem = New-Object System.Windows.Forms.ToolStripMenuItem "コピー"
$copyItem.ShortcutKeys = "Control, C"
$copyItem.Add_Click({ $textBox.Copy() })
$editMenu.DropDownItems.Add($copyItem) | Out-Null

# 貼り付け:Ctrl+V
$pasteItem = New-Object System.Windows.Forms.ToolStripMenuItem "貼り付け"
$pasteItem.ShortcutKeys = "Control, V"
$pasteItem.Add_Click({ $textBox.Paste() })
$editMenu.DropDownItems.Add($pasteItem) | Out-Null

# 削除:Delete
$deleteItem = New-Object System.Windows.Forms.ToolStripMenuItem "削除"
$deleteItem.ShortcutKeys = [System.Windows.Forms.Keys]::Delete
$deleteItem.Add_Click({
    $start = $textBox.SelectionStart
    $length = $textBox.SelectionLength
    $textBox.Text = $textBox.Text.Remove($start, $length)
})
$editMenu.DropDownItems.Add($deleteItem) | Out-Null

# 区切り
$editMenu.DropDownItems.Add((New-Object System.Windows.Forms.ToolStripSeparator)) | Out-Null

# 全て選択:Ctrl+A
$selectAllItem = New-Object System.Windows.Forms.ToolStripMenuItem "すべて選択"
$selectAllItem.ShortcutKeys = "Control, A"
$selectAllItem.Add_Click({ $textBox.SelectAll() })
$editMenu.DropDownItems.Add($selectAllItem) | Out-Null

# 日付と時刻:F5
$timeDateItem = New-Object System.Windows.Forms.ToolStripMenuItem "日付と時刻"
$timeDateItem.ShortcutKeys = "F5"
$timeDateItem.Add_Click({
    $dateTime = Get-Date -Format "yyyy/MM/dd HH:mm:ss"
    $textBox.SelectedText = $dateTime
})
$editMenu.DropDownItems.Add($timeDateItem) | Out-Null

# 区切り
$editMenu.DropDownItems.Add((New-Object System.Windows.Forms.ToolStripSeparator)) | Out-Null

# 検索:Ctrl+F
$findItem = New-Object System.Windows.Forms.ToolStripMenuItem "検索"
$findItem.ShortcutKeys = "Control, F"
$findItem.Add_Click({
    $input = [Microsoft.VisualBasic.Interaction]::InputBox("検索する文字列を入力してください", "検索")
    if ($input) {
        $global:searchText = $input
        $global:searchIndex = 0  # 先頭から検索開始

        $index = $textBox.Text.IndexOf($global:searchText, $global:searchIndex)
        if ($index -ge 0) {
            $textBox.SelectionStart = $index
            $textBox.SelectionLength = $global:searchText.Length
            $textBox.ScrollToCaret()
            $global:searchIndex = $index + $global:searchText.Length
        } else {
            [System.Windows.Forms.MessageBox]::Show("文字列が見つかりません。", "検索")
            $global:searchText = ""
            $global:searchIndex = 0
        }
    }
})
$editMenu.DropDownItems.Add($findItem) | Out-Null

# 次を検索:F3
$findNextItem = New-Object System.Windows.Forms.ToolStripMenuItem "次を検索"
$findNextItem.ShortcutKeys = [System.Windows.Forms.Keys]::F3
$findNextItem.Add_Click({
    if ([string]::IsNullOrEmpty($global:searchText)) {
        [System.Windows.Forms.MessageBox]::Show("先に検索してください。", "次を検索")
        return
    }
    $index = $textBox.Text.IndexOf($global:searchText, $global:searchIndex)
    if ($index -ge 0) {
        $textBox.SelectionStart = $index
        $textBox.SelectionLength = $global:searchText.Length
        $textBox.ScrollToCaret()
        $global:searchIndex = $index + $global:searchText.Length
    } else {
        [System.Windows.Forms.MessageBox]::Show("これ以上見つかりません。", "次を検索")
    }
})
$editMenu.DropDownItems.Add($findNextItem) | Out-Null

# 置換:Ctrl+H
$replaceItem = New-Object System.Windows.Forms.ToolStripMenuItem "置換"
$replaceItem.ShortcutKeys = "Control, H"
$replaceItem.Add_Click({
    $find = [Microsoft.VisualBasic.Interaction]::InputBox("置換したい文字列を入力してください", "置換(検索)")
    if ($find) {
        $replace = [Microsoft.VisualBasic.Interaction]::InputBox("新しい文字列を入力してください", "置換(置換後)")
        if ($replace -ne $null) {
            $textBox.Text = $textBox.Text.Replace($find, $replace)
        }
    }
})
$editMenu.DropDownItems.Add($replaceItem) | Out-Null


# アプリ実行
$form.Add_Shown({ $form.Activate() })
$form.ShowDialog() | Out-Null

お好きにコードをお使いください。

3.備考

✅ 改良案1:時間経過で自動保存する機能
      →これは便利機能ですがコードが長くなりそうだったので割愛

✅ 改良案2:フォントサイズや文字色は固定なので変更できるように
      →僕の現在の用途には不要な機能だったので割愛しました
      →文字コードも同じです。

✅ タブ化したり、文字数や行数表示したり、弄り方は色々あると思います。

・「Out-Null」は「.Add」を実行する時にISEのログに返り値が表示されるため
 消す為に入れてあります。邪魔であれば削除しても動作に問題ないです。

・置換機能として、1つのダイアログに入力を2つ持たせる画面は
 コードが長くなりそうだったのでやめました。

・友人知人からプログラムを勉強したいだけど何をしたら良いか
 と聞かれる事があるのですが、その時まず提案するのが「メモ帳」アプリ作りです。

・WEBアプリやサイトを作るのでなければ、メモ帳開発はとても良い教材だと思います。


  それでは
       どこかの誰かの何かの足しになれば幸いです。
                        01000010 01011001 01000101

4.参考

@Tadataka_Takahashi様:[備忘録] PowerShellで作る「リアルタイム システム監視ダッシュボード」- PropertyGridの活用

@K014C様:PowerShellでフォームの作成とファイルパスの取得

@tatsuki1112様:PowerShellでGUIアプリを作って、勤怠を少しだけ効率化した話

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?