Powershellで画像ビューワを作る「zipファイル対応]

コンピュータ

以前に作成した画像ビューワを拡張してzipファイルに対応しました。

書籍などをスキャンした画像を閲覧することを想定し、画像が末尾(又は先頭)まで移動した場合、自動的に次のディレクトリやzipファイルを参照するようしました。また、表示モードを「単ページ表示」「見開き表示」「半分表示」(上下分割)の閲覧方法をメニューから選ぶことが出来ます。

F11キーを押すと、デスクトップのサイズにウィンドウサイズを拡大します。フルスクリーンに似ていますが、ウィンドウの枠とメニューを非表示にしウィンドウを目いっぱい広げる処理をしています。デスクトップサイズの取得時にデュアルディスプレイに対応したつもりですので、ディスプレイが横に並んでいるデュアルディスプレイで見開き表示にすると、左右のページが各々ディスプレイに表示されます。
横並びのデュアルディスプレイ以外のマルチディスプレイ環境では正しく表示されないと思われます。

事前準備

アセンブリの読み込みが失敗する場合がありますので、事前に$profileでアセンブリを読み込むよう記述しておきます。

ファイルの場所

$profileの場所は以下になります。
“C:\Users\「ユーザー名」\Documents\WindowsPowerShell\Microsoft.PowerShellISE_profile.ps1”
“C:\Users\「ユーザー名」\Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1”
存在しない場合はPowerShellISEなどで新規作成してください。

追記内容

Add-Type -AssemblyName System.IO.Compression.FileSystem
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing

スクリプト

# 
# 画像ビューワ
# 
# zipファイル対応版

# 
# 書籍
# 

Set-StrictMode -Version Latest

# アセンブリの読み込み
Add-Type -AssemblyName System.IO.Compression.FileSystem
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing

# 書籍オブジェクトのコンテナの種類
enum BookContainerType {
    Directory
    Recursive
    Archive
}

# 書籍クラス
class Book {
    
    # 初期化パス
    $init_path = $null

    # コンテナタイプ
    $container_type = $null # enum BookContainerType

    # 場所(ディレクトリorアーカイブファイルのパス)
    $location = $null

    # 検索済みフラグ
    $searched_flag = $false

    # 画像ファイルのパスの一覧
    $files = $null

    # 画像ファイルの数
    $count = $null

    # 現在のページ位置
    $pos = 0

    # コンストラクタ
    Book($path) {
        if (-not(Test-Path -LiteralPath $path)) { throw ("{0}が無い" -f $path) }

        $this.init_path = $path

        $gi = Get-Item -LiteralPath $path
        if ($gi.PSIsContainer) {
            # ディレクトリ
            $this.container_type = [BookContainerType]::Recursive
            $this.location = $path
        } elseif ($gi.Extension -match "\.(jp(e)?g|png|bmp|gif)$") {
            # 画像ファイル
            $this.container_type = [BookContainerType]::Directory
            $this.location = Split-Path $path -Parent
        } elseif ($gi.Extension -match "\.(zip)$") {
            # アーカイブファイル
            $this.container_type = [BookContainerType]::Archive
            $this.location = $path
        } else {
            throw ("{0}は未対応のファイル形式" -f $path)
        }
    }

    # 画像ファイルを検索
    [void]search() {
        
        if ($this.searched_flag) { return }

        if ($this.container_type -eq [BookContainerType]::Archive) {
            # アーカイブファイル
            $this.search_archive()
        } else {
            # ディレクトリ
            $this.search_directory()
        }

        $this.searched_flag = $true
    }

    # 画像ファイル検索(ディレクトリ)
    [void]search_directory() {
        
        if ($this.container_type -eq [BookContainerType]::Directory) {
            # 同一ディレクトリのみ
            $gci = Get-ChildItem -LiteralPath $this.location -File
        } else {
            # 再帰処理
            $gci = Get-ChildItem -LiteralPath $this.location -File -Recurse
        }

        $this.files = $gci | ? {
            $_.Extension -match "\.(jp(e)?g|png|bmp|gif)$"
        } | Select-Object -Property FullName

        if ($this.files -eq $null) {
            $this.count = 0
        } elseif ($this.files -Is [PSCustomObject]) {
            $this.count = 1
        } else {
            $this.count = ($this.files).Count
        }

        $this.pos = 0
        if ($this.container_type -eq [BookContainerType]::Directory) {
            $this.files | % -Begin {
                $i = 0
            } -Process {
                if ($_.FullName -eq $this.init_path) {
                    $this.pos = $i
                }
                $i = $i + 1
            }
        }
    }

