winforms Powershell GUI PictureBox无法更改照片

v1l68za4  于 2022-11-17  发布在  Shell
关注(0)|答案(1)|浏览(201)

我是新的Powershell。我试图创建图片框,将加载大量的图像在一个文件夹。我有一个文件夹,包含10个图像。但我希望我的图片框显示它动态每秒钟或3秒
以下是目前为止我代码。

####################################### Form settings ##############################################
    [void] [System.Reflection.Assembly]::LoadWithPartialName("System.Drawing") 
    [void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")  

    $Form = New-Object System.Windows.Forms.Form
    $Form.FormBorderStyle = [System.Windows.Forms.FormBorderStyle]::FixedDialog
    $Form.Anchor = "Top,Bottom,Left,Right"
    $Form.Size = New-Object System.Drawing.Size(1920,1600) 
    $Form.AutoScale = $True 
    $Form.StartPosition = "CenterScreen" #loads the window in the center of the screen
    $Form.BackgroundImageLayout = "Zoom"
    $Form.MinimizeBox = $True
    $Form.MaximizeBox = $False
    $Form.WindowState = "Normal"
    $Form.SizeGripStyle = "Auto"
    $Form.AutoSizeMode = New-Object System.Windows.Forms.AutoSizeMode
    $Form.SizeGripStyle = "Show"
    $Form.BackColor = "LightGray"
    ###################################################################################################
    ###################################################################################################
    ######################################### Image Folder ############################################
 
    $ImagePreview = New-Object System.Windows.Forms.PictureBox
    $ImagePreview.SizeMode = [System.Windows.Forms.PictureBoxSizeMode]::StretchImage
    $ImagePreview.Location = New-Object System.Drawing.Size(965,110) 
    $ImagePreview.Size = New-Object System.Drawing.Size(295,370)
    $ImagePreview.BackColor = "White"
    $Form.Controls.Add($ImagePreview)
 
    Function ImageFolder($ImagePreview)
    {
        $ImageItem = Get-Item "C:\Newfolder" 
        $ImagePreview.ImageLocation = $ImageItem
    }

    $TimerImageFolder = New-Object System.Windows.Forms.Timer
    $TimerImageFolder.Interval  = 3000
    $TimerImageFolder.Add_Tick({$ImageFolder $ImagePreview})
    $TimerImageFolder.Enabled = $True
    
    $ImageGroupBox = New-Object System.Windows.Forms.GroupBox
    $ImageGroupBox.Location = New-Object System.Drawing.Size(940,70) 
    $ImageGroupBox.size = New-Object System.Drawing.Size(350,440)
    $ImageGroupBox.text = "Preview"
    $ImageGroupBox.BackColor = "DimGray"
    $ImageGroupBox.ForeColor = "White"
    $Form.Controls.Add($ImageGroupBox)

    ####################################### Result ##############################################
    $Form.Add_Shown({$Form.Activate()})
    [void] $Form.ShowDialog()

我不知道哪部分错了。非常感谢你们的帮助

k75qkfdt

k75qkfdt1#

您尝试从PowerShell执行的是一项繁琐的任务。您可能注意到,它需要示例化powershell instance,其中初始化Forms.Timer,这是必需的,因为我们需要在单独的线程上执行.Tick event,否则,每次触发此事件时表单都会冻结。
下面共享的代码是,作为您试图实现的最小复制,我已经尝试尽可能地简化,但如前所述,这不是一个简单的任务从PowerShell。
下面的例子以及另一个例子使用一个API从互联网而不是从磁盘加载图片可以在this Gist上找到。那里还有一个gif演示。

using namespace System.Windows.Forms
using namespace System.Drawing
using namespace System.Management.Automation.Runspaces

Add-Type -AssemblyName System.Drawing, System.Windows.Forms

[Application]::EnableVisualStyles()

$event = @{}
# Get the paths of all the pictures in the `pictures` folder
$pictures = (Get-ChildItem .\pictures -Filter *.png).FullName

# basic form
$form = [Form]@{
    ClientSize    = [Size]::new(1280, 720)
    StartPosition = 'CenterScreen'
}

# basic picturebox, note it includes a `Name` so it's easier to find
# from inside the `powershell` instance
$pictureBox = [PictureBox]@{
    Name      = 'myPictureBox'
    Anchor    = 'top, left'
    SizeMode  = [PictureBoxSizeMode]::StretchImage
    Location  = [Point]::new(20, 20)
    Size      = [Size]::new($form.Width - 60, $form.Height - 80)
    Image     = [Drawing.Image]::FromFile($pictures[0])
}
$form.Controls.Add($pictureBox)

# event to resize the picturebox when the form is resized
$form.Add_Resize({
    $pictureBox.Size = [Size]::new($this.Width - 60, $this.Height - 80)
})

# initialize a `powershell` instance where we can handle the the Slide Show
# in PowerShell we require to perform this action from a different thread,
# else the form will freeze every 3000 milliseconds
$ps = [powershell]::Create().AddScript({
    param($pictures, $form)

    [ref] $ref = 1
    $timer = [Windows.Forms.Timer]@{
        Interval = 3000
    }

    # find the pictureBox in the Form controls
    $pictureBox = $form.Controls.Find('myPictureBox', $false)[0]

    # this Tick Event swaps the pictures when triggered
    $timer.Add_Tick({
        $pictureBox.Image = [Drawing.Image]::FromFile($pictures[$ref.Value++ % $pictures.Count])
    })

    # Start the Timer
    $timer.Enabled = $true

    # this `while` loop keeps this thread running until the form is closed
    while($form.DialogResult -eq 'None') {
        # we perform `Application.DoEvents()` so the form is updated on each loop iteration,
        # without it we wouldn't see the picturebox updated
        [Windows.Forms.Application]::DoEvents()
    }
    $form.DialogResult
    # here we pass the list of paths and the form instance itself to this thread
}).AddParameters(@{ pictures = $pictures; form = $form })

# when the form is shown
$form.Add_Shown({
    # bring it to front
    $this.Activate()
    # and add this AsyncResult to the `$events` hashtable
    $event['AsyncResult'] = $ps.BeginInvoke()
})

# display the form (this blocks the current thread)
$null = $form.ShowDialog()
# when the form is closed, stop the runspace
$ps.EndInvoke($event['AsyncResult'])
# and dispose everything
$form, $ps | ForEach-Object Dispose

相关问题