diff --git a/Directory.Build.targets b/Directory.Build.targets index 414537d3e72..9e33ec38ca8 100644 --- a/Directory.Build.targets +++ b/Directory.Build.targets @@ -17,7 +17,9 @@ - x64;x86 + AnyCPU;x86 + x86 + x64;x86 diff --git a/src/System.Windows.Forms.Primitives/src/Interop/Comdlg32/Interop.PrintDlg.cs b/src/System.Windows.Forms.Primitives/src/Interop/Comdlg32/Interop.PrintDlg.cs new file mode 100644 index 00000000000..ef5d5b11efe --- /dev/null +++ b/src/System.Windows.Forms.Primitives/src/Interop/Comdlg32/Interop.PrintDlg.cs @@ -0,0 +1,42 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Runtime.InteropServices; + +internal partial class Interop +{ + internal partial class Comdlg32 + { + [DllImport(ExternDll.Comdlg32, ExactSpelling = true, SetLastError = true, CharSet = CharSet.Unicode)] + private static extern BOOL PrintDlgW(ref PRINTDLGW_32 lppd); + + [DllImport(ExternDll.Comdlg32, ExactSpelling = true, SetLastError = true, CharSet = CharSet.Unicode)] + private static extern BOOL PrintDlgW(ref PRINTDLGW_64 lppd); + + public static BOOL PrintDlg(ref PRINTDLGW lppd) + { + if (IntPtr.Size == 4) + { + if (lppd is PRINTDLGW_32 lppd32) + { + BOOL result = PrintDlgW(ref lppd32); + lppd = lppd32; + return result; + } + + throw new InvalidOperationException($"Expected {nameof(PRINTDLGW_32)} data struct"); + } + + if (lppd is PRINTDLGW_64 lppd64) + { + BOOL result = PrintDlgW(ref lppd64); + lppd = lppd64; + return result; + } + + throw new InvalidOperationException($"Expected {nameof(PRINTDLGW_64)} data struct"); + } + } +} diff --git a/src/System.Windows.Forms.Primitives/src/Interop/Comdlg32/Interop.PrintDlgW.cs b/src/System.Windows.Forms.Primitives/src/Interop/Comdlg32/Interop.PrintDlgW.cs new file mode 100644 index 00000000000..7e995c74886 --- /dev/null +++ b/src/System.Windows.Forms.Primitives/src/Interop/Comdlg32/Interop.PrintDlgW.cs @@ -0,0 +1,134 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Runtime.InteropServices; +using static Interop.User32; + +internal partial class Interop +{ + internal partial class Comdlg32 + { + // Any change in PRINTDLG_32, should also be in PRINTDLG and PRINTDLG_64 + // x86 requires EXPLICIT packing of 1. + + public unsafe interface PRINTDLGW + { + uint lStructSize { get; set; } + + IntPtr hwndOwner { get; set; } + IntPtr hDevMode { get; set; } + IntPtr hDevNames { get; set; } + IntPtr hDC { get; set; } + + PD Flags { get; set; } + + ushort nFromPage { get; set; } + ushort nToPage { get; set; } + ushort nMinPage { get; set; } + ushort nMaxPage { get; set; } + ushort nCopies { get; set; } + + IntPtr hInstance { get; set; } + IntPtr lCustData { get; set; } + + IntPtr lpfnPrintHook { get; set; } + IntPtr lpfnSetupHook { get; set; } + + char* lpPrintTemplateName { get; set; } + char* lpSetupTemplateName { get; set; } + + IntPtr hPrintTemplate { get; set; } + IntPtr hSetupTemplate { get; set; } + } + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode, Pack = 1)] + public unsafe struct PRINTDLGW_32 : PRINTDLGW + { + public uint _lStructSize; + public IntPtr _hwndOwner; + public IntPtr _hDevMode; + public IntPtr _hDevNames; + public IntPtr _hDC; + public PD _flags; + public ushort _nFromPage; + public ushort _nToPage; + public ushort _nMinPage; + public ushort _nMaxPage; + public ushort _nCopies; + public IntPtr _hInstance; + public IntPtr _lCustData; + public IntPtr _lpfnPrintHook; + public IntPtr _lpfnSetupHook; + public char* _lpPrintTemplateName; + public char* _lpSetupTemplateName; + public IntPtr _hPrintTemplate; + public IntPtr _hSetupTemplate; + + public uint lStructSize { get => _lStructSize; set => _lStructSize = value; } + public IntPtr hwndOwner { get => _hwndOwner; set => _hwndOwner = value; } + public IntPtr hDevMode { get => _hDevMode; set => _hDevMode = value; } + public IntPtr hDevNames { get => _hDevNames; set => _hDevNames = value; } + public IntPtr hDC { get => _hDC; set => _hDC = value; } + public PD Flags { get => _flags; set => _flags = value; } + public ushort nFromPage { get => _nFromPage; set => _nFromPage = value; } + public ushort nToPage { get => _nToPage; set => _nToPage = value; } + public ushort nMinPage { get => _nMinPage; set => _nMinPage = value; } + public ushort nMaxPage { get => _nMaxPage; set => _nMaxPage = value; } + public ushort nCopies { get => _nCopies; set => _nCopies = value; } + public IntPtr hInstance { get => _hInstance; set => _hInstance = value; } + public IntPtr lCustData { get => _lCustData; set => _lCustData = value; } + public IntPtr lpfnPrintHook { get => _lpfnPrintHook; set => _lpfnPrintHook = value; } + public IntPtr lpfnSetupHook { get => _lpfnSetupHook; set => _lpfnSetupHook = value; } + public char* lpPrintTemplateName { get => _lpPrintTemplateName; set => _lpPrintTemplateName = value; } + public char* lpSetupTemplateName { get => _lpSetupTemplateName; set => _lpSetupTemplateName = value; } + public IntPtr hPrintTemplate { get => _hPrintTemplate; set => _hPrintTemplate = value; } + public IntPtr hSetupTemplate { get => _hSetupTemplate; set => _hSetupTemplate = value; } + } + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] + public unsafe struct PRINTDLGW_64 : PRINTDLGW + { + public uint _lStructSize; + public IntPtr _hwndOwner; + public IntPtr _hDevMode; + public IntPtr _hDevNames; + public IntPtr _hDC; + public PD _flags; + public ushort _nFromPage; + public ushort _nToPage; + public ushort _nMinPage; + public ushort _nMaxPage; + public ushort _nCopies; + public IntPtr _hInstance; + public IntPtr _lCustData; + public IntPtr _lpfnPrintHook; + public IntPtr _lpfnSetupHook; + public char* _lpPrintTemplateName; + public char* _lpSetupTemplateName; + public IntPtr _hPrintTemplate; + public IntPtr _hSetupTemplate; + + public uint lStructSize { get => _lStructSize; set => _lStructSize = value; } + public IntPtr hwndOwner { get => _hwndOwner; set => _hwndOwner = value; } + public IntPtr hDevMode { get => _hDevMode; set => _hDevMode = value; } + public IntPtr hDevNames { get => _hDevNames; set => _hDevNames = value; } + public IntPtr hDC { get => _hDC; set => _hDC = value; } + public PD Flags { get => _flags; set => _flags = value; } + public ushort nFromPage { get => _nFromPage; set => _nFromPage = value; } + public ushort nToPage { get => _nToPage; set => _nToPage = value; } + public ushort nMinPage { get => _nMinPage; set => _nMinPage = value; } + public ushort nMaxPage { get => _nMaxPage; set => _nMaxPage = value; } + public ushort nCopies { get => _nCopies; set => _nCopies = value; } + public IntPtr hInstance { get => _hInstance; set => _hInstance = value; } + public IntPtr lCustData { get => _lCustData; set => _lCustData = value; } + public IntPtr lpfnPrintHook { get => _lpfnPrintHook; set => _lpfnPrintHook = value; } + public IntPtr lpfnSetupHook { get => _lpfnSetupHook; set => _lpfnSetupHook = value; } + public char* lpPrintTemplateName { get => _lpPrintTemplateName; set => _lpPrintTemplateName = value; } + public char* lpSetupTemplateName { get => _lpSetupTemplateName; set => _lpSetupTemplateName = value; } + public IntPtr hPrintTemplate { get => _hPrintTemplate; set => _hPrintTemplate = value; } + public IntPtr hSetupTemplate { get => _hSetupTemplate; set => _hSetupTemplate = value; } + } + } +} diff --git a/src/System.Windows.Forms.Primitives/src/System/Windows/Forms/Internals/NativeMethods.cs b/src/System.Windows.Forms.Primitives/src/System/Windows/Forms/Internals/NativeMethods.cs index f4a730d300a..438fa06a647 100644 --- a/src/System.Windows.Forms.Primitives/src/System/Windows/Forms/Internals/NativeMethods.cs +++ b/src/System.Windows.Forms.Primitives/src/System/Windows/Forms/Internals/NativeMethods.cs @@ -210,153 +210,6 @@ public class EDITSTREAM64 public delegate int TreeViewCompareCallback(IntPtr lParam1, IntPtr lParam2, IntPtr lParamSort); - // Any change in PRINTDLG, should also be in PRINTDLG_32 and PRINTDLG_64 - public interface PRINTDLG - { - int lStructSize { get; set; } - - IntPtr hwndOwner { get; set; } - IntPtr hDevMode { get; set; } - IntPtr hDevNames { get; set; } - IntPtr hDC { get; set; } - - Comdlg32.PD Flags { get; set; } - - short nFromPage { get; set; } - short nToPage { get; set; } - short nMinPage { get; set; } - short nMaxPage { get; set; } - short nCopies { get; set; } - - IntPtr hInstance { get; set; } - IntPtr lCustData { get; set; } - - WndProc lpfnPrintHook { get; set; } - WndProc lpfnSetupHook { get; set; } - - string lpPrintTemplateName { get; set; } - string lpSetupTemplateName { get; set; } - - IntPtr hPrintTemplate { get; set; } - IntPtr hSetupTemplate { get; set; } - } - - // Any change in PRINTDLG_32, should also be in PRINTDLG and PRINTDLG_64 - // x86 requires EXPLICIT packing of 1. - [StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Auto)] - public class PRINTDLG_32 : PRINTDLG - { - int m_lStructSize; - - IntPtr m_hwndOwner; - IntPtr m_hDevMode; - IntPtr m_hDevNames; - IntPtr m_hDC; - - short m_nFromPage; - short m_nToPage; - short m_nMinPage; - short m_nMaxPage; - short m_nCopies; - - IntPtr m_hInstance; - IntPtr m_lCustData; - - WndProc m_lpfnPrintHook; - WndProc m_lpfnSetupHook; - - string m_lpPrintTemplateName; - string m_lpSetupTemplateName; - - IntPtr m_hPrintTemplate; - IntPtr m_hSetupTemplate; - - public int lStructSize { get { return m_lStructSize; } set { m_lStructSize = value; } } - - public IntPtr hwndOwner { get { return m_hwndOwner; } set { m_hwndOwner = value; } } - public IntPtr hDevMode { get { return m_hDevMode; } set { m_hDevMode = value; } } - public IntPtr hDevNames { get { return m_hDevNames; } set { m_hDevNames = value; } } - public IntPtr hDC { get { return m_hDC; } set { m_hDC = value; } } - - public Comdlg32.PD Flags { get; set; } - - public short nFromPage { get { return m_nFromPage; } set { m_nFromPage = value; } } - public short nToPage { get { return m_nToPage; } set { m_nToPage = value; } } - public short nMinPage { get { return m_nMinPage; } set { m_nMinPage = value; } } - public short nMaxPage { get { return m_nMaxPage; } set { m_nMaxPage = value; } } - public short nCopies { get { return m_nCopies; } set { m_nCopies = value; } } - - public IntPtr hInstance { get { return m_hInstance; } set { m_hInstance = value; } } - public IntPtr lCustData { get { return m_lCustData; } set { m_lCustData = value; } } - - public WndProc lpfnPrintHook { get { return m_lpfnPrintHook; } set { m_lpfnPrintHook = value; } } - public WndProc lpfnSetupHook { get { return m_lpfnSetupHook; } set { m_lpfnSetupHook = value; } } - - public string lpPrintTemplateName { get { return m_lpPrintTemplateName; } set { m_lpPrintTemplateName = value; } } - public string lpSetupTemplateName { get { return m_lpSetupTemplateName; } set { m_lpSetupTemplateName = value; } } - - public IntPtr hPrintTemplate { get { return m_hPrintTemplate; } set { m_hPrintTemplate = value; } } - public IntPtr hSetupTemplate { get { return m_hSetupTemplate; } set { m_hSetupTemplate = value; } } - } - - // Any change in PRINTDLG_64, should also be in PRINTDLG_32 and PRINTDLG - // x64 does not require EXPLICIT packing of 1. - [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] - public class PRINTDLG_64 : PRINTDLG - { - int m_lStructSize; - - IntPtr m_hwndOwner; - IntPtr m_hDevMode; - IntPtr m_hDevNames; - IntPtr m_hDC; - - short m_nFromPage; - short m_nToPage; - short m_nMinPage; - short m_nMaxPage; - short m_nCopies; - - IntPtr m_hInstance; - IntPtr m_lCustData; - - WndProc m_lpfnPrintHook; - WndProc m_lpfnSetupHook; - - string m_lpPrintTemplateName; - string m_lpSetupTemplateName; - - IntPtr m_hPrintTemplate; - IntPtr m_hSetupTemplate; - - public int lStructSize { get { return m_lStructSize; } set { m_lStructSize = value; } } - - public IntPtr hwndOwner { get { return m_hwndOwner; } set { m_hwndOwner = value; } } - public IntPtr hDevMode { get { return m_hDevMode; } set { m_hDevMode = value; } } - public IntPtr hDevNames { get { return m_hDevNames; } set { m_hDevNames = value; } } - public IntPtr hDC { get { return m_hDC; } set { m_hDC = value; } } - - public Comdlg32.PD Flags { get; set; } - - public short nFromPage { get { return m_nFromPage; } set { m_nFromPage = value; } } - public short nToPage { get { return m_nToPage; } set { m_nToPage = value; } } - public short nMinPage { get { return m_nMinPage; } set { m_nMinPage = value; } } - public short nMaxPage { get { return m_nMaxPage; } set { m_nMaxPage = value; } } - public short nCopies { get { return m_nCopies; } set { m_nCopies = value; } } - - public IntPtr hInstance { get { return m_hInstance; } set { m_hInstance = value; } } - public IntPtr lCustData { get { return m_lCustData; } set { m_lCustData = value; } } - - public WndProc lpfnPrintHook { get { return m_lpfnPrintHook; } set { m_lpfnPrintHook = value; } } - public WndProc lpfnSetupHook { get { return m_lpfnSetupHook; } set { m_lpfnSetupHook = value; } } - - public string lpPrintTemplateName { get { return m_lpPrintTemplateName; } set { m_lpPrintTemplateName = value; } } - public string lpSetupTemplateName { get { return m_lpSetupTemplateName; } set { m_lpSetupTemplateName = value; } } - - public IntPtr hPrintTemplate { get { return m_hPrintTemplate; } set { m_hPrintTemplate = value; } } - public IntPtr hSetupTemplate { get { return m_hSetupTemplate; } set { m_hSetupTemplate = value; } } - } - [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] public class PRINTDLGEX { diff --git a/src/System.Windows.Forms.Primitives/src/System/Windows/Forms/Internals/UnsafeNativeMethods.cs b/src/System.Windows.Forms.Primitives/src/System/Windows/Forms/Internals/UnsafeNativeMethods.cs index 49a51d67bc3..3649a7f6f2d 100644 --- a/src/System.Windows.Forms.Primitives/src/System/Windows/Forms/Internals/UnsafeNativeMethods.cs +++ b/src/System.Windows.Forms.Primitives/src/System/Windows/Forms/Internals/UnsafeNativeMethods.cs @@ -18,32 +18,6 @@ internal static class UnsafeNativeMethods [DllImport(ExternDll.Kernel32, CharSet = CharSet.Auto)] public static extern int GetLocaleInfo(uint Locale, int LCType, StringBuilder lpLCData, int cchData); - [DllImport(ExternDll.Comdlg32, EntryPoint = "PrintDlg", SetLastError = true, CharSet = CharSet.Auto)] - public static extern bool PrintDlg_32([In, Out] NativeMethods.PRINTDLG_32 lppd); - - [DllImport(ExternDll.Comdlg32, EntryPoint = "PrintDlg", SetLastError = true, CharSet = CharSet.Auto)] - public static extern bool PrintDlg_64([In, Out] NativeMethods.PRINTDLG_64 lppd); - - public static bool PrintDlg([In, Out] NativeMethods.PRINTDLG lppd) - { - if (IntPtr.Size == 4) - { - if (!(lppd is NativeMethods.PRINTDLG_32 lppd_32)) - { - throw new NullReferenceException("PRINTDLG data is null"); - } - return PrintDlg_32(lppd_32); - } - else - { - if (!(lppd is NativeMethods.PRINTDLG_64 lppd_64)) - { - throw new NullReferenceException("PRINTDLG data is null"); - } - return PrintDlg_64(lppd_64); - } - } - [DllImport(ExternDll.Comdlg32, SetLastError = true, CharSet = CharSet.Auto)] public static extern HRESULT PrintDlgEx([In, Out] NativeMethods.PRINTDLGEX lppdex); diff --git a/src/System.Windows.Forms.Primitives/tests/Interop/Comdlg32/PRINTDLGWTests.cs b/src/System.Windows.Forms.Primitives/tests/Interop/Comdlg32/PRINTDLGWTests.cs new file mode 100644 index 00000000000..9414aef7ea8 --- /dev/null +++ b/src/System.Windows.Forms.Primitives/tests/Interop/Comdlg32/PRINTDLGWTests.cs @@ -0,0 +1,83 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Runtime.InteropServices; +using Xunit; +using static Interop.Comdlg32; + +namespace System.Windows.Forms.Primitives.Tests.Interop.Comdlg32 +{ + public class PRINTDLGWTests : IClassFixture + { + public static bool Is32bit => IntPtr.Size == 4; + public static bool Is64bit => IntPtr.Size == 8; + + [ConditionalFact(nameof(Is32bit))] + public unsafe void PRINTDLGW_32_Size() + { + Assert.Equal(66, sizeof(PRINTDLGW_32)); + } + + [ConditionalFact(nameof(Is32bit))] + public unsafe void PRINTDLGW_32_ensure_layout() + { + PRINTDLGW_32 sut = new PRINTDLGW_32(); + byte* addr = (byte*)&sut; + + Assert.Equal(0, (byte*)&sut._lStructSize - addr); // 4, DWORD + Assert.Equal(4, (byte*)&sut._hwndOwner - addr); // 4, HWND + Assert.Equal(8, (byte*)&sut._hDevMode - addr); // 4, HGLOBAL + Assert.Equal(12, (byte*)&sut._hDevNames - addr); // 4, HGLOBAL + Assert.Equal(16, (byte*)&sut._hDC - addr); // 4, HDC + Assert.Equal(20, (byte*)&sut._flags - addr); // 4, DWORD + Assert.Equal(24, (byte*)&sut._nFromPage - addr); // 2, WORD + Assert.Equal(26, (byte*)&sut._nToPage - addr); // 2, WORD + Assert.Equal(28, (byte*)&sut._nMinPage - addr); // 2, WORD + Assert.Equal(30, (byte*)&sut._nMaxPage - addr); // 2, WORD + Assert.Equal(32, (byte*)&sut._nCopies - addr); // 2, WORD + Assert.Equal(34, (byte*)&sut._hInstance - addr); // 4, HINSTANCE + Assert.Equal(38, (byte*)&sut._lCustData - addr); // 4, LPARAM + Assert.Equal(42, (byte*)&sut._lpfnPrintHook - addr); // 4, LPPRINTHOOKPROC + Assert.Equal(46, (byte*)&sut._lpfnSetupHook - addr); // 4, LPSETUPHOOKPROC + Assert.Equal(50, (byte*)&sut._lpPrintTemplateName - addr); // 4, LPCWSTR + Assert.Equal(54, (byte*)&sut._lpSetupTemplateName - addr); // 4, LPCWSTR + Assert.Equal(58, (byte*)&sut._hPrintTemplate - addr); // 4, HGLOBAL + Assert.Equal(62, (byte*)&sut._hSetupTemplate - addr); // 4, HGLOBAL + } + + [ConditionalFact(nameof(Is64bit))] + public unsafe void PRINTDLGW_64_Size() + { + Assert.Equal(120, sizeof(PRINTDLGW_64)); + } + + [ConditionalFact(nameof(Is64bit))] + public unsafe void PRINTDLGW_64_ensure_layout() + { + PRINTDLGW_64 sut = new PRINTDLGW_64(); + byte* addr = (byte*)&sut; + + Assert.Equal(0, (byte*)&sut._lStructSize - addr); // 8, DWORD + Assert.Equal(8, (byte*)&sut._hwndOwner - addr); // 8, HWND + Assert.Equal(16, (byte*)&sut._hDevMode - addr); // 8, HGLOBAL + Assert.Equal(24, (byte*)&sut._hDevNames - addr); // 8, HGLOBAL + Assert.Equal(32, (byte*)&sut._hDC - addr); // 8, HDC + Assert.Equal(40, (byte*)&sut._flags - addr); // 8, DWORD + Assert.Equal(44, (byte*)&sut._nFromPage - addr); // 2, WORD + Assert.Equal(46, (byte*)&sut._nToPage - addr); // 2, WORD + Assert.Equal(48, (byte*)&sut._nMinPage - addr); // 2, WORD + Assert.Equal(50, (byte*)&sut._nMaxPage - addr); // 2, WORD + Assert.Equal(52, (byte*)&sut._nCopies - addr); // 2, WORD + // 2 bytes alignment 54 -> 56 + Assert.Equal(56, (byte*)&sut._hInstance - addr); // 8, HINSTANCE + Assert.Equal(64, (byte*)&sut._lCustData - addr); // 8, LPARAM + Assert.Equal(72, (byte*)&sut._lpfnPrintHook - addr); // 8, LPPRINTHOOKPROC + Assert.Equal(80, (byte*)&sut._lpfnSetupHook - addr); // 8, LPSETUPHOOKPROC + Assert.Equal(88, (byte*)&sut._lpPrintTemplateName - addr); // 8, LPCWSTR + Assert.Equal(96, (byte*)&sut._lpSetupTemplateName - addr); // 8, LPCWSTR + Assert.Equal(104, (byte*)&sut._hPrintTemplate - addr); // 8, HGLOBAL + Assert.Equal(112, (byte*)&sut._hSetupTemplate - addr); // 8, HGLOBAL + } + } +} diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/Printing/PrintDialog.cs b/src/System.Windows.Forms/src/System/Windows/Forms/Printing/PrintDialog.cs index 436618c6037..9cf42877805 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/Printing/PrintDialog.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/Printing/PrintDialog.cs @@ -291,40 +291,6 @@ public override void Reset() showNetwork = true; } - // Create a PRINTDLG with a few useful defaults. - internal static NativeMethods.PRINTDLG CreatePRINTDLG() - { - NativeMethods.PRINTDLG data = null; - if (IntPtr.Size == 4) - { - data = new NativeMethods.PRINTDLG_32(); - } - else - { - data = new NativeMethods.PRINTDLG_64(); - } - data.lStructSize = Marshal.SizeOf(data); - data.hwndOwner = IntPtr.Zero; - data.hDevMode = IntPtr.Zero; - data.hDevNames = IntPtr.Zero; - data.Flags = 0; - data.hDC = IntPtr.Zero; - data.nFromPage = 1; - data.nToPage = 1; - data.nMinPage = 0; - data.nMaxPage = 9999; - data.nCopies = 1; - data.hInstance = IntPtr.Zero; - data.lCustData = IntPtr.Zero; - data.lpfnPrintHook = null; - data.lpfnSetupHook = null; - data.lpPrintTemplateName = null; - data.lpSetupTemplateName = null; - data.hPrintTemplate = IntPtr.Zero; - data.hSetupTemplate = IntPtr.Zero; - return data; - } - internal static NativeMethods.PRINTDLGEX CreatePRINTDLGEX() { NativeMethods.PRINTDLGEX data = new NativeMethods.PRINTDLGEX(); @@ -353,26 +319,43 @@ internal static NativeMethods.PRINTDLGEX CreatePRINTDLGEX() protected override bool RunDialog(IntPtr hwndOwner) { - var hookProcPtr = new NativeMethods.WndProc(HookProc); - if (!UseEXDialog) { - NativeMethods.PRINTDLG data = CreatePRINTDLG(); - return ShowPrintDialog(hwndOwner, hookProcPtr, data); + return ShowPrintDialog(hwndOwner); + } + + NativeMethods.PRINTDLGEX data = CreatePRINTDLGEX(); + return ShowPrintDialog(hwndOwner, data); + } + + private unsafe bool ShowPrintDialog(IntPtr hwndOwner) + { + PRINTDLGW data; + if (IntPtr.Size == 4) + { + data = new PRINTDLGW_32 + { + lStructSize = (uint)sizeof(PRINTDLGW_32) + }; } else { - NativeMethods.PRINTDLGEX data = CreatePRINTDLGEX(); - return ShowPrintDialog(hwndOwner, data); + data = new PRINTDLGW_64 + { + lStructSize = (uint)sizeof(PRINTDLGW_64) + }; } - } - private bool ShowPrintDialog(IntPtr hwndOwner, NativeMethods.WndProc hookProcPtr, NativeMethods.PRINTDLG data) - { + data.nFromPage = 1; + data.nToPage = 1; + data.nMinPage = 0; + data.nMaxPage = 9999; data.Flags = GetFlags(); - data.nCopies = (short)PrinterSettings.Copies; + data.nCopies = (ushort)PrinterSettings.Copies; data.hwndOwner = hwndOwner; - data.lpfnPrintHook = hookProcPtr; + + User32.WNDPROCINT wndproc = new User32.WNDPROCINT(HookProc); + data.lpfnPrintHook = Marshal.GetFunctionPointerForDelegate(wndproc); try { @@ -389,9 +372,9 @@ private bool ShowPrintDialog(IntPtr hwndOwner, NativeMethods.WndProc hookProcPtr } catch (InvalidPrinterException) { + // Leave those fields null; Windows will fill them in data.hDevMode = IntPtr.Zero; data.hDevNames = IntPtr.Zero; - // Leave those fields null; Windows will fill them in } try @@ -416,18 +399,19 @@ private bool ShowPrintDialog(IntPtr hwndOwner, NativeMethods.WndProc hookProcPtr throw new ArgumentException(string.Format(SR.PDpageOutOfRange, "FromPage")); } - data.nFromPage = (short)PrinterSettings.FromPage; - data.nToPage = (short)PrinterSettings.ToPage; - data.nMinPage = (short)PrinterSettings.MinimumPage; - data.nMaxPage = (short)PrinterSettings.MaximumPage; + data.nFromPage = (ushort)PrinterSettings.FromPage; + data.nToPage = (ushort)PrinterSettings.ToPage; + data.nMinPage = (ushort)PrinterSettings.MinimumPage; + data.nMaxPage = (ushort)PrinterSettings.MaximumPage; } - if (!UnsafeNativeMethods.PrintDlg(data)) + if (PrintDlg(ref data).IsFalse()) { + var result = CommDlgExtendedError(); return false; } - UpdatePrinterSettings(data.hDevMode, data.hDevNames, data.nCopies, data.Flags, settings, PageSettings); + UpdatePrinterSettings(data.hDevMode, data.hDevNames, (short)data.nCopies, data.Flags, settings, PageSettings); PrintToFile = (data.Flags & PD.PRINTTOFILE) != 0; PrinterSettings.PrintToFile = PrintToFile; @@ -444,7 +428,7 @@ private bool ShowPrintDialog(IntPtr hwndOwner, NativeMethods.WndProc hookProcPtr // whether the user wants to print them collated. if ((data.Flags & PD.USEDEVMODECOPIESANDCOLLATE) == 0) { - PrinterSettings.Copies = data.nCopies; + PrinterSettings.Copies = (short)data.nCopies; PrinterSettings.Collate = (data.Flags & PD.COLLATE) == PD.COLLATE; } @@ -452,6 +436,7 @@ private bool ShowPrintDialog(IntPtr hwndOwner, NativeMethods.WndProc hookProcPtr } finally { + GC.KeepAlive(wndproc); Kernel32.GlobalFree(data.hDevMode); Kernel32.GlobalFree(data.hDevNames); } diff --git a/src/System.Windows.Forms/tests/IntegrationTests/WinformsControlsTest/MainForm.Designer.cs b/src/System.Windows.Forms/tests/IntegrationTests/WinformsControlsTest/MainForm.Designer.cs index b1e45f694db..3b8354de49d 100644 --- a/src/System.Windows.Forms/tests/IntegrationTests/WinformsControlsTest/MainForm.Designer.cs +++ b/src/System.Windows.Forms/tests/IntegrationTests/WinformsControlsTest/MainForm.Designer.cs @@ -48,6 +48,7 @@ private void InitializeComponent() this.DateTimePickerButton = new System.Windows.Forms.Button(); this.FolderBrowserDialogButton = new System.Windows.Forms.Button(); this.ShowExceptionDialogButton = new System.Windows.Forms.Button(); + this.ShowPrintDialogButton = new System.Windows.Forms.Button(); this.flowLayoutPanelUITypeEditors = new System.Windows.Forms.FlowLayoutPanel(); this.fontNameEditor = new System.Windows.Forms.Button(); this.collectionEditors = new System.Windows.Forms.Button(); @@ -217,6 +218,16 @@ private void InitializeComponent() this.ShowExceptionDialogButton.UseVisualStyleBackColor = true; this.ShowExceptionDialogButton.Click += new System.EventHandler(this.ShowExceptionDialogButton_Click); // + // ShowPrintDialogButton + // + this.ShowPrintDialogButton.Location = new System.Drawing.Point(3, 177); + this.ShowPrintDialogButton.Name = "ShowPrintDialogButton"; + this.ShowPrintDialogButton.Size = new System.Drawing.Size(259, 23); + this.ShowPrintDialogButton.TabIndex = 6; + this.ShowPrintDialogButton.Text = "Print dialog"; + this.ShowPrintDialogButton.UseVisualStyleBackColor = true; + this.ShowPrintDialogButton.Click += new System.EventHandler(this.ShowPrintDialogButton_Click); + // // flowLayoutPanelUITypeEditors // this.flowLayoutPanelUITypeEditors.Controls.Add(this.buttonsButton); @@ -226,6 +237,7 @@ private void InitializeComponent() this.flowLayoutPanelUITypeEditors.Controls.Add(this.DateTimePickerButton); this.flowLayoutPanelUITypeEditors.Controls.Add(this.FolderBrowserDialogButton); this.flowLayoutPanelUITypeEditors.Controls.Add(this.ShowExceptionDialogButton); + this.flowLayoutPanelUITypeEditors.Controls.Add(this.ShowPrintDialogButton); this.flowLayoutPanelUITypeEditors.Controls.Add(this.dataGridViewButton); this.flowLayoutPanelUITypeEditors.Controls.Add(this.treeViewButton); this.flowLayoutPanelUITypeEditors.Controls.Add(this.button4); @@ -331,6 +343,7 @@ private void InitializeComponent() private System.Windows.Forms.Button DateTimePickerButton; private System.Windows.Forms.Button FolderBrowserDialogButton; private System.Windows.Forms.Button ShowExceptionDialogButton; + private System.Windows.Forms.Button ShowPrintDialogButton; private System.Windows.Forms.FlowLayoutPanel flowLayoutPanelUITypeEditors; private System.Windows.Forms.Button fontNameEditor; private System.Windows.Forms.Button collectionEditors; diff --git a/src/System.Windows.Forms/tests/IntegrationTests/WinformsControlsTest/MainForm.cs b/src/System.Windows.Forms/tests/IntegrationTests/WinformsControlsTest/MainForm.cs index d2e9c212d59..54af625fe31 100644 --- a/src/System.Windows.Forms/tests/IntegrationTests/WinformsControlsTest/MainForm.cs +++ b/src/System.Windows.Forms/tests/IntegrationTests/WinformsControlsTest/MainForm.cs @@ -3,7 +3,6 @@ // See the LICENSE file in the project root for more information. using System; -using System.Drawing; using System.Windows.Forms; using System.Windows.Forms.IntegrationTests.Common; using WindowsFormsApp1; @@ -17,6 +16,9 @@ public MainForm() { this.BringToForeground(); InitializeComponent(); + + // force the panel to show all buttons + flowLayoutPanelUITypeEditors.PerformLayout(); } private void button1_Click(object sender, EventArgs e) @@ -100,6 +102,12 @@ private void ShowExceptionDialogButton_Click(object sender, EventArgs e) new ThreadExceptionDialog(new Exception("Really long exception description string, because we want to see if it properly wraps around or is truncated.")).ShowDialog(); } + private void ShowPrintDialogButton_Click(object sender, EventArgs e) + { + PrintDialog pdlg = new PrintDialog(); + pdlg.ShowDialog(); + } + private void FontNameEditor_Click(object sender, EventArgs e) { new PropertyGrid(new UserControlWithFontNameEditor()).Show();