    # 画像ファイル検索(アーカイブファイル)
    [void]search_archive() {
        
        if ($zip = [System.IO.Compression.ZipFile]::OpenRead($this.location)) {
            try {

                $this.files = $zip.Entries | ? {
                    $_.FullName -match "\.(jp(e)?g|png|bmp|gif)$"
                } | sort | Select-Object -Property FullName

                if ($this.files -eq $null) {
                    $this.count = 0
                } elseif ($this.files -Is [PSCustomObject]) {
                    $this.count = 1
                } else {
                    $this.count = ($this.files).Count
                }
                $this.pos = 0
            } finally {
                $zip.Dispose()
            }
        }
    }

    # 最初のページ確認
    [boolean]is_first(){
        $this.search()

        if ($this.count -eq 0) { return $true }

        return ($this.pos -eq 0)
    }

    # 最後のページ確認
    [boolean]is_last(){
        $this.search()

        if ($this.count -eq 0) { return $true }

        return ($this.pos -eq ($this.count-1))
    }

    # 次のページへ移動
    [boolean]next(){
        $this.search()

        if ($this.is_last()) {
            return $false
        }

        $this.pos = $this.pos + 1

        return $true
    }

    # 前のページへ移動
    [boolean]prev(){
        $this.search()

        if ($this.is_first()) {
            return $false
        }

        $this.pos = $this.pos - 1

        return $true
    }

    # 先頭のページへ移動
    [void]first(){
        while ($this.prev()) {}
    }

    # 最後のページへ移動
    [void]last(){
        while ($this.next()) {}
    }

    # 現在のファイル名を取得
    [string]get_filename() {
        $this.search()

        if ($this.count -eq 0) { return "" }
        
        return $this.files[$this.pos].FullName
    }

    # 現在の画像を取得
    [System.Drawing.Image]get_image() {
        $this.search()

        $result = $null

        if ($this.count -eq 0) { return $this.create_noimage() }

        if ($this.container_type -eq [BookContainerType]::Archive) {
            # アーカイブファイル
            $result = $this.get_image_archive()
        } else {
            # ディレクトリ
            $result = $this.get_image_directory()
        }
        return $result
    }

    # 現在の画像を取得(アーカイブファイル)
    [System.Drawing.Image]get_image_archive() {
        
        $file = $this.get_filename()
        $result = $null

        if ($zip = [System.IO.Compression.ZipFile]::OpenRead($this.location)) {
            try {
                
                if ($fs = $zip.GetEntry($file).Open()) {
                    try {
                        $result = [System.Drawing.Image]::FromStream($fs)
                    } finally {
                        $fs.Close()
                    }
                }

            } finally {
                $zip.Dispose()
            }
        }

        return $result
    }

    # 現在の画像を取得(ディレクトリ
    [System.Drawing.Image]get_image_directory() {
        
        $file = $this.get_filename()
        $result = $null

        if ($fs = New-Object System.IO.FileStream($file,[System.IO.FileMode]::Open,[System.IO.FileAccess]::Read)) {
            try {
                $result = [System.Drawing.Image]::FromStream($fs)
            } finally {
                $fs.Close()
            }
        }

        return $result
    }

    # NoImage画像を作成
    [System.Drawing.Image]create_noimage() {
        $msg = "No image"

        $width = 400
        $height = 300
        
        if ($c = New-Object System.Drawing.Bitmap($width, $height)) {
            $g = [System.Drawing.Graphics]::FromImage($c)
            try {
                $fnt = New-Object System.Drawing.Font("MS UI Gothic", 48)
                try {


                    $r = $g.MeasureString($msg,$fnt,$width)
                    $x = [int]((($width - [int]$r.Width)) / 2)
                    if ($x -lt 0 ) { $x = 0 }
                    $y = [int]((($height - [int]$r.Height)) / 2)
                    if ($y -lt 0 ) { $y = 0 }



                    $g.FillRectangle([System.Drawing.Brushes]::White, 0, 0, $width, $height)
                    $g.DrawString($msg, $fnt, [System.Drawing.Brushes]::Black, $x, $y)
                } finally {
                    $fnt.Dispose()
                }
            } finally {
                $g.Dispose()
            }
            return $c
        }

        throw $_
    }
}

