【发布时间】:2020-11-18 23:59:38
【问题描述】:
在我之前的一个问题中,我询问了如何截取ScrollViewer 中的所有内容,而不仅仅是ViewPort 中可见的内容。经过多次尝试,我找到了自己的答案,但不幸的是,这个答案引发了另一个问题。
看看这个示例代码:
ItemViewModel.vb(我的TreeViewItems 只是一个简单的视图模型):
Public Class ItemViewModel
Public Property Text As String
Public Property Items As New ObservableCollection(Of ItemViewModel)
End Class
ViewModel.vb(我的主窗口的视图模型,在构造函数中创建了一些项目):
Public Class ViewModel
Public Property Items As New ObservableCollection(Of ItemViewModel)
Private Const levels As Integer = 3
Public Sub New()
Dim item1 As ItemViewModel
Dim item2 As ItemViewModel
Dim item3 As ItemViewModel
For index1 As Integer = 1 To levels
item1 = New ItemViewModel With {.Text = String.Format("Node {0} - {1}", index1, Guid.NewGuid.ToString)}
Me.Items.Add(item1)
For index2 As Integer = 1 To levels
item2 = New ItemViewModel With {.Text = String.Format("Node {0}.{1} - {2}", index1, index2, Guid.NewGuid.ToString)}
item1.Items.Add(item2)
For index3 As Integer = 1 To levels
item3 = New ItemViewModel With {.Text = String.Format("Node {0}.{1}.{2} - {3}", index1, index2, index3, Guid.NewGuid.ToString)}
item2.Items.Add(item3)
Next index3
Next index2
Next index1
End Sub
End Class
MainWindow.xaml(主窗口本身,显示TreeView):
<Window x:Class="MainWindow"
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:ScreenshotTest"
mc:Ignorable="d"
Title="MainWindow"
Height="200" Width="300" KeyDown="Window_KeyDown">
<Window.DataContext>
<local:ViewModel />
</Window.DataContext>
<TreeView x:Name="Tree" ItemsSource="{Binding Items}">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate DataType="{x:Type local:ItemViewModel}" ItemsSource="{Binding Items}">
<Border BorderThickness="1" BorderBrush="Black" Margin="1">
<TextBlock Text="{Binding Text}" Margin="2" />
</Border>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
<TreeView.ItemContainerStyle>
<Style TargetType="{x:Type TreeViewItem}">
<Setter Property="IsExpanded" Value="True" />
</Style>
</TreeView.ItemContainerStyle>
</TreeView>
</Window>
MainWindow.xaml.vb(主窗口的代码隐藏,这里是“有用”代码所在的位置):
Class MainWindow
Private Sub Window_KeyDown(sender As Object, e As KeyEventArgs)
Dim panel As StackPanel
If e.Key <> Key.P Then
Exit Sub
End If
panel = GetFirstChildOfType(Of StackPanel)(Me.Tree)
panel.Background = Brushes.White
panel.UpdateLayout()
Me.CaptureScreen(panel, "C:\Temp\Screenshot.png")
End Sub
Private Shared Function GetFirstChildOfType(Of T As DependencyObject)(obj As DependencyObject) As T
Dim result As T
Dim child As DependencyObject
If (obj Is Nothing) Then
Return Nothing
End If
If (VisualTreeHelper.GetChildrenCount(obj) = 0) Then
Return Nothing
End If
For index As Integer = 0 To VisualTreeHelper.GetChildrenCount(obj)
child = VisualTreeHelper.GetChild(obj, index)
result = TryCast(child, T)
If (result Is Nothing) Then
result = GetFirstChildOfType(Of T)(child)
End If
If (result IsNot Nothing) Then
Return result
End If
Next index
Return Nothing
End Function
Private Sub CaptureScreen(source As UIElement, filename As String)
Dim height As Double
Dim renderHeight As Double
Dim width As Double
Dim renderWidth As Double
Dim renderTarget As RenderTargetBitmap
Dim vb As VisualBrush
Dim dv As DrawingVisual
Dim encoder As PngBitmapEncoder
Try
height = source.RenderSize.Height
renderHeight = height
width = source.RenderSize.Width
renderWidth = width
renderTarget = New RenderTargetBitmap(Convert.ToInt32(renderWidth), Convert.ToInt32(renderHeight), 96, 96, PixelFormats.Pbgra32)
vb = New VisualBrush(source)
dv = New DrawingVisual
Using dc As DrawingContext = dv.RenderOpen
dc.DrawRectangle(vb, Nothing, New Rect(New Point(0, 0), New Point(width, height)))
End Using
renderTarget.Render(dv)
encoder = New PngBitmapEncoder
encoder.Frames.Add(BitmapFrame.Create(renderTarget))
Using fs As IO.FileStream = New IO.FileStream(filename, IO.FileMode.Create, IO.FileAccess.Write)
encoder.Save(fs)
End Using
Catch ex As Exception
Stop
End Try
End Sub
End Class
如果你运行这个程序,你会看到一个带有一些项目的TreeView,如果你按P,一个TreeView的内容的屏幕截图会被截取并保存为“C:\Temp\Screenshot. png"。
到目前为止,一切都很好,屏幕截图大致看起来就像屏幕上看到的一样(质量方面)。例如,如果您在 IrfanView 中查看创建的 png 文件(大小为 100%),所有内容都是可读的。
但是如果我创建越来越多的项目(将levels 常量增加到 5,然后增加到 7),图片的质量会越来越差,在 levels=7 屏幕截图上看不到任何内容.
有谁知道这里发生了什么以及我该如何解决?我对 C# 中的答案也很好。
这里有一些屏幕截图可以可视化我的问题:
屏幕上的主窗口
level=3 的屏幕截图
level=5 的屏幕截图
level=7 的屏幕截图
【问题讨论】: