VB.NET-Tipp 0153: Bug im PageSetupDialog
von AtaRist
Beschreibung
In Windows-Systemen mit metrischem Maßsystem in den Regions- und Spracheinstellungen kommt es zu zwei Fehlern bei der Benutzung des PageSetupDialog:
- Ist EnableMetric nicht gesetzt, werden falsche Werte für die Seitenränder zurückgeliefert, da immer davon ausgegangen wird, dass die Zahlen metrische Werte sind, was allerdings in dem Fall nicht gegeben ist. Somit werden zum Beispiel aus 100 1/100 Inch plötzlich 39 1/100 Inch.
- Ist EnableMetric auf True gesetzt werden die Werte für die Seitenränder teilweise falsch angezeigt. Das liegt daran, dass die Werte in der Margins-Klasse als Integer definiert sind und es bei der Umrechnung von Inch in Millimeter zu gewaltigen Rundungsfehlern kommt.
Dieser Fehler ist Microsoft sehr wohl bekannt, sie bieten aber keinen wirklich praktikablen Workaround dazu an (KB814355).
Wird eine höhere Auflösung benötigt führt kein Weg an einem eigenen Dialog und eigenen Pagesettings- und Margins-Klassen vorbei.
Hier finden sich beide Lösungsmöglichkeiten.
Schwierigkeitsgrad: | Framework-Version(en): .NET Framework 1.0, .NET Framework 1.1, .NET Framework 2.0, .NET Framework 3.0, .NET Framework 3.5, .NET Framework 4 | .NET-Version(en): Visual Basic 2002, Visual Basic 2003, Visual Basic 2005, Visual Basic 2008, Visual Basic 2010 | Download: |
' Dieser Quellcode stammt von http://www.activevb.de ' und kann frei verwendet werden. Für eventuelle Schäden ' wird nicht gehaftet. ' Um Fehler oder Fragen zu klären, nutzen Sie bitte unser Forum. ' Ansonsten viel Spaß und Erfolg mit diesem Source! ' Projektversion: Visual Studio 2008 ' Option Strict: An ' Option Explicit: An ' Option Infer: An ' ' Referenzen: ' - System ' - System.Data ' - System.Deployment ' - System.Drawing ' - System.Management ' - System.Windows.Forms ' - System.Xml ' ' Imports: ' - Microsoft.VisualBasic ' - System ' - System.Collections ' - System.Collections.Generic ' - System.ComponentModel ' - System.Drawing ' - System.Diagnostics ' - System.Windows.Forms ' - System.Xml.Serialization ' ' ############################################################################## ' ########################## dlgMyPageSetupDialog.vb ########################### ' ############################################################################## Imports System.Windows.Forms Public Class dlgMyPageSetupDialog Private _pagesettings As MyPageSettings Private _printersettings As Printing.PrinterSettings Private _EnableMetric As Boolean Private _PreviewText As String = _ "Dies ein Test für die Seiteneinstellungen ihres Druckers." & _ vbCrLf & "Doch manchmal ist einfach zu blöd einen sinnvollen Text " & _ "für sowas zu erstellen daher lassen wird das jetzt und geben den " & _ "Text einfach mal aus." & vbCrLf & vbCrLf Public Property PageSettings() As MyPageSettings Get Return _pagesettings End Get Set(ByVal value As MyPageSettings) _pagesettings = value _printersettings = _pagesettings.PrinterSettings End Set End Property Public Property PrinterSettings() As Printing.PrinterSettings Get Return _printersettings End Get Set(ByVal value As Printing.PrinterSettings) _printersettings = value End Set End Property Public Property EnableMetric() As Boolean Get Return _EnableMetric End Get Set(ByVal value As Boolean) _enableMetric = value End Set End Property Private Sub btnOk_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles btnOk.Click CreateNewPageSettings() Me.DialogResult = System.Windows.Forms.DialogResult.OK Me.Close() End Sub Private Sub btnCancel_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) _ Handles btnCancel.Click Me.DialogResult = System.Windows.Forms.DialogResult.Cancel Me.Close() End Sub Private Sub btnPrinter_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) _ Handles btnPrinter.Click Dim dlgprn As New dlgMyPrinterSettings dlgprn.PrinterSettings = _printersettings If dlgprn.ShowDialog = Windows.Forms.DialogResult.OK Then _printersettings = dlgprn.PrinterSettings _pagesettings = New MyPageSettings(_printersettings) ShowPageSettings() End If End Sub Private Sub ShowPageSettings() pnlPreview.SuspendLayout() cbxPaperSize.Items.Clear() For Each ps As Printing.PaperSize In _ _pagesettings.PrinterSettings.PaperSizes cbxPaperSize.Items.Add(ps.PaperName) Next cbxPaperSize.SelectedItem = _pagesettings.PaperSize.PaperName cbxPaperSource.Items.Clear() If _printersettings.PaperSources.Count > 0 Then For Each ps As Printing.PaperSource In _printersettings.PaperSources cbxPaperSource.Items.Add(ps.SourceName) Next cbxPaperSource.SelectedItem = _pagesettings.PaperSource.SourceName cbxPaperSource.Enabled = True Else cbxPaperSource.Enabled = False End If If _pagesettings.Landscape Then rbtLandscape.Checked = True Else rbtNormal.Checked = True End If If Globalization.RegionInfo.CurrentRegion.IsMetric And _EnableMetric Then txtMarginLeft.Text = Math.Round( _ _pagesettings.Margins.LeftMetric / 10, 2).ToString txtMarginRight.Text = Math.Round( _ _pagesettings.Margins.RightMetric / 10, 2).ToString txtMarginTop.Text = Math.Round( _ _pagesettings.Margins.TopMetric / 10, 2).ToString txtMarginBottom.Text = Math.Round( _ _pagesettings.Margins.BottomMetric / 10, 2).ToString Else txtMarginLeft.Text = Math.Round( _ _pagesettings.Margins.Left / 10, 2).ToString txtMarginRight.Text = Math.Round( _ _pagesettings.Margins.Right / 10, 2).ToString txtMarginTop.Text = Math.Round( _ _pagesettings.Margins.Top / 10, 2).ToString txtMarginBottom.Text = Math.Round( _ _pagesettings.Margins.Bottom / 10, 2).ToString End If pnlPreview.ResumeLayout() End Sub Private Function PaperSizeFromName(ByVal Name As String) _ As Printing.PaperSize For Each ps As Printing.PaperSize In _printersettings.PaperSizes If ps.PaperName = Name Then Return ps End If Next Return Nothing End Function Private Function PaperSourceFromName(ByVal Name As String) _ As Printing.PaperSource For Each ps As Printing.PaperSource In _printersettings.PaperSources If ps.SourceName = Name Then Return ps End If Next Return Nothing End Function Private Sub CreateNewPagesettings() _pagesettings = New MyPageSettings _pagesettings.PrinterSettings = _printersettings Dim tmp As Single = 0.0 If Globalization.RegionInfo.CurrentRegion.IsMetric And _EnableMetric Then Single.TryParse(txtMarginLeft.Text.Trim, tmp) _pagesettings.Margins.LeftMetric = CSng(Math.Round(tmp * 10, 2)) Single.TryParse(txtMarginRight.Text.Trim, tmp) _pagesettings.Margins.RightMetric = CSng(Math.Round(tmp * 10, 2)) Single.TryParse(txtMarginTop.Text.Trim, tmp) _pagesettings.Margins.TopMetric = CSng(Math.Round(tmp * 10, 2)) Single.TryParse(txtMarginBottom.Text.Trim, tmp) _pagesettings.Margins.BottomMetric = CSng(Math.Round(tmp * 10, 2)) Else Single.TryParse(txtMarginLeft.Text.Trim, tmp) _pagesettings.Margins.Left = CSng(Math.Round(tmp * 10, 2)) Single.TryParse(txtMarginRight.Text.Trim, tmp) _pagesettings.Margins.Right = CSng(Math.Round(tmp * 10, 2)) Single.TryParse(txtMarginTop.Text.Trim, tmp) _pagesettings.Margins.Top = CSng(Math.Round(tmp * 10, 2)) Single.TryParse(txtMarginBottom.Text.Trim, tmp) _pagesettings.Margins.Bottom = CSng(Math.Round(tmp * 10, 2)) End If _pagesettings.Landscape = rbtLandscape.Checked If cbxPaperSource.Enabled Then _pagesettings.PaperSource = _ PaperSourceFromName(cbxPaperSource.SelectedItem.ToString) Else _pagesettings.PaperSource = Nothing End If _pagesettings.PaperSize = _ PaperSizeFromName(cbxPaperSize.SelectedItem.ToString) End Sub Private Sub dlgMyPageSetupDialog_Load(ByVal sender As Object, _ ByVal e As System.EventArgs) _ Handles Me.Load ShowPageSettings() End Sub Private Sub pnlPreview_Paint(ByVal sender As Object, _ ByVal e As System.Windows.Forms.PaintEventArgs) _ Handles pnlPreview.Paint Dim docrect As Rectangle = TransformInchToDevice(e.Graphics, _ _pagesettings.Bounds) Dim marrect As Rectangle = TransformInchToDevice(e.Graphics, _ _pagesettings.Margins) Dim fkt As Double If _pagesettings.Landscape Then fkt = docrect.Width / (pnlPreview.Width - 10) Else fkt = docrect.Height / (pnlPreview.Height - 10) End If docrect.Width = CInt(Math.Round(docrect.Width / fkt)) docrect.Height = CInt(Math.Round(docrect.Height / fkt)) marrect.X = CInt(Math.Round(marrect.X / fkt)) marrect.Y = CInt(Math.Round(marrect.Y / fkt)) marrect.Width = CInt(Math.Round(marrect.Width / fkt)) marrect.Height = CInt(Math.Round(marrect.Height / fkt)) Dim offset As Size = New Size(8, 8) If _pagesettings.Landscape Then docrect.Location = New Point(0, _ CInt((pnlPreview.Height - 8 - docrect.Height) / 2) - 3) Else docrect.Location = New Point( _ CInt((pnlPreview.Width - 8 - docrect.Width) / 2) - 3, 0) End If marrect.Size = New Size(docrect.Width - marrect.X - marrect.Width, _ docrect.Height - marrect.Y - marrect.Height) marrect.Location = New Point(marrect.X + docrect.X, _ marrect.Y + docrect.Y) Dim br As Brush = New SolidBrush(SystemColors.ButtonShadow) e.Graphics.FillRectangle(br, _ New Rectangle(docrect.Location + offset, docrect.Size)) br = New SolidBrush(Color.White) e.Graphics.FillRectangle(br, docrect) Dim pn As New Pen(Color.Black) e.Graphics.DrawRectangle(pn, docrect) pn = New Pen(Color.Silver) pn.DashStyle = Drawing2D.DashStyle.Dash e.Graphics.DrawRectangle(pn, marrect) marrect.Location = marrect.Location + New Size(1, 1) marrect.Size = marrect.Size - New Size(2, 2) Dim ptxt As String = _PreviewText & _PreviewText & _PreviewText & _ _PreviewText & _PreviewText & _PreviewText & _ _PreviewText & _PreviewText & _PreviewText e.Graphics.DrawString(ptxt, New Font(New FontFamily("Arial"), 3), _ New SolidBrush(Color.Black), marrect) End Sub Private Function TransformInchToDevice(ByVal gr As Graphics, _ ByVal value As PointF) As Point Dim pt() As PointF = {value} gr.PageUnit = GraphicsUnit.Inch gr.TransformPoints(Drawing2D.CoordinateSpace.Device, _ Drawing2D.CoordinateSpace.Page, pt) Return New Point(CInt(Math.Round(pt(0).X)), CInt(Math.Round(pt(0).Y))) End Function Private Function TransformInchToDevice(ByVal gr As Graphics, _ ByVal value As RectangleF) As Rectangle Dim pt() As PointF = { _ New PointF(value.Location.X / 100, value.Location.Y / 100), _ New PointF(value.Size.Width / 100, value.Size.Height / 100)} gr.PageUnit = GraphicsUnit.Inch gr.TransformPoints(Drawing2D.CoordinateSpace.Device, _ Drawing2D.CoordinateSpace.Page, pt) gr.PageUnit = GraphicsUnit.Pixel Return New Rectangle(CInt(Math.Round(pt(0).X)), _ CInt(Math.Round(pt(0).Y)), _ CInt(Math.Round(pt(1).X)), _ CInt(Math.Round(pt(1).Y))) End Function Private Function TransformInchToDevice(ByVal gr As Graphics, _ ByVal value As MyMargins) As Rectangle Dim pt() As PointF = {New PointF(value.Left / 100, value.Top / 100), _ New PointF(value.Right / 100, value.Bottom / 100)} gr.PageUnit = GraphicsUnit.Inch gr.TransformPoints(Drawing2D.CoordinateSpace.Device, _ Drawing2D.CoordinateSpace.Page, pt) gr.PageUnit = GraphicsUnit.Pixel Return New Rectangle(CInt(Math.Round(pt(0).X)), _ CInt(Math.Round(pt(0).Y)), _ CInt(Math.Round(pt(1).X)), _ CInt(Math.Round(pt(1).Y))) End Function Private Sub cbxPaperSize_SelectedIndexChanged(ByVal sender As Object, _ ByVal e As System.EventArgs) _ Handles cbxPaperSize.SelectedIndexChanged _pagesettings.PaperSize = _ PaperSizeFromName(cbxPaperSize.SelectedItem.ToString) pnlPreview.Invalidate() End Sub Private Sub rbtLandscape_CheckedChanged(ByVal sender As Object, _ ByVal e As System.EventArgs) Handles rbtLandscape.CheckedChanged _pagesettings.Landscape = rbtLandscape.Checked pnlPreview.Invalidate() End Sub Private Sub txtMarginBottom_TextChanged(ByVal sender As Object, _ ByVal e As System.EventArgs) Handles txtMarginBottom.TextChanged Dim tmp As Single Single.TryParse(txtMarginBottom.Text.Trim, tmp) If Globalization.RegionInfo.CurrentRegion.IsMetric And _EnableMetric Then _pagesettings.Margins.BottomMetric = CSng(Math.Round(tmp * 10, 2)) Else _pagesettings.Margins.Bottom = CSng(Math.Round(tmp * 10, 2)) End If pnlPreview.Invalidate() End Sub Private Sub txtMarginLeft_TextChanged(ByVal sender As Object, _ ByVal e As System.EventArgs) Handles txtMarginLeft.TextChanged Dim tmp As Single Single.TryParse(txtMarginLeft.Text.Trim, tmp) If Globalization.RegionInfo.CurrentRegion.IsMetric And _EnableMetric Then _pagesettings.Margins.LeftMetric = CSng(Math.Round(tmp * 10, 2)) Else _pagesettings.Margins.Left = CSng(Math.Round(tmp * 10, 2)) End If pnlPreview.Invalidate() End Sub Private Sub txtMarginRight_TextChanged(ByVal sender As Object, _ ByVal e As System.EventArgs) Handles txtMarginRight.TextChanged Dim tmp As Single Single.TryParse(txtMarginRight.Text.Trim, tmp) If Globalization.RegionInfo.CurrentRegion.IsMetric And _EnableMetric Then _pagesettings.Margins.RightMetric = CSng(Math.Round(tmp * 10, 2)) Else _pagesettings.Margins.Right = CSng(Math.Round(tmp * 10, 2)) End If pnlPreview.Invalidate() End Sub Private Sub txtMarginTop_TextChanged(ByVal sender As Object, _ ByVal e As System.EventArgs) Handles txtMarginTop.TextChanged Dim tmp As Single Single.TryParse(txtMarginTop.Text.Trim, tmp) If Globalization.RegionInfo.CurrentRegion.IsMetric And _EnableMetric Then _pagesettings.Margins.TopMetric = CSng(Math.Round(tmp * 10, 2)) Else _pagesettings.Margins.Top = CSng(Math.Round(tmp * 10, 2)) End If pnlPreview.Invalidate() End Sub End Class ' ############################################################################## ' ########################## dlgMyPrinterSettings.vb ########################### ' ############################################################################## Imports System.Runtime.InteropServices Imports System.Windows.Forms Imports System.Management Public Class dlgMyPrinterSettings Private Declare Function OpenPrinter Lib "winspool.drv" _ Alias "OpenPrinterA" (ByVal pPrinterName As String, _ ByRef phPrinter As IntPtr, _ ByVal pDefault As IntPtr) As Int32 Private Declare Function PrinterProperties Lib "winspool.drv" ( _ ByVal hWnd As IntPtr, ByVal hPrinter As IntPtr) As Int32 Private Declare Function ClosePrinter Lib "winspool.drv" ( _ ByVal hPrinter As IntPtr) As Int32 Private Enum PrinterStatus Sonstiger = 1 Unbekannt = 2 Bereit = 3 Druckt = 4 Aufwärmen = 5 Angehalten = 6 Offline = 7 End Enum Private _PrinterSettings As Printing.PrinterSettings Public Sub New() ' Dieser Aufruf ist für den Windows Form-Designer erforderlich. InitializeComponent() ' Fügen Sie Initialisierungen nach dem InitializeComponent()-Aufruf ' hinzu. For Each s As String In Printing.PrinterSettings.InstalledPrinters cbxPrintername.Items.Add(s) Next End Sub Public Property PrinterSettings() As Printing.PrinterSettings Get Return _PrinterSettings End Get Set(ByVal value As Printing.PrinterSettings) _PrinterSettings = DirectCast(value.Clone, Printing.PrinterSettings) cbxPrintername.SelectedItem = _PrinterSettings.PrinterName End Set End Property Private Sub btnOK_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles btnOK.Click Me.DialogResult = System.Windows.Forms.DialogResult.OK Me.Close() End Sub Private Sub btnCancel_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles btnCancel.Click Me.DialogResult = System.Windows.Forms.DialogResult.Cancel Me.Close() End Sub Private Sub cbxPrintername_SelectedIndexChanged( _ ByVal sender As Object, _ ByVal e As System.EventArgs) _ Handles cbxPrintername.SelectedIndexChanged _PrinterSettings.PrinterName = cbxPrintername.SelectedItem.ToString ShowPrinterStatus() End Sub Private Sub ShowPrinterStatus() Dim sQuery As String = "SELECT * FROM Win32_Printer WHERE Caption='" & _ _PrinterSettings.PrinterName & "'" Dim Printerssearch As New ManagementObjectSearcher(sQuery) Dim printers As ManagementObjectCollection = Printerssearch.Get Dim prtcapt As String For Each prt As ManagementObject In printers prtcapt = prt.GetPropertyValue("Caption").ToString If prtcapt = _PrinterSettings.PrinterName Then lblStatus.Text = "" lblTyp.Text = "" lblLocation.Text = "" lblComment.Text = "" For Each prop As PropertyData In prt.Properties Select Case prop.Name Case "PrinterStatus" If prop.Value IsNot Nothing Then lblStatus.Text = DirectCast(CInt(prop.Value), _ PrinterStatus).ToString End If Case "DriverName" If prop.Value IsNot Nothing Then lblTyp.Text = prop.Value.ToString End If Case "PortName" If prop.Value IsNot Nothing Then lblLocation.Text = prop.Value.ToString End If Case "Comment" If prop.Value IsNot Nothing Then lblComment.Text = prop.Value.ToString End If End Select Next End If Next End Sub Private Sub btnPrinterProperties_Click(ByVal sender As Object, _ ByVal e As System.EventArgs) Handles btnPrinterProperties.Click Dim hPrinter As IntPtr Dim retval As Int32 retval = OpenPrinter(cbxPrintername.SelectedItem.ToString, _ hPrinter, Nothing) retval = PrinterProperties(Me.Handle, hPrinter) retval = ClosePrinter(hPrinter) End Sub End Class ' ############################################################################## ' ############################### frmPSDBug.vb ################################# ' ############################################################################## Imports System.Drawing.Printing Public Class frmPSDBug Private _PageSettings As Printing.PageSettings Private _PrinterSettings As PrinterSettings Private _myPageSettings As MyPageSettings Private Sub Form1_Load(ByVal sender As Object, _ ByVal e As System.EventArgs) Handles Me.Load _PrinterSettings = GetDefaultPrinterSettings() _PageSettings = _PrinterSettings.DefaultPageSettings _myPageSettings = New MyPageSettings(_PrinterSettings) End Sub Private Sub btnPageSetup_Click(ByVal sender As Object, _ ByVal e As System.EventArgs) _ Handles btnPageSetup.Click If rbtOwnDialog.Checked Then Dim pdlg As New MyPageSetupDialog pdlg.EnableMetric = ckbMetric.Checked pdlg.PageSettings = _myPageSettings ShowMyMargins(pdlg.PageSettings.Margins, False) If pdlg.ShowDialog() = Windows.Forms.DialogResult.OK Then _myPageSettings = pdlg.PageSettings End If ShowMyMargins(_myPageSettings.Margins, True) Else Dim pdlg As New PageSetupDialog ShowMargins(_PageSettings.Margins, False) ' alte Seitenränder merken Dim oldMargins As Printing.Margins = _ DirectCast(_PageSettings.Margins.Clone, Printing.Margins) ' mit Korrektur If rbtCorrection.Checked Then CorrectMargins(_PageSettings) End If ' PageSetupDialog initialisieren pdlg.PrinterSettings = _PrinterSettings pdlg.PageSettings = _PageSettings pdlg.EnableMetric = ckbMetric.Checked ' und los geht's If pdlg.ShowDialog() = Windows.Forms.DialogResult.OK Then ' Geänderte Seiteneinstellungen übernehmen _PageSettings = pdlg.PageSettings Else ' Bei Abbruch die nicht "korrigierten" Seitenränder wieder ' zurück schreiben If rbtCorrection.Checked Then _PageSettings.Margins = oldMargins End If End If ShowMargins(pdlg.PageSettings.Margins, True) End If End Sub Private Sub CorrectMargins(ByRef pgs As Printing.PageSettings) If Globalization.RegionInfo.CurrentRegion.IsMetric Then ' Wegen Rundungsfehlern darf nicht durch 0.3948 geteilt werden! Dim fkt As Single = 3.948 pgs.Margins.Left = CInt(Math.Round(pgs.Margins.Left / fkt) * 10) pgs.Margins.Top = CInt(Math.Round(pgs.Margins.Top / fkt) * 10) pgs.Margins.Right = CInt(Math.Round(pgs.Margins.Right / fkt) * 10) pgs.Margins.Bottom = CInt(Math.Round(pgs.Margins.Bottom / fkt) * 10) End If End Sub Private Function GetDefaultPrinterSettings() As Printing.PrinterSettings Dim prs As New Printing.PrinterSettings For Each prtn As String In Printing.PrinterSettings.InstalledPrinters prs.PrinterName = prtn If prs.IsDefaultPrinter Then Return prs End If Next Return Nothing End Function Private Sub ShowMargins(ByVal vMargins As Printing.Margins, _ ByVal after As Boolean) If after Then lblALeft.Text = vMargins.Left.ToString() lblATop.Text = vMargins.Top.ToString() lblARight.Text = vMargins.Right.ToString() lblABottom.Text = vMargins.Bottom.ToString() Else lblBLeft.Text = vMargins.Left.ToString() lblBTop.Text = vMargins.Top.ToString() lblBRight.Text = vMargins.Right.ToString() lblBBottom.Text = vMargins.Bottom.ToString() End If End Sub Private Sub ShowMyMargins(ByVal vMargins As MyMargins, _ ByVal after As Boolean) If after Then lblALeft.Text = vMargins.Left.ToString() lblATop.Text = vMargins.Top.ToString() lblARight.Text = vMargins.Right.ToString() lblABottom.Text = vMargins.Bottom.ToString() Else lblBLeft.Text = vMargins.Left.ToString() lblBTop.Text = vMargins.Top.ToString() lblBRight.Text = vMargins.Right.ToString() lblBBottom.Text = vMargins.Bottom.ToString() End If End Sub Private Sub rbtCorrection_CheckedChanged(ByVal sender As Object, _ ByVal e As System.EventArgs) _ Handles rbtCorrection.CheckedChanged If rbtCorrection.Checked Then ckbMetric.Checked = False ckbMetric.Enabled = False Else ckbMetric.Enabled = True End If End Sub End Class ' ############################################################################## ' ############################### MyMargins.vb ################################# ' ############################################################################## Imports System.ComponentModel Imports System.Xml.Serialization <SerializableAttribute()> _ <TypeConverterAttribute(GetType(MyMarginsConverter))> _ Public Class MyMargins Implements ICloneable Public Enum Units HundredsOfAnInch = 0 TensOfAMillimeter = 1 End Enum Private _Left As Single Private _Right As Single Private _Top As Single Private _Bottom As Single Private _Unit As Units = Units.HundredsOfAnInch Public Sub New() End Sub Public Sub New(ByVal left As Single, ByVal right As Single, _ ByVal top As Single, ByVal bottom As Single) _Left = Math.Abs(left) _Right = Math.Abs(right) _Top = Math.Abs(top) _Bottom = Math.Abs(bottom) End Sub Public Sub New(ByVal margins As Printing.Margins) _Left = margins.Left _Right = margins.Right _Top = margins.Top _Bottom = margins.Bottom End Sub Public Property Left() As Single Get Return _Left End Get Set(ByVal value As Single) _Left = Math.Abs(value) End Set End Property Public Property Right() As Single Get Return _Right End Get Set(ByVal value As Single) _Right = Math.Abs(value) End Set End Property Public Property Top() As Single Get Return _Top End Get Set(ByVal value As Single) _Top = Math.Abs(value) End Set End Property Public Property Bottom() As Single Get Return _Bottom End Get Set(ByVal value As Single) _Bottom = Math.Abs(value) End Set End Property <xmlignore()> _ Public Property LeftMetric() As Single Get Return InchToMetric(_Left) End Get Set(ByVal value As Single) _Left = MetricToInch(Math.Abs(value)) End Set End Property <XmlIgnore()> _ Public Property RightMetric() As Single Get Return InchToMetric(_Right) End Get Set(ByVal value As Single) _Right = MetricToInch(Math.Abs(value)) End Set End Property <XmlIgnore()> _ Public Property TopMetric() As Single Get Return InchToMetric(_Top) End Get Set(ByVal value As Single) _Top = MetricToInch(Math.Abs(value)) End Set End Property <XmlIgnore()> _ Public Property BottomMetric() As Single Get Return InchToMetric(_Bottom) End Get Set(ByVal value As Single) _Bottom = MetricToInch(Math.Abs(value)) End Set End Property Private Function MetricToInch(ByVal value As Single) As Single Return CSng(Math.Round(value * 3.937 / 10, 2)) End Function Private Function InchToMetric(ByVal value As Single) As Single Return CSng(Math.Round(value / 3.937 * 10, 2)) End Function Public Function Clone() As Object Implements System.ICloneable.Clone Dim cln As New MyMargins cln.Left = _Left cln.Right = _Right cln.Top = _Top cln.Bottom = _Bottom Return cln End Function Public Overrides Function Equals(ByVal obj As Object) As Boolean If obj.GetType.Name = "MyMargins" Then Dim vo As MyMargins = DirectCast(obj, MyMargins) If vo.Left = _Left AndAlso vo.Right = _Right _ AndAlso vo.Top = _Top AndAlso vo.Bottom = _Bottom Then Return True End If End If Return False End Function End Class ' ############################################################################## ' ########################### MyMarginsConverter.vb ############################ ' ############################################################################## Imports System.ComponentModel Public Class MyMarginsConverter Inherits ExpandableObjectConverter Public Sub New() MyBase.New() End Sub Public Overrides Function CanConvertFrom (_ ByVal context As System.ComponentModel.ITypeDescriptorContext, _ ByVal sourceType As System.Type) As Boolean If sourceType Is GetType(MyMargins) Then Return True ElseIf sourceType Is GetType(String) Then Return True Else Return MyBase.CanConvertFrom(sourceType) End If End Function Public Overrides Function CanConvertTo( _ ByVal context As System.ComponentModel.ITypeDescriptorContext, _ ByVal destinationType As System.Type) As Boolean If destinationType Is GetType(String) Then Return True End If End Function Public Overrides Function ConvertFrom( _ ByVal context As System.ComponentModel.ITypeDescriptorContext, _ ByVal culture As System.Globalization.CultureInfo, _ ByVal value As Object) As Object If TypeOf value Is Printing.Margins Then Return New MyMargins(DirectCast(value, Printing.Margins)) ElseIf TypeOf value Is String Then Return ObjectFromString(DirectCast(value, String), culture) End If Return MyBase.ConvertFrom(context, culture, value) End Function Public Overrides Function ConvertTo( _ ByVal context As System.ComponentModel.ITypeDescriptorContext, _ ByVal culture As System.Globalization.CultureInfo, _ ByVal value As Object, _ ByVal destinationType As System.Type) As Object If destinationType Is GetType(String) Then Dim src As MyMargins = DirectCast(value, MyMargins) Dim retval As String = "{MyMargins" retval &= " Left=" & src.Left.ToString("g", culture) retval &= " Right=" & src.Right.ToString("g", culture) retval &= " Top=" & src.Top.ToString("g", culture) retval &= " Bottom=" & src.Bottom.ToString("g", culture) Return retval End If Return MyBase.ConvertTo(context, culture, value, destinationType) End Function Public Overloads Function IsValid(ByVal value As Object) As Boolean If TypeOf value Is String Then Dim v As String = DirectCast(value, String) Return v.StartsWith("{MyMargins") And _ v.Contains("Left=") And _ v.Contains("Right=") And _ v.Contains("Top=") And _ v.Contains("Bottom=") ElseIf TypeOf value Is Printing.Margins Then Return True Else Return MyBase.IsValid(value) End If End Function Public Overrides Function IsValid( _ ByVal context As System.ComponentModel.ITypeDescriptorContext, _ ByVal value As Object) As Boolean Return IsValid(value) End Function Private Function ObjectFromString(ByVal value As String, _ ByVal culture As Globalization.CultureInfo) As MyMargins Dim v As String() = _ value.Replace("{", "").Replace("}", "").Split(New Char() {" "c}) Dim mm As New MyMargins If v(0).Trim <> "MyMargins" Then Return Nothing End If For Each s As String In v If s.StartsWith("Left=") Then Single.TryParse(s.Substring(s.IndexOf("=") + 1), _ System.Globalization.NumberStyles.AllowDecimalPoint, _ culture, mm.Left) End If If s.StartsWith("Right=") Then Single.TryParse(s.Substring(s.IndexOf("=") + 1), _ System.Globalization.NumberStyles.AllowDecimalPoint, _ culture, mm.Right) End If If s.StartsWith("Top=") Then Single.TryParse(s.Substring(s.IndexOf("=") + 1), _ System.Globalization.NumberStyles.AllowDecimalPoint, _ culture, mm.Top) End If If s.StartsWith("Bottom=") Then Single.TryParse(s.Substring(s.IndexOf("=") + 1), _ System.Globalization.NumberStyles.AllowDecimalPoint, _ culture, mm.Bottom) End If Next Return mm End Function End Class ' ############################################################################## ' ############################# MyPageSettings.vb ############################## ' ############################################################################## Public Class MyPageSettings Inherits Printing.PageSettings Private _Margins As New MyMargins Public Sub New() MyBase.New() End Sub Public Sub New(ByVal ps As Printing.PrinterSettings) MyBase.New(ps) _Margins = New MyMargins(MyBase.Margins) End Sub Public Overloads Property Margins() As MyMargins Get Return _Margins End Get Set(ByVal value As MyMargins) _Margins = value End Set End Property End Class ' ############################################################################## ' ########################### MyPageSetupDialog.vb ############################# ' ############################################################################## Public Class MyPageSetupDialog Private _PrinterSettings As Printing.PrinterSettings Private _PageSettings As MyPageSettings Private _EnableMetric As Boolean Public Sub New() MyBase.New() InitializeComponent() End Sub Public Function ShowDialog() As DialogResult Dim frmDlg As New dlgMyPageSetupDialog If _PageSettings Is Nothing Then _PageSettings = New MyPageSettings(GetDefaultPrinterSettings()) End If frmDlg.PageSettings = DirectCast(_PageSettings.Clone, MyPageSettings) If _PrinterSettings IsNot Nothing Then frmDlg.PrinterSettings = DirectCast(_PrinterSettings.Clone, _ Printing.PrinterSettings) End If frmDlg.EnableMetric = _EnableMetric Dim dlgresult As DialogResult = frmDlg.ShowDialog() If dlgresult = DialogResult.OK Then _PageSettings = DirectCast(frmDlg.PageSettings.Clone, _ MyPageSettings) _PrinterSettings = _PageSettings.PrinterSettings End If Return dlgresult End Function Private Function GetDefaultPrinterSettings() As Printing.PrinterSettings Dim prs As New Printing.PrinterSettings For Each prtn As String In Printing.PrinterSettings.InstalledPrinters prs.PrinterName = prtn If prs.IsDefaultPrinter Then Return prs End If Next Return Nothing End Function Public Property PageSettings() As MyPageSettings Get Return _PageSettings End Get Set(ByVal value As MyPageSettings) _PageSettings = value End Set End Property Public Property PrinterSettings() As Printing.PrinterSettings Get Return _PrinterSettings End Get Set(ByVal value As Printing.PrinterSettings) _PrinterSettings = value End Set End Property Public Property EnableMetric() As Boolean Get Return _enableMetric End Get Set(ByVal value As Boolean) _enableMetric = value End Set End Property End Class
Ihre Meinung
Falls Sie Fragen zu diesem Artikel haben oder Ihre Erfahrung mit anderen Nutzern austauschen möchten, dann teilen Sie uns diese bitte in einem der unten vorhandenen Themen oder über einen neuen Beitrag mit. Hierzu können sie einfach einen Beitrag in einem zum Thema passenden Forum anlegen, welcher automatisch mit dieser Seite verknüpft wird.