# 本棚クラス
class BookShelf {
    

    # 書籍オブジェクトの配列
    [Book[]]$books = $null

    # 書籍の位置
    [int]$pos = $null

    # 書籍の数
    [int]$count = 0
    
    # 最初の書籍のパス
    [string]$start_path = $null

    # 本棚の場所(ディレクトリのパス)
    [string]$location = $null

    # コンストラクタ
    BookShelf() {
        $this.init()
    }

    # プロパティの初期化
    [void]init() {
        $this.books = $null
        $this.pos = $null
        $this.count = 0
        $this.start_path = $null
        $this.location = $null
    }

    # パスをセット
    [void]set_path($path) {
        
        if (-not(Test-Path -LiteralPath $path)) { throw $path }

        # 初期化
        $this.init()

        $this.start_path = $path
        $this.location = Split-Path $path -Parent
        $this.pos = 0

        $this.books = Get-ChildItem -LiteralPath $this.location | ? {
            ($_.PSIsContainer) -Or ($_.Extension -match "\.(jp(e)?g|png|bmp|gif|zip)")
        } | % -Begin {
            $i = 0
        } -Process {
            if($_.FullName -eq $path) {
                $this.pos = $i
            }            
            $i = $i + 1
            
            [Book]::new($_.FullName)
        }
        if ($this.books -eq $null) {
            $this.count = 0
        } else {
            $this.count = ($this.books).Count
        }
    }
    
    # 現在の書籍を取得
    [Book]get_book() {
        return $this.books[$this.pos]
    }

    # 最初の本確認
    [boolean]is_first(){
        return ($this.pos -eq 0)
    }

    # 最後の本確認
    [boolean]is_last(){

        return ($this.pos -eq ($this.count-1))
    }

    # 次の本へ移動
    [boolean]next(){
        if ($this.is_last()) {
            return $false
        }

        $this.pos = $this.pos + 1

        return $true
    }

    # 前の本へ移動
    [boolean]prev(){
        if ($this.is_first()) {
            return $false
        }

        $this.pos = $this.pos - 1

        return $true
    }

    # 先頭の本へ移動
    [void]first(){

        while ($this.prev()) {}
    }

    # 最後のページへ移動
    [void]last(){
        if ($this.count -eq 0) { return }
        $this.remove_empty_item()
        if ($this.count -eq 0) { return }

        while ($this.next()) {}
    }
}


# 表示モード(単ページ、両開き、半分)
enum ViewMode {
    Single
    Dual
    Half
}

# 表示部分(上部、下部)
enum ViewPart {
    Up
    Down
}

# コントローラークラス
class Controler {

    # 本棚オブジェクト
    $shelf = $null

    # ビューモード
    $view_mode = $null

    # 表示部分(半分表示)
    $view_part = $null

    # コンストラクタ
    Controler() {
        # 後からPathが変更される前提
        $this.shelf = [BookShelf]::new()
        $this.set_single_view()
    }

    # 本棚をセット
    set_shelfpath($path){

        $this.shelf.set_path($path)
        
    }

    # ビューモードを単ページにセット
    set_single_view(){
        $this.view_mode = [ViewMode]::Single
    }

    # ビューモードを見開きにセット
    set_dual_view(){
        $this.view_mode = [ViewMode]::Dual
    }

    # ビューモードを半分表示にセット
    set_half_view(){
        $this.view_mode = [ViewMode]::Half
        $this.view_part = [ViewPart]::Up
    }

    # 次へ
    [boolean]next() {
        $result = $false
        if ($this.view_mode -eq [ViewMode]::Single) {
            $result = $this.next_single()
        } elseif ($this.view_mode -eq [ViewMode]::Dual) {
            $result = $this.next_dual()
        } elseif ($this.view_mode -eq [ViewMode]::Half) {
            $result = $this.next_half()
        }
        return $result
    }

    # 次へ(単ページ)
    [boolean]next_single() {
        
        $result = $false

        if ($this.shelf.count -eq 0) {
            return $result
        }

        $book = $this.shelf.get_book()
        if ($this.shelf.is_last() -And $book.is_last()){
            return $result
        }

        $result = $true
        if ($book.is_last()) {
            # 最終ページの場合、本棚から前の本を取得
            $this.shelf.next()
            $book = $this.shelf.get_book()
            $book.first()

        } else {
            # 次のページをめくる
            $book.next()
        }

        return $result
    }

