我想用Powershell在背景图像上画一些信息。我使用WPF表单来编写这些信息,以便更好地格式化/样式化。问题是,当我必须弄乱信息的时候,DataGrid的高度会被削减,这是我不明白的。我尝试使用MaxHeight和其他不同的属性,但无法修复它。
Add-Type -AssemblyName PresentationFramework, System.Drawing
[void][System.Reflection.Assembly]::LoadWithPartialName('PresentationFramework')
[xml]$xaml = @'
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApp1" SizeToContent="WidthAndHeight"
Name="window" Height="Auto" Width="Auto" Background="Blue" WindowStyle="ToolWindow">
<Window.Resources>
<Style TargetType="Grid">
<Setter Property="ShowGridLines" Value="True"/>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="Width" Value="Auto"/>
<Setter Property="Height" Value="Auto"/>
</Style>
<Style TargetType="TableCell">
<Setter Property="LineHeight" Value="Auto"/>
<Setter Property="BorderThickness" Value="1"/>
</Style>
<Style TargetType="RowDefinition" >
<Setter Property="Height" Value="Auto"/>
</Style>
<Style TargetType="TableColumn">
<Setter Property="Width" Value="Auto"/>
</Style>
<Style TargetType="TextBlock" >
<Setter Property="FontFamily" Value="Consolas" />
<Setter Property="FontSize" Value="20" />
<Setter Property="Foreground" Value="White" />
<Setter Property="Margin" Value="0" />
<Setter Property="Padding" Value="0" />
</Style>
<Style TargetType="DataGrid">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="GridLinesVisibility" Value="All"/>
<Setter Property="HeadersVisibility" Value="None"/>
</Style>
<Style TargetType="DataGridRow">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="Height" Value="Auto"/>
</Style>
<Style TargetType="DataGridCell">
<Setter Property="Height" Value="Auto"/>
<Setter Property="Foreground" Value="White" />
<Setter Property="FocusVisualStyle" Value="{x:Null}" />
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="FontFamily" Value="Consolas" />
<Setter Property="FontSize" Value="20" />
</Style>
</Window.Resources>
<Grid Name="Grid1" >
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Grid.Column="0" Padding="0,0,0,20" FontSize="30"><TextBlock FontSize="30" Foreground="#FFCBCBCB">This</TextBlock> is my Header!</TextBlock>
<DataGrid Grid.Row="1" Grid.Column="0" Name="DG1" AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTextColumn Header="Name" Binding="{Binding Name}" Width="Auto" CanUserResize="False" CanUserReorder="False" />
<DataGridTextColumn Header="Spacer" Binding="{Binding Spacer}" Width="50" CanUserResize="False" CanUserReorder="False" />
<DataGridTextColumn Header="Value" Binding="{Binding Value}" Width="Auto" CanUserResize="False" CanUserReorder="False" />
</DataGrid.Columns>
</DataGrid>
<TextBlock Grid.Row="2" Grid.Column="0" Padding="0,50,0,0">This is my Footer</TextBlock>
</Grid>
</Window>
'@
# Read XAML
$reader=(New-Object System.Xml.XmlNodeReader $xaml)
try{
$WpfApp1=[Windows.Markup.XamlReader]::Load( $reader )
}
catch{
Write-Error "Unable to parse XML, with error: $($Error[0])`n Ensure that there are NO SelectionChanged or TextChanged properties (PowerShell cannot process them)"
throw
}
# Store Form Objects In PowerShell
$xaml.SelectNodes("//*[@Name]") | %{"trying item $($_.Name)";
try {Set-Variable -Name "WPF_$($_.Name)" -Value $WpfApp1.FindName($_.Name) -ErrorAction Stop}
catch{throw}
}
# Fülle Grid
for ($i=1; $i -le 60; $i++) {
$WPF_DG1.AddChild([pscustomobject]@{Name='Test';Value=$i})
}
$WPF_window.AllowsTransparency = $True
$WPF_window.Opacity = 0
$WPF_window.ShowInTaskbar = $False
$WPF_window.ShowActivated = $False
$WPF_window.WindowStyle = 'None'
$WpfApp1.Add_ContentRendered({
$WpfApp1.Close()
})
$WpfApp1.ShowDialog() | out-null
[int]$infoHeight = $WPF_Grid1.ActualHeight
[int]$infoWidth = $WPF_Grid1.ActualWidth
[string]::Format("WPF_Grid1 Größe: {0}x{1}", $infoWidth, $infoHeight) | Write-Host
# Speichere WPF-Grid in Bitmap
$rBmp = New-Object Windows.Media.Imaging.RenderTargetBitmap($infoWidth, $infoHeight, 96, 96, ([Windows.Media.PixelFormats]::Pbgra32))
$rBmp.Render($WPF_Grid1)
# Konvertiere Bitmap
$ms = New-Object System.IO.MemoryStream
$enc = New-Object System.Windows.Media.Imaging.BmpBitmapEncoder
$enc.Frames.Add([Windows.Media.Imaging.BitmapFrame]::Create($rBmp))
$enc.Save($ms)
$infoImg = [System.Drawing.Image]::FromStream($ms)
$infoImg.MakeTransparent()
[string]::Format("infoImg Größe: {0}x{1}", $infoImg.width, $infoImg.height) | Write-Host
# Lese Quell-Bild
$srcImg = [System.Drawing.Image]::FromFile($Env:WinDir + "\Web\Screen\img100.jpg")
[string]::Format("srcImg Größe: {0}x{1}", $srcImg.width, $srcImg.height) | Write-Host
# Erstelle ein Bitmap in das gezeichnet wird
$dstBmp = New-Object System.Drawing.Bitmap(([int]($srcImg.width)),([int]($srcImg.height)))
# Erstelle Graphics Objekt
$gUnit = [Drawing.GraphicsUnit]::Pixel
$gImg = [System.Drawing.Graphics]::FromImage($dstBmp)
$gImg.CompositingQuality = [System.Drawing.Drawing2D.CompositingQuality]::HighQuality
$gImg.SmoothingMode = [System.Drawing.Drawing2D.SmoothingMode]::AntiAlias
$gImg.InterpolationMode = [System.Drawing.Drawing2D.InterpolationMode]::HighQualityBicubic
$gImg.PixelOffsetMode = [System.Drawing.Drawing2D.PixelOffsetMode]::HighQuality
# Zeichne das Quell-Bild in unser gImg
$srcRect = New-Object Drawing.Rectangle(0, 0, $srcImg.Width, $srcImg.Height)
$gImg.DrawImage($srcImg, $srcRect, 0, 0, $srcImg.Width, $srcImg.Height, $gUnit)
# get scale ratio
$xpos = 150
$ypos = 150
$ratio = 0.1
while($($infoImg.Height*$ratio) -le $(($srcImg.Height-$ypos)*0.75))
{
$ratio += 0.1
#[string]::Format("if ({0} -le {1})", $($infoImg.Height*$ratio), $($srcImg.Height*0.75)) | Write-Host
}
[string]::Format("infoRect: X={0} Y={1} RATIO={2}", $xpos, $ypos, $ratio) | Write-Host
# Zeichne das Info-Bild in unser gImg
$infoRect = New-Object Drawing.Rectangle($xpos, $ypos, $($infoImg.Width*$ratio), $($infoImg.Height*$ratio))
$gImg.DrawImage($infoImg, $infoRect, 0, 0, $infoImg.Width, $infoImg.Height, $gUnit)
# Aufräumen
Remove-Item –Path "$($Env:Temp)\Test-*.jpg" -Force
# Neue Ausgabedatei erstellen
$dstFile = "$($Env:Temp)\Test-$(get-date -Format yyyy-MM-dd-HH-mm).jpg"
$dstBmp.save($dstFile, [System.Drawing.Imaging.ImageFormat]::Jpeg)我添加了一个完整的工作测试代码(在win 10上-因为背景图像,你也可以更改为其他图像),它显示了问题。
检查生成的Test-*.jpg in %Temp% -我们应该看到网格的页脚。当我们将for循环更改为max 30时,整个过程都在运行...但有时我需要显示更多的信息。
希望有人能指出是什么导致了这个问题。在网上找不到相同的东西,并为此工作了几个小时……
发布于 2020-02-03 04:14:01
在WPF中,当呈现应用程序时,实际高度被设置为监视器边界的最大值。这很有意义,因为在正常情况下,您不希望窗口比显示器大。
你为你的窗口拍摄的快照只考虑了渲染部分,这在你的例子中遗漏了一些元素。
为了避免这个问题,你想让窗口变得尽可能的大。因为您不知道窗口的高度,所以这里可以做的是设置一个任意的MinHeight值,以确保您的窗口包含所有内容。
因为它不会显示在屏幕上,并且我们不关心窗口是否越界,所以我们在这里使用3000。
在那里,我们将使用Add-ContentRendered脚本块并计算网格的实际高度(页眉+数据网格+页脚)。
然后,我们将窗口的MinHeight和Height属性重置为该大小,以便快照不包含空白空间。
以下是代码中受影响的部分以及修改后的外观
# Arbitrary value to make sure all of our content will be captured
$WPF_window.MinHeight = 3000
$WpfApp1.Add_ContentRendered( {
$MinHeight = ($WPF_Grid1.RowDefinitions.ActualHeight | Measure-Object -Sum) |
Select -ExpandProperty Sum
$WPF_window.MinHeight = $MinHeight
$WPF_window.Height = $MinHeight
$WpfApp1.Close()
})https://stackoverflow.com/questions/59981067
复制相似问题