winforms Powershell GUI进度条 Flink 的文本与绘图

wgeznvg7  于 2023-06-24  发布在  Shell
关注(0)|答案(1)|浏览(97)

我想创建一个PowershellGUI,在一个进度条上显示文本,例如,我用来计数目录中的文件,但文本 Flink 。我从这里得到的想法是:更新后的标签可以工作,但是因为它没有真正的透明背景,我不能把它放在酒吧上。设置Doublebuffer是没有帮助的,有什么关于如何改进的提示吗?
下面是示例代码:

$code = @"
    using System;
    using System.Windows.Forms;

    public class DoubleBufferedForm : System.Windows.Forms.Form
    {
        public DoubleBufferedForm()
        {
            this.DoubleBuffered = true;
        }
    }
"@

$Type = [DoubleBufferedForm]
if(!$Type)
{
    Add-Type -TypeDefinition $code -ReferencedAssemblies System.Windows.Forms, System.Drawing, System.Data, System.ComponentModel
}
Add-Type -AssemblyName System.Windows.Forms

[System.Windows.Forms.Application]::EnableVisualStyles()
[void][Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
[void][Reflection.Assembly]::LoadWithPartialName("System.Drawing")

$Path = "C:\Windows"
$Title = "Directory Usage Analysis: $Path"

$ObjForm = New-Object DoubleBufferedForm
$ObjForm.Text = $title
$ObjForm.Height = 200
$ObjForm.Width = 400
$ObjForm.BackColor = "White"
$ObjForm.FormBorderStyle = [System.Windows.Forms.FormBorderStyle]::FixedSingle
$ObjForm.StartPosition = [System.Windows.Forms.FormStartPosition]::CenterScreen

$ProgressBar = New-Object System.Windows.Forms.ProgressBar
$ProgressBar.Style = 'Continuous'
$ProgressBar.Width = $ObjForm.Width - 100
$ProgressBar.Height = 20
$ProgressBar.Left = ($ObjForm.Width - $ProgressBar.Width) / 2
$ProgressBar.Top = 40
$ObjForm.Controls.Add($ProgressBar)

$x = ($Progressbar.Width / 2)
$y = ($Progressbar.Height / 100)

$ObjLabel = New-Object system.Windows.Forms.Label
$ObjLabel.AutoSize = $true
$ObjLabel.Left = ($ObjForm.Width - $Label.Width) / 2
$ObjLabel.Top = 70
$ObjLabel.Location = New-Object System.Drawing.Size($x, $y)

$ObjForm.controls.add($ObjLabel)

$SyncHash = [hashtable]::Synchronized(@{ Form = $ObjForm; ProgressBar = $ProgressBar; Label = $ObjLabel ; path = $path})
$Runspace = [runspacefactory]::CreateRunspace()
$Runspace.ThreadOptions = "ReuseThread"
$Runspace.Open()
$Runspace.SessionStateProxy.SetVariable("SyncHash", $SyncHash)
$Worker = [PowerShell]::Create().AddScript({
    $files = @([System.IO.Directory]::GetFileSystemEntries($SyncHash.path,'*'))
    for ($i = 0; $i -le $files.count; $i++) {
            start-sleep -Milliseconds 100
            [int]$pct = ($i/$files.count)*100
            $text = "$pct %"
            
            $Font = New-Object System.Drawing.Font('Arial',10,[System.Drawing.FontStyle]([System.Drawing.FontStyle]::Bold))
            $brush1 = New-Object Drawing.SolidBrush([System.Drawing.Color]::Black)
            
            $PBCG = $SyncHash.ProgressBar.CreateGraphics()
            $x = ($($SyncHash.ProgressBar.Width) / 2) - ([int]$PBCG.MeasureString($text, $Font).Width / 2)
            $y = ($($SyncHash.ProgressBar.Height) / 2) - ([int]$PBCG.MeasureString($text, $Font).Height / 2)
            $PointF = [System.Drawing.PointF]::new($x, $y)    
    
            $SyncHash.ProgressBar.Value = $pct
            $SyncHash.label.text = "Completed: $pct %"
            
            $SyncHash.Form.Refresh()
            $PBCG.DrawString($text, $Font, $brush1, $PointF)
        }
        $SyncHash.Form.Refresh()
        start-sleep 5
        $SyncHash.Form.Close()
    })
$Worker.Runspace = $Runspace
$Worker.BeginInvoke() | out-null
$ObjForm.ShowDialog()

我已经尝试过运行空间和双缓冲区的不同方法,但我不理解我能找到的.NET的东西。
这也无济于事:Anyway to remove text flickering in this custom ProgressBar class?
使用WPF对我来说太复杂了,因为我已经有了一个完整的Form,我只想在其中实现这个bar。

0ve6wy6x

0ve6wy6x1#

您可以处理WM_PAINT,然后使用TextRenderer并在ProgressBar上绘制所需的文本。

**示例- PowerShell在ProgressBar上显示文本-无 Flink **

using assembly System.Windows.Forms
using namespace System.Windows.Forms
using namespace System.Drawing
$assemblies = "System.Windows.Forms", "System.Drawing"
$code = @"
using System.Drawing;
using System.Windows.Forms;
public class MyProgressBar : ProgressBar
{
    protected override void WndProc(ref Message m)
    {
        base.WndProc(ref m);
        if (m.Msg == 0xF /*WM_PAINT*/)
        {
            using (var g = CreateGraphics())
                TextRenderer.DrawText(g, Text,
                   Font, ClientRectangle, ForeColor);
        }
    }
}
"@
Add-Type -ReferencedAssemblies $assemblies -TypeDefinition $code -Language CSharp 
$form = [Form] @{
    ClientSize = [Point]::new(400,100);
    Text = "ProgressBar Text Sample";
}    
$form.Controls.AddRange(@(
    ($myProgressBar1 = [MyProgressBar] @{Location = [Point]::new(10,40);
        ForeColor = [Color]::Black;
        Width = 300; 
        Height = 50;})
))
$timer = [Timer] @{Interval=100; Enabled=$false}
$timer.add_Tick({param($sender,$e)
    if($myProgressBar1.Value -lt 100){
        $myProgressBar1.Value+=1
        $myProgressBar1.Text = $myProgressBar1.Value.ToString();
    }
})
$form.add_Load({param($sender,$e) $timer.Start()});
$null = $form.ShowDialog()
$timer.Dispose()
$form.Dispose()

相关问题