    # 次へ(見開き)
    [boolean]next_dual() {
        $result = $false

        if ($this.shelf.count -eq 0) {
            return $result
        }

        $book = $this.shelf.get_book()

        if ($book.is_last() -And $this.shelf.is_last()) {
            return $result
        }

        $result = $true
        if ($book.is_last()) {
            # 最終ページの場合、本棚から次の本を取得
            $this.shelf.next()
            $book = $this.shelf.get_book()
            $book.first()
        } else {
            # 次のページをめくる
            $book.next()

            if ($book.is_last()) {
                # 最終ページの場合、本棚から次の本を取得
                $this.shelf.next()
                $book = $this.shelf.get_book()
                $book.first()
            } else {
                $book.next()
            }
        }

        return $result
    }

    # 次へ(半分)
    [boolean]next_half() {
        $result = $false

        if ($this.shelf.count -eq 0) {
            return $result
        }

        $book = $this.shelf.get_book()
        if ($this.shelf.is_last() -And $book.is_last()){
            return $result
        }

        $result = $true
        if ($this.view_part -eq [ViewPart]::Up) {
            $this.view_part = [ViewPart]::Down
            return $result
        }

        if ($book.is_last()) {
            # 最終ページの場合、本棚から前の本を取得
            $this.shelf.next()
            $book = $this.shelf.get_book()
            $book.first()

        } else {
            # 次のページをめくる
            $book.next()
        }
        $this.view_part = [ViewPart]::Up

        return $result
    }

    # 前へ
    [boolean]prev() {
        $result = $false
        if ($this.view_mode -eq [ViewMode]::Single) {
            $result = $this.prev_single()
        } elseif ($this.view_mode -eq [ViewMode]::Dual) {
            $result = $this.prev_dual()
        } elseif ($this.view_mode -eq [ViewMode]::Half) {
            $result = $this.prev_half()
        }
        return $result
    }

    # 前へ(単ページ)
    [boolean]prev_single() {
        $result = $false

        if ($this.shelf.count -eq 0) {
            return $result
        }

        $book = $this.shelf.get_book()
        if ($this.shelf.is_first() -And $book.is_first()){
            return $result
        }

        $result = $true
        if ($book.is_first()) {
            # 先頭ページの場合、本棚から前の本を取得
            $this.shelf.prev()
            $book = $this.shelf.get_book()
            $book.last()

        } else {
            # 前のページをめくる
            $book.prev()
        }

        return $result
    }
    # 前へ(両開き)
    [boolean]prev_dual() {
        $result = $false

        if ($this.shelf.count -eq 0) {
            return $result
        }

        $book = $this.shelf.get_book()
        if ($this.shelf.is_first() -And $book.is_first()){
            return $result
        }


        $result = $true
        if ($book.is_first()) {
            # 先頭ページの場合、本棚から前の本を取得
            $this.shelf.prev()
            $book = $this.shelf.get_book()
            $book.last()

            if (-not($book.is_first()) -And (0 -eq ($book.count % 2))) {
                $book.prev()
            }

        } else {
            # 前のページをめくる
            $book.prev()

            if (-not($book.is_first())) {
                $book.prev()
            }

        }
        return $result
    }
    # 前へ(半分)
    [boolean]prev_half() {
        $result = $false

        if ($this.shelf.count -eq 0) {
            return $result
        }

        $book = $this.shelf.get_book()
        if ($this.shelf.is_first() -And $book.is_first()){
            return $result
        }


        $result = $true
        if ($this.view_part -eq [ViewPart]::Down) {
            $this.view_part = [ViewPart]::Up
            return $result
        }

        if ($book.is_first()) {
            # 先頭ページの場合、本棚から前の本を取得
            $this.shelf.prev()
            $book = $this.shelf.get_book()
            $book.last()

        } else {
            # 前のページをめくる
            $book.prev()
        }
        $this.view_part = [ViewPart]::Down

        return $result
    }

    # 画像を取得
    [System.Drawing.Image]get_image(){
        $img = $null
        if ($this.view_mode -eq [ViewMode]::Single) {
            $img = $this.get_image_single()
        } elseif ($this.view_mode -eq [ViewMode]::Dual) {
            $img = $this.get_image_dual()
        } elseif ($this.view_mode -eq [ViewMode]::Half) {
            $img = $this.get_image_half()
        }
        return $img
    }

