Skip to content

Commit

Permalink
Move common dialogs to CsWin32 and clean printing (dotnet#10471)
Browse files Browse the repository at this point in the history
We can't (yet) directly use CsWin32 directly for the common dialogs due to packing differences between 32 and 64 bit. We target AnyCPU and CsWin32 doesn't have the ability to force a particular platform definition. For now, I'm copying in CsWin32 defines from a platform targetted project.

Hopefully we'll eventually get .NET support for specifying packing per platform. Also investigating getting a feature added to CsWin32 to mitigate this for us.

This does a pass through all of the print code to clean to style guides.

Plan is to follow up with an attempt to update System.Drawing to CsWin32 code.
  • Loading branch information
JeremyKuhne authored Dec 13, 2023
1 parent dbc7ce3 commit fc705dc
Show file tree
Hide file tree
Showing 78 changed files with 2,748 additions and 3,278 deletions.
5 changes: 4 additions & 1 deletion .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ csharp_prefer_braces = true:silent
csharp_style_namespace_declarations = file_scoped:silent
csharp_style_prefer_method_group_conversion = true:silent
csharp_style_prefer_top_level_statements = true:silent
csharp_style_prefer_primary_constructors = true:suggestion
csharp_style_prefer_primary_constructors = true:silent
csharp_style_expression_bodied_lambdas = true:silent
csharp_style_expression_bodied_local_functions = false:silent
csharp_style_allow_embedded_statements_on_same_line_experimental = true:silent
Expand All @@ -187,6 +187,9 @@ csharp_style_deconstructed_variable_declaration = true:suggestion

# Visual Basic files

# SYSLIB1054: Use 'LibraryImportAttribute' instead of 'DllImportAttribute' to generate P/Invoke marshalling code at compile time
dotnet_diagnostic.SYSLIB1054.severity = none

[*.vb]
# Modifier preferences
visual_basic_preferred_modifier_order = Partial,Default,Private,Protected,Public,Friend,NotOverridable,Overridable,MustOverride,Overloads,Overrides,MustInherit,NotInheritable,Static,Shared,Shadows,ReadOnly,WriteOnly,Dim,Const,WithEvents,Widening,Narrowing,Custom,Async:suggestion
Expand Down
6 changes: 6 additions & 0 deletions src/System.Drawing.Common/src/System.Drawing.Common.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ Since .NET 7, non-Windows platforms are not supported, even with the runtime con
<Compile Include="System\Drawing\Printing\PrintEventHandler.cs" />
<Compile Include="System\Drawing\Printing\PrintAction.cs" />
<Compile Include="System\Drawing\Printing\PrintController.cs" />
<Compile Include="System\Drawing\Printing\PrintController.SafeDeviceModeHandle.cs" />
<Compile Include="System\Drawing\Printing\PrintPageEventHandler.cs" />
<Compile Include="System\Drawing\Printing\QueryPageSettingsEventArgs.cs" />
<Compile Include="System\Drawing\Printing\QueryPageSettingsEventHandler.cs" />
Expand Down Expand Up @@ -221,6 +222,11 @@ Since .NET 7, non-Windows platforms are not supported, even with the runtime con
<Compile Include="System\Drawing\Printing\PageSettings.cs" />
<Compile Include="System\Drawing\Printing\PrintDocument.cs" />
<Compile Include="System\Drawing\Printing\PrinterSettings.cs" />
<Compile Include="System\Drawing\Printing\PrinterSettings.ArrayEnumerator.cs" />
<Compile Include="System\Drawing\Printing\PrinterSettings.PaperSizeCollection.cs" />
<Compile Include="System\Drawing\Printing\PrinterSettings.PaperSourceCollection.cs" />
<Compile Include="System\Drawing\Printing\PrinterSettings.PrinterResolutionCollection.cs" />
<Compile Include="System\Drawing\Printing\PrinterSettings.StringCollection.cs" />
<Compile Include="System\Drawing\Printing\PrintEventArgs.cs" />
<Compile Include="System\Drawing\Printing\PrintPageEventArgs.cs" />
<Compile Include="System\Drawing\Printing\PrintPreviewGraphics.cs" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,53 +9,47 @@
namespace System.Drawing.Printing;

/// <summary>
/// Specifies a print controller that sends information to a printer.
/// Specifies a print controller that sends information to a printer.
/// </summary>
public class StandardPrintController : PrintController
{
private DeviceContext? _dc;
private Graphics? _graphics;

/// <summary>
/// Implements StartPrint for printing to a physical printer.
/// Implements StartPrint for printing to a physical printer.
/// </summary>
public override void OnStartPrint(PrintDocument document, PrintEventArgs e)
{
Debug.Assert(_dc is null && _graphics is null, "PrintController methods called in the wrong order?");

base.OnStartPrint(document, e);
// the win32 methods below SuppressUnmanagedCodeAttributes so assertin on UnmanagedCodePermission is redundant

if (!document.PrinterSettings.IsValid)
throw new InvalidPrinterException(document.PrinterSettings);

Debug.Assert(_modeHandle is not null, "_modeHandle should have been set by PrintController.OnStartPrint");
_dc = document.PrinterSettings.CreateDeviceContext(_modeHandle);
Gdi32.DOCINFO info = new Gdi32.DOCINFO();
info.lpszDocName = document.DocumentName;
if (document.PrinterSettings.PrintToFile)
info.lpszOutput = document.PrinterSettings.OutputPort; // This will be "FILE:"
else
info.lpszOutput = null;
info.lpszDatatype = null;
info.fwType = 0;

Gdi32.DOCINFO info = new()
{
lpszDocName = document.DocumentName,
lpszDatatype = null,
fwType = 0,
// Print to file is "FILE:"
lpszOutput = document.PrinterSettings.PrintToFile ? document.PrinterSettings.OutputPort : null
};

int result = Gdi32.StartDoc(new HandleRef(_dc, _dc.Hdc), info);
if (result <= 0)
{
int error = Marshal.GetLastPInvokeError();
if (error == SafeNativeMethods.ERROR_CANCELLED)
{
e.Cancel = true;
}
else
{
throw new Win32Exception(error);
}
e.Cancel = error == SafeNativeMethods.ERROR_CANCELLED ? true : throw new Win32Exception(error);
}
}

/// <summary>
/// Implements StartPage for printing to a physical printer.
/// Implements StartPage for printing to a physical printer.
/// </summary>
public override Graphics OnStartPage(PrintDocument document, PrintPageEventArgs e)
{
Expand All @@ -79,9 +73,7 @@ public override Graphics OnStartPage(PrintDocument document, PrintPageEventArgs

if (document.OriginAtMargins)
{
// Adjust the origin of the graphics object to be at the
// user-specified margin location
//
// Adjust the origin of the graphics object to be at the user-specified margin location.
int dpiX = Gdi32.GetDeviceCaps(new HandleRef(_dc, _dc.Hdc), Gdi32.DeviceCapability.LOGPIXELSX);
int dpiY = Gdi32.GetDeviceCaps(new HandleRef(_dc, _dc.Hdc), Gdi32.DeviceCapability.LOGPIXELSY);
int hardMarginX_DU = Gdi32.GetDeviceCaps(new HandleRef(_dc, _dc.Hdc), Gdi32.DeviceCapability.PHYSICALOFFSETX);
Expand All @@ -94,13 +86,11 @@ public override Graphics OnStartPage(PrintDocument document, PrintPageEventArgs
}

int result2 = Gdi32.StartPage(new HandleRef(_dc, _dc.Hdc));
if (result2 <= 0)
throw new Win32Exception();
return _graphics;
return result2 <= 0 ? throw new Win32Exception() : _graphics;
}

/// <summary>
/// Implements EndPage for printing to a physical printer.
/// Implements EndPage for printing to a physical printer.
/// </summary>
public override void OnEndPage(PrintDocument document, PrintPageEventArgs e)
{
Expand All @@ -110,7 +100,9 @@ public override void OnEndPage(PrintDocument document, PrintPageEventArgs e)
{
int result = Gdi32.EndPage(new HandleRef(_dc, _dc.Hdc));
if (result <= 0)
{
throw new Win32Exception();
}
}
finally
{
Expand All @@ -122,7 +114,7 @@ public override void OnEndPage(PrintDocument document, PrintPageEventArgs e)
}

/// <summary>
/// Implements EndPrint for printing to a physical printer.
/// Implements EndPrint for printing to a physical printer.
/// </summary>
public override void OnEndPrint(PrintDocument document, PrintEventArgs e)
{
Expand Down
12 changes: 6 additions & 6 deletions src/System.Drawing.Common/src/System/Drawing/Printing/Duplex.cs
Original file line number Diff line number Diff line change
@@ -1,30 +1,30 @@
// Licensed to the .NET Foundation under one or more agreements.
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

namespace System.Drawing.Printing;

/// <summary>
/// Specifies the printer's duplex setting.
/// Specifies the printer's duplex setting.
/// </summary>
public enum Duplex
{
/// <summary>
/// The printer's default duplex setting.
/// The printer's default duplex setting.
/// </summary>
Default = -1,

/// <summary>
/// Single-sided printing.
/// Single-sided printing.
/// </summary>
Simplex = SafeNativeMethods.DMDUP_SIMPLEX,

/// <summary>
/// Double-sided, horizontal printing.
/// Double-sided, horizontal printing.
/// </summary>
Horizontal = SafeNativeMethods.DMDUP_HORIZONTAL,

/// <summary>
/// Double-sided, vertical printing.
/// Double-sided, vertical printing.
/// </summary>
Vertical = SafeNativeMethods.DMDUP_VERTICAL,
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,6 @@

using System.Runtime.Serialization;

/*
* This file is not intended to be used by Mono.
* Instead InvalidPrinterException.Serializable.cs should be used.
*/

namespace System.Drawing.Printing;

[Runtime.CompilerServices.TypeForwardedFrom(AssemblyRef.SystemDrawing)]
Expand All @@ -18,7 +13,7 @@ public partial class InvalidPrinterException
#endif
protected InvalidPrinterException(SerializationInfo info, StreamingContext context) : base(info, context)
{
// Ignoring not deserializable input
// Ignoring not serializable input
}

#if NET8_0_OR_GREATER
Expand Down
Original file line number Diff line number Diff line change
@@ -1,23 +1,22 @@
// Licensed to the .NET Foundation under one or more agreements.
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Security;

namespace System.Drawing.Printing;

/// <summary>
/// Represents the exception that is thrown when trying to access a printer using invalid printer settings.
/// Represents the exception that is thrown when trying to access a printer using invalid printer settings.
/// </summary>
[Serializable]
public partial class InvalidPrinterException : SystemException
{
private readonly PrinterSettings? _settings;

/// <summary>
/// Initializes a new instance of the <see cref='InvalidPrinterException'/> class.
/// Initializes a new instance of the <see cref='InvalidPrinterException'/> class.
/// </summary>
public InvalidPrinterException(PrinterSettings settings)
: base(GenerateMessage(settings))
public InvalidPrinterException(PrinterSettings settings) : base(GenerateMessage(settings))
{
_settings = settings;
}
Expand Down
Loading

0 comments on commit fc705dc

Please sign in to comment.