Vb.net 如何使用滚动条打印容器的隐藏和可见内容
我有一个可滚动的面板:它的一些子控件是隐藏的,另一些是可见的 如何打印此面板上的所有内容,包括隐藏的子控件或在不滚动的情况下不可见的子控件Vb.net 如何使用滚动条打印容器的隐藏和可见内容,vb.net,winforms,graphics,scrollbar,panel,Vb.net,Winforms,Graphics,Scrollbar,Panel,我有一个可滚动的面板:它的一些子控件是隐藏的,另一些是可见的 如何打印此面板上的所有内容,包括隐藏的子控件或在不滚动的情况下不可见的子控件 Private Sub PrintDocument1_PrintPage(sender As Object, e As Printing.PrintPageEventArgs) Handles PrintDocument1.PrintPage Panel1.AutoSize = True Dim b As New Bitmap(Panel1.
Private Sub PrintDocument1_PrintPage(sender As Object, e As Printing.PrintPageEventArgs) Handles PrintDocument1.PrintPage
Panel1.AutoSize = True
Dim b As New Bitmap(Panel1.DisplayRectangle.Width, Panel1.DisplayRectangle.Height)
Panel1.DrawToBitmap(b, Panel1.ClientRectangle)
e.Graphics.DrawImage(b, New Point(40, 40))
Panel1.AutoSize = False
End Sub
这些方法集允许将文件的内容打印到位图 程序说明:
[ScrollableControl]。AutoScrollPosition=新点(0,0)
(否则会引发异常:位图大小错误。您可能希望存储当前滚动位置,然后将其还原)这将是位图的大小
边界
矩形相对于容器ClientArea)DrawNestedControls
,该方法将枚举并绘制所有嵌套的子容器/控件,保留内部剪辑边界RichEditPrinter
类包含打印RichTextBox/RichEdit控件内容所需的逻辑。该类使用正在打印控件的位图的设备上下文向RichTextBox发送消息。MSDN文档中提供了更多详细信息:
ScrollableControlToBitmap()
方法仅将ScrollableControl
类型作为参数:无法传递TextBox控件,即使它使用滚动条
► 将fullSize
参数设置为True
或False
以包含容器内的所有子控件或仅包含可见的子控件。如果设置为True
,则容器的ClientRectangle
将展开以包含并打印其所有子控件
► 将includeHidden
参数设置为True
或False
以包括或排除隐藏控件(如果有)
注意:此代码使用属性评估容器设备上下文的当前Dpi。此属性需要.Net Framework 4.7+。如果此版本不可用,您可以删除:
bitmap.SetResolution(canvas.DeviceDpi, canvas.DeviceDpi);
或使用其他方法导出值。请参阅。可能,请更新项目的框架版本:)
导入系统图形
导入System.Drawing.Imaging
导入System.Runtime.InteropServices
导入System.Windows.Forms
公共类控制打印机
作为位图的公共共享函数ScrollableControlToBitmap(画布作为ScrollableControl,fullSize作为Boolean,includeHidden作为Boolean)
canvas.AutoScrollPosition=新点(0,0)
如果包括在内,那么
canvas.SuspendLayout()
对于画布中的每个子控件作为控件。控件
child.Visible=True
下一个
canvas.ResumeLayout(True)
如果结束
canvas.PerformLayout()
Dim containerSize As Size=canvas.DisplayRectangle.Size
如果是全尺寸的话
containerSize.Width=Math.Max(containerSize.Width,canvas.ClientSize.Width)
containerSize.Height=Math.Max(containerSize.Height,canvas.ClientSize.Height)
其他的
containerSize=If((画布的类型是表单),canvas.PreferredSize,canvas.ClientSize)
如果结束
Dim bmp=新位图(containerSize.Width、containerSize.Height、PixelFormat.Format32bppArgb)
bmp.SetResolution(canvas.DeviceDpi,canvas.DeviceDpi)
Dim g=图形。从图像(bmp)
g、 清除(画布。背景色)
Dim rtfPrinter=新的RichEditPrinter(g)
尝试
DrawNestedControls(画布、画布、新矩形(Point.Empty、containerSize)、bmp、rtfPrinter)
返回bmp
最后
rtfPrinter.Dispose()
g、 处置
结束尝试
端函数
私有共享子DrawNestedControls(outerContainer作为控件,parent作为控件,parentBounds作为矩形,bmp作为位图,rtfPrinter作为RichEditPrinter)
对于i As Integer=parent.Controls.Count-1到0步骤-1
Dim ctl=父控件(i)
如果不是ctl.Visible或LSE(ctl.WITH<1或LSE ctl.Height<1),则继续
Dim剪贴簿=矩形。空
如果parent.Equals(outerContainer)则
剪贴簿=ctl.Bounds
其他的
Dim scrContainerSize As Size=parentBounds.Size
如果父项的类型为ScrollableControl,则
Dim scrCtrl=DirectCast(父级,可滚动控件)
与scrCtrl
如果.VerticalScroll.Visible,则SCRCContainerSize.Width-=(SystemInformation.VerticalScrollBarWidth+1)
如果.HorizontalScroll.Visible,则SCRCContainerSize.Height-=(SystemInformation.HorizontalScrollBarHeight+1)
以
如果结束
剪贴簿=Rectangle.Intersect(新矩形(Point.Empty,scrContainerSize),ctl.Bounds)
如果结束
如果剪贴簿宽度小于1或剪贴簿高度小于1,则继续
Dim bounds=outerContainer.RectangleToClient(父.RectangleToScreen(剪贴簿))
如果ctl的类型为RichTextBox,则
Dim rtb=DirectCast(ctl,RichTextBox)
rtfPrinter。
' Prints the content of the current Form instance,
' include all child controls and also those that are not visible
Dim bitmap = ControlsPrinter.ScrollableControlToBitmap(Me, True, True)
' Prints the content of a ScrollableControl inside a Form
' include all child controls except those that are not visible
Dim bitmap = ControlsPrinter.ScrollableControlToBitmap(Me.Panel1, True, False)
Imports System.Drawing
Imports System.Drawing.Imaging
Imports System.Runtime.InteropServices
Imports System.Windows.Forms
Public Class ControlPrinter
Public Shared Function ScrollableControlToBitmap(canvas As ScrollableControl, fullSize As Boolean, includeHidden As Boolean) As Bitmap
canvas.AutoScrollPosition = New Point(0, 0)
If includeHidden Then
canvas.SuspendLayout()
For Each child As Control In canvas.Controls
child.Visible = True
Next
canvas.ResumeLayout(True)
End If
canvas.PerformLayout()
Dim containerSize As Size = canvas.DisplayRectangle.Size
If fullSize Then
containerSize.Width = Math.Max(containerSize.Width, canvas.ClientSize.Width)
containerSize.Height = Math.Max(containerSize.Height, canvas.ClientSize.Height)
Else
containerSize = If((TypeOf canvas Is Form), canvas.PreferredSize, canvas.ClientSize)
End If
Dim bmp = New Bitmap(containerSize.Width, containerSize.Height, PixelFormat.Format32bppArgb)
bmp.SetResolution(canvas.DeviceDpi, canvas.DeviceDpi)
Dim g = Graphics.FromImage(bmp)
g.Clear(canvas.BackColor)
Dim rtfPrinter = New RichEditPrinter(g)
Try
DrawNestedControls(canvas, canvas, New Rectangle(Point.Empty, containerSize), bmp, rtfPrinter)
Return bmp
Finally
rtfPrinter.Dispose()
g.Dispose()
End Try
End Function
Private Shared Sub DrawNestedControls(outerContainer As Control, parent As Control, parentBounds As Rectangle, bmp As Bitmap, rtfPrinter As RichEditPrinter)
For i As Integer = parent.Controls.Count - 1 To 0 Step -1
Dim ctl = parent.Controls(i)
If Not ctl.Visible OrElse (ctl.Width < 1 OrElse ctl.Height < 1) Then Continue For
Dim clipBounds = Rectangle.Empty
If parent.Equals(outerContainer) Then
clipBounds = ctl.Bounds
Else
Dim scrContainerSize As Size = parentBounds.Size
If TypeOf parent Is ScrollableControl Then
Dim scrCtrl = DirectCast(parent, ScrollableControl)
With scrCtrl
If .VerticalScroll.Visible Then scrContainerSize.Width -= (SystemInformation.VerticalScrollBarWidth + 1)
If .HorizontalScroll.Visible Then scrContainerSize.Height -= (SystemInformation.HorizontalScrollBarHeight + 1)
End With
End If
clipBounds = Rectangle.Intersect(New Rectangle(Point.Empty, scrContainerSize), ctl.Bounds)
End If
If clipBounds.Width < 1 OrElse clipBounds.Height < 1 Then Continue For
Dim bounds = outerContainer.RectangleToClient(parent.RectangleToScreen(clipBounds))
If TypeOf ctl Is RichTextBox Then
Dim rtb = DirectCast(ctl, RichTextBox)
rtfPrinter.DrawRtf(rtb.Rtf, outerContainer.Bounds, bounds, ctl.BackColor)
Else
ctl.DrawToBitmap(bmp, bounds)
End If
If ctl.HasChildren Then
DrawNestedControls(outerContainer, ctl, clipBounds, bmp, rtfPrinter)
End If
Next
End Sub
Friend Class RichEditPrinter
Implements IDisposable
Private dc As Graphics = Nothing
Private rtb As RTBPrinter = Nothing
Public Sub New(graphics As Graphics)
dc = graphics
rtb = New RTBPrinter() With {
.ScrollBars = RichTextBoxScrollBars.None
}
End Sub
Public Sub DrawRtf(rtf As String, canvas As Rectangle, layoutArea As Rectangle, color As Color)
rtb.Rtf = rtf
rtb.Draw(dc, canvas, layoutArea, color)
rtb.Clear()
End Sub
Public Sub Dispose() Implements IDisposable.Dispose
rtb.Dispose()
End Sub
Private Class RTBPrinter
Inherits RichTextBox
Public Sub Draw(g As Graphics, hdcArea As Rectangle, layoutArea As Rectangle, color As Color)
Using brush = New SolidBrush(color)
g.FillRectangle(brush, layoutArea)
End Using
Dim hdc As IntPtr = g.GetHdc()
Dim canvasAreaTwips = New RECT().ToInches(hdcArea)
Dim layoutAreaTwips = New RECT().ToInches(layoutArea)
Dim formatRange = New FORMATRANGE() With {
.charRange = New CHARRANGE() With {
.cpMax = -1,
.cpMin = 0
},
.hdc = hdc,
.hdcTarget = hdc,
.rect = layoutAreaTwips,
.rectPage = canvasAreaTwips
}
Dim lParam As IntPtr = Marshal.AllocCoTaskMem(Marshal.SizeOf(formatRange))
Marshal.StructureToPtr(formatRange, lParam, False)
SendMessage(Me.Handle, EM_FORMATRANGE, CType(1, IntPtr), lParam)
Marshal.FreeCoTaskMem(lParam)
g.ReleaseHdc(hdc)
End Sub
<DllImport("User32.dll", CharSet:=CharSet.Auto, SetLastError:=True)>
Friend Shared Function SendMessage(hWnd As IntPtr, uMsg As Integer, wParam As IntPtr, lParam As IntPtr) As Integer
End Function
Friend Const WM_USER As Integer = &H400
Friend Const EM_FORMATRANGE As Integer = WM_USER + 57
<StructLayout(LayoutKind.Sequential)>
Friend Structure RECT
Public Left As Integer
Public Top As Integer
Public Right As Integer
Public Bottom As Integer
Public Function ToRectangle() As Rectangle
Return Rectangle.FromLTRB(Left, Top, Right, Bottom)
End Function
Public Function ToInches(rectangle As Rectangle) As RECT
Dim inch As Single = 14.92F
Return New RECT() With {
.Left = CType(rectangle.Left * inch, Integer),
.Top = CType(rectangle.Top * inch, Integer),
.Right = CType(rectangle.Right * inch, Integer),
.Bottom = CType(rectangle.Bottom * inch, Integer)
}
End Function
End Structure
<StructLayout(LayoutKind.Sequential)>
Friend Structure FORMATRANGE
Public hdcTarget As IntPtr ' A HDC for the target device to format for
Public hdc As IntPtr ' A HDC for the device to render to, if EM_FORMATRANGE is being used to send the output to a device
Public rect As RECT ' The area within the rcPage rectangle to render to. Units are measured in twips.
Public rectPage As RECT ' The entire area of a page on the rendering device. Units are measured in twips.
Public charRange As CHARRANGE ' The range of characters to format (see CHARRANGE)
End Structure
<StructLayout(LayoutKind.Sequential)>
Friend Structure CHARRANGE
Public cpMin As Integer ' First character of range (0 for start of doc)
Public cpMax As Integer ' Last character of range (-1 for end of doc)
End Structure
End Class
End Class
End Class