    # 画像を取得(単ページ)
    [System.Drawing.Image]get_image_single(){
        $book = $this.shelf.get_book()

        return $book.get_image()
    }

    # 画像を取得(両開き)
    [System.Drawing.Image]get_image_dual(){
        $book = $this.shelf.get_book()
        
        $r_img = $book.get_image()

        if ($book.is_last()) {
            $l_img = [System.Drawing.Bitmap]::new($r_img.Width, $r_img.Height)
        } else {
            $book.next() | Out-Null
            $l_img = $book.get_image()
            $book.prev() | Out-Null
        }

        $w = ($r_img.Width + $l_img.Width)
        $h = $r_img.Height

        $img = [System.Drawing.Bitmap]::new($w, $h)
        $gr = [System.Drawing.Graphics]::FromImage($img)

        $s = [System.Drawing.Rectangle]::new(0, 0, $l_img.Width, $l_img.Height)
        $d = $s
        $gr.DrawImage($l_img, $d, $s, 2)

        $s = [System.Drawing.Rectangle]::new(0, 0, $r_img.Width, $r_img.Height)
        $d = [System.Drawing.Rectangle]::new($l_img.Width, 0, $r_img.Width, $r_img.Height)
        $gr.DrawImage($r_img, $d, $s, 2)

        $gr.Dispose()
        $l_img.Dispose()
        $r_img.Dispose()

        return [System.Drawing.Image]$img
    }

    # 画像を取得(半分表示)
    [System.Drawing.Image]get_image_half(){
        $book = $this.shelf.get_book()
        
        $src = $book.get_image()

        $w = $src.Width
        $h = [int]($src.Height / 2)

        $dst = [System.Drawing.Bitmap]::new($w, $h)
        $gr = [System.Drawing.Graphics]::FromImage($dst)

        $s = [System.Drawing.Rectangle]::new(0, 0, $w, $h)
        if ($this.view_part -eq [ViewPart]::Down) {
            $s = [System.Drawing.Rectangle]::new(0, $h, $w, $h)
        }
        $d = [System.Drawing.Rectangle]::new(0, 0, $w, $h)
        $gr.DrawImage($src, $d, $s, 2)


        $gr.Dispose()
        $src.Dispose()

        return [System.Drawing.Image]$dst
    }
}


# フォームを表示
function show() {
    Write-Host ("{0}" -f $MyInvocation.MyCommand)



    $ctrl = [Controler]::new()


    # ウィンドウのデフォルト幅
    $default_window_width = 400
    # ウィンドウのデフォルト高さ
    $default_window_height = 300

    # フォーム作成
    function my_form_create() {
        return New-Object System.Windows.Forms.Form | % {
            $_.Name = "MAINFORM"
            $_.Size = "${default_window_width},${default_window_height}"
            $_.Add_Resize({my_form_resize_event $this})
            $_.Add_KeyDown({
                switch ($_.KeyCode) {
                    "F11" { my_form_f11_event_fullscreen $this }
                }
            })
            $_.Add_Shown({
                my_form_resize_event $this
            })
            $_
        } | Add-Member -MemberType ScriptMethod -Name set_image -TypeName System.Drawing.Image -Value {
            param($img)

            $pic = $this.Controls["PICBOX"]
            if($pic -eq $null) { return }

            if ($pic.Image -Is [IDisposable]) { $pic.Image.Dispose() }
            $pic.Image = $img

        } -PassThru


    }

    # フォームのサイズ変更イベント
    function my_form_resize_event($sender) {
        $form = $sender
        $pic = $form.Controls["PICBOX"]
        $menu = $form.Controls["MENUBAR"]

        $pic.Size = $form.ClientSize


        $y = 0
        if ($menu.Visible) {
            $y = $menu.Size.Height
        }

        $pic.Location = "0,${y}"

        $w = $form.ClientSize.Width
        $h = $form.ClientSize.Height - $y


        $pic.Size = "${w},${h}"
    }

    # フォームのF11イベント(フルスクリーン)
    function my_form_f11_event_fullscreen($sender) {
        $form = $sender
        $menu = $form.Controls["MENUBAR"]

        # ディスプレイサイズと開始位置を取得
        $w = 0; $h = 0
        $x = 0; $y = 0
        [System.Windows.Forms.Screen]::AllScreens | % {
            $h = $_.Bounds.Height
            $w = $w + $_.Bounds.Width
            if ($x -ge $_.Bounds.X) {
                $x = $_.Bounds.X
            }
            if ($y -ge $_.Bounds.Y) {
                $y = $_.Bounds.Y
            }
        }

        # サイズ変更
        switch ($this.FormBorderStyle) {
            "None" {
                $menu.Visible = $true
                $form.FormBorderStyle = "Sizable"
                $form.SetDesktopBounds(0,0,$default_window_width, $default_window_height)
                $form.Text = "ウィンドウモード"
            }
            "Sizable" {
                $menu.Visible = $false
                $form.FormBorderStyle = "None"
                $form.SetDesktopBounds($x,$y,$w,$h)
                $form.Text = "フルスクリーンモード" # 見えない
            }
        }

    }

    # ピクチャボックス作成
    function my_picbox_create() {
        return New-Object System.Windows.Forms.PictureBox | % {
            $_.Name = "PICBOX"
            $_.SizeMode = "Zoom"

            if ($_.Image -Is [IDisposable]) { $_.Image.Dispose() }

            $_.Add_MouseDown({
                switch ($_.Button) {
                    "Right" { my_picbox_right_click_event($this) }
                    "Left" { my_picbox_left_click_event($this) }
                }
            })
            # D&D
            $_.AllowDrop = $true
            $_.Add_DragEnter({$_.Effect = "ALL"})


            $_.Add_DragDrop({
                $f = $this.parent
                $file = @($_.Data.GetData("FileDrop"))[0]
                $f.Text = $file
                $ctrl.set_shelfpath($file)
                start_view
            })

            $_
        }
    }

    # ピクチャボックスのクリックイベント(右クリック)
    function my_picbox_right_click_event($sender) {
        $pic = $sender
        $form = $pic.Parent

        $form.Text = "右クリック"

        if ($ctrl.prev()) {
            $img = $ctrl.get_image()
            $form.set_image($img)
        }

    }

    # ピクチャボックスのクリックイベント(左クリック)
    function my_picbox_left_click_event($sender) {
        $pic = $sender
        $form = $pic.Parent

        $form.Text = "左クリック"

        if ($ctrl.next()) {
            $img = $ctrl.get_image()
            $form.set_image($img)
        }

    }

    # 
    function start_view() {
        if ($ctrl.shelf.count -ne 0) {
            $img = $ctrl.get_image()
            $form.set_image($img)
        }
    }

    # メニュー開く項目の作成
    function my_menu_open_create() {
        return New-Object System.Windows.Forms.ToolStripMenuItem | % {
            $_.Name = "OPEN"
            $_.Text = "開く"
            $_.Add_Click({my_menu_open_click_event ($this)})
            $_
        }
    }

    # メニュー開く項目のクリックイベント
    function my_menu_open_click_event($sender) {
        $menu_item = $sender
        $form = $menu_item.OwnerItem.Owner.Parent
        $form.Text = $menu_item.Text

        $dialog = New-Object System.Windows.Forms.OpenFileDialog
        $dialog.Filter = "画像ファイル(*.PNG;*.JPG;*.GIF;*.ZIP)|*.PNG;*.JPG;*.JPEG;*.GIF;*.ZIP"
        $dialog.InitialDirectory = [Environment]::GetFolderPath("MyDocument")
        $dialog.Title = "ファイルを選択してください"
        $dialog.Multiselect = $false

        # ダイアログを表示
        if($dialog.ShowDialog() -eq [System.Windows.Forms.DialogResult]::OK){
            #Write-Host $dialog.FileName

            $ctrl.set_shelfpath($dialog.FileName)
            start_view
        }


    }

    # メニュー閉じる項目の作成
    function my_menu_close_create() {
        return New-Object System.Windows.Forms.ToolStripMenuItem | % {
            $_.Name = "CLOSE"
            $_.Text = "閉じる"
            $_.Add_Click({my_menu_close_click_event ($this)})
            $_
        }
    }

    # メニュー閉じる項目のクリックイベント
    function my_menu_close_click_event($sender) {
        $menu_item = $sender
        $form = $menu_item.OwnerItem.Owner.Parent
        $form.Text = $menu_item.Text
        $form.Close()
    }

    # メニューファイル項目の作成
    function my_menu_file_create() {
        return New-Object System.Windows.Forms.ToolStripMenuItem | % {
            $_.Name = "FILE"
            $_.Text = "ファイル"


            $item_open = my_menu_open_create
            $item_close = my_menu_close_create
            $separator = New-Object System.Windows.Forms.ToolStripSeparator
            $_.DropDownItems.AddRange(@($item_open, $separator, $item_close))

            $_
        }
    }

    # メニュー単ページ項目の作成
    function my_menu_singleview_create() {
        return New-Object System.Windows.Forms.ToolStripMenuItem | % {
            $_.Name = "SINGLEV"
            $_.Text = "単ページ表示"
            $_.Add_Click({my_menu_singleview_click_event ($this)})
            $_
        }
    }

    # メニュー単ページ項目のクリックイベント
    function my_menu_singleview_click_event($sender) {
        $menu_item = $sender
        $form = $menu_item.OwnerItem.Owner.Parent
        $form.Text = $menu_item.Text
        $ctrl.set_single_view()
        start_view
    }

    # メニュー見開き項目の作成
    function my_menu_dualview_create() {
        return New-Object System.Windows.Forms.ToolStripMenuItem | % {
            $_.Name = "DUALV"
            $_.Text = "見開き表示"
            $_.Add_Click({my_menu_dualview_click_event ($this)})
            $_
        }
    }

    # メニュー見開き項目のクリックイベント
    function my_menu_dualview_click_event($sender) {
        $menu_item = $sender
        $form = $menu_item.OwnerItem.Owner.Parent
        $form.Text = $menu_item.Text
        $ctrl.set_dual_view()
        start_view
    }

    # メニュー半分表示項目の作成
    function my_menu_halfview_create() {
        return New-Object System.Windows.Forms.ToolStripMenuItem | % {
            $_.Name = "HALFV"
            $_.Text = "半分表示"
            $_.Add_Click({my_menu_halfview_click_event ($this)})
            $_
        }
    }

    # メニュー半分表示項目のクリックイベント
    function my_menu_halfview_click_event($sender) {
        $menu_item = $sender
        $form = $menu_item.OwnerItem.Owner.Parent
        $form.Text = $menu_item.Text
        $ctrl.set_half_view()
        start_view
    }

    # メニュー表示項目の作成
    function my_menu_view_create() {
        return New-Object System.Windows.Forms.ToolStripMenuItem | % {
            $_.Name = "VIEW"
            $_.Text = "表示"


            $item_singlev = my_menu_singleview_create
            $item_dualv = my_menu_dualview_create
            $item_half = my_menu_halfview_create
            $_.DropDownItems.AddRange(@($item_singlev,$item_dualv,$item_half))

            $_
        }
    }

    # メニューの作成
    function my_menu_create() {
        return New-Object System.Windows.Forms.MenuStrip | % {
            $_.Name = "MENUBAR"

            $item_file = my_menu_file_create
            $item_view = my_menu_view_create

            $_.Items.AddRange(@($item_file, $item_view))
            $_
        }
    }

    $form = my_form_create
    $pic = my_picbox_create
    $menu = my_menu_create



    $form.Controls.AddRange(@($menu,$pic))

    start_view

    $form.ShowDialog()
}

show

powershell_iseを起動しスクリプトをコピー&ペーストして名前を付けて保存してください。
ブログの記事に投稿するには長すぎるスクリプトですが、頑張ってコピペしてください。

powershell_ise及びpowershellの起動

[Win]+[R]キーを押す。
名前欄に「powershell_ise」又は「powershell」と入力しエンター

PowerShellスクリプトを初めて実行する場合

使い方

powershell_ise又はpowershellを起動しコンソールから先に保存したファイル名のパスを入力しエンターキーを押すとフォームが表示されます。

フォームに表示させたい画像をエクスプローラからドラッグ&ドロップすると画像が表示されます。画像ファイル以外にも画像ファイルが保存されたディレクトリ、zipファイル等も対応しています。

画像表示後、左クリックで次の画像、右クリックで前の画像に推移します。

最後の画像に到達すると、そこで停止するように作ったつもりですが、書庫内(ディレクトリ又はzipファイル)内でループするバグがあります。治せる場合はそのうち治したいです。

終了は×で閉じてください。

コメント