├── .github
└── FUNDING.yml
├── .gitignore
├── preview.png
├── PrintDialogX
├── Resources
│ ├── Effects
│ │ ├── Grayscale.ps
│ │ ├── Monochrome.ps
│ │ ├── Grayscale.fx
│ │ └── Monochrome.fx
│ └── Languages
│ │ ├── zh-CN.xaml
│ │ └── en-US.xaml
├── Global.xaml
├── PrintDialogWindow.xaml
├── PrintDialogX.csproj
├── PrintDocument.cs
├── IPrintDialogHost.cs
├── PrintDialogWindow.xaml.cs
├── PrintDialog.cs
├── InterfaceSettings.cs
├── ValueHelpers.cs
├── ValueMappings.cs
└── PrintDialogControl.xaml
├── PrintDialogX.Test
├── App.xaml.cs
├── App.xaml
├── PrintDialogX.Test.csproj
└── MainWindow.xaml
├── LICENSE.txt
├── PrintDialogX.sln
└── README.md
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | github: [Fei-Sheng-Wu]
2 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .vs/
2 |
3 | bin/
4 | obj/
5 |
6 | *.user
7 | *.nupkg
8 | *.snupkg
--------------------------------------------------------------------------------
/preview.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Fei-Sheng-Wu/PrintDialogX/HEAD/preview.png
--------------------------------------------------------------------------------
/PrintDialogX/Resources/Effects/Grayscale.ps:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Fei-Sheng-Wu/PrintDialogX/HEAD/PrintDialogX/Resources/Effects/Grayscale.ps
--------------------------------------------------------------------------------
/PrintDialogX/Resources/Effects/Monochrome.ps:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Fei-Sheng-Wu/PrintDialogX/HEAD/PrintDialogX/Resources/Effects/Monochrome.ps
--------------------------------------------------------------------------------
/PrintDialogX.Test/App.xaml.cs:
--------------------------------------------------------------------------------
1 | using System.Windows;
2 |
3 | namespace PrintDialogX.Test
4 | {
5 | public partial class App : Application
6 | {
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/PrintDialogX/Resources/Effects/Grayscale.fx:
--------------------------------------------------------------------------------
1 | sampler2D input : register(s0);
2 |
3 | float4 main(float2 uv : TEXCOORD) : COLOR
4 | {
5 | float4 color = tex2D(input, uv);
6 | color.rgb = dot(color.rgb, float3(0.3, 0.59, 0.11));
7 |
8 | return color;
9 | }
--------------------------------------------------------------------------------
/PrintDialogX.Test/App.xaml:
--------------------------------------------------------------------------------
1 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/PrintDialogX.Test/PrintDialogX.Test.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | WinExe
5 | net6.0-windows
6 | true
7 | enable
8 | latest
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/PrintDialogX/Resources/Effects/Monochrome.fx:
--------------------------------------------------------------------------------
1 | sampler2D input : register(s0);
2 |
3 | float left : register(c0);
4 | float top : register(c1);
5 | float width : register(c2);
6 | float height : register(c3);
7 |
8 | float4 main(float2 uv : TEXCOORD) : COLOR
9 | {
10 | float4 color = tex2D(input, uv);
11 | float2 position = frac((uv * float2(width, height) + float2(left, top)) / 256.0);
12 | float dither = frac(sin(dot(floor(position * 2048.0), float2(12.34, 45.67))) * 4321.1234);
13 | float grayscale = dot(color.rgb, float3(0.3, 0.59, 0.11));
14 | color.rgb = 1.0 - smoothstep(grayscale - 0.001, grayscale + 0.01, dither);
15 |
16 | return color;
17 | }
--------------------------------------------------------------------------------
/PrintDialogX/Global.xaml:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright © 2025 FeiShengWu
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/PrintDialogX.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 17
4 | VisualStudioVersion = 17.4.33205.214
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PrintDialogX", "PrintDialogX\PrintDialogX.csproj", "{10A50135-1CAB-49DF-9AAA-C970DDF46F63}"
7 | EndProject
8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PrintDialogX.Test", "PrintDialogX.Test\PrintDialogX.Test.csproj", "{E98DEC5C-3EEA-4F69-A232-A309CFB91471}"
9 | EndProject
10 | Global
11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
12 | Debug|Any CPU = Debug|Any CPU
13 | Release|Any CPU = Release|Any CPU
14 | EndGlobalSection
15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
16 | {10A50135-1CAB-49DF-9AAA-C970DDF46F63}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
17 | {10A50135-1CAB-49DF-9AAA-C970DDF46F63}.Debug|Any CPU.Build.0 = Debug|Any CPU
18 | {10A50135-1CAB-49DF-9AAA-C970DDF46F63}.Release|Any CPU.ActiveCfg = Release|Any CPU
19 | {10A50135-1CAB-49DF-9AAA-C970DDF46F63}.Release|Any CPU.Build.0 = Release|Any CPU
20 | {E98DEC5C-3EEA-4F69-A232-A309CFB91471}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
21 | {E98DEC5C-3EEA-4F69-A232-A309CFB91471}.Debug|Any CPU.Build.0 = Debug|Any CPU
22 | {E98DEC5C-3EEA-4F69-A232-A309CFB91471}.Release|Any CPU.ActiveCfg = Release|Any CPU
23 | {E98DEC5C-3EEA-4F69-A232-A309CFB91471}.Release|Any CPU.Build.0 = Release|Any CPU
24 | EndGlobalSection
25 | GlobalSection(SolutionProperties) = preSolution
26 | HideSolutionNode = FALSE
27 | EndGlobalSection
28 | GlobalSection(ExtensibilityGlobals) = postSolution
29 | SolutionGuid = {0ADCEB1B-0618-4D8A-9759-3F4C2AC95324}
30 | EndGlobalSection
31 | EndGlobal
32 |
--------------------------------------------------------------------------------
/PrintDialogX/PrintDialogWindow.xaml:
--------------------------------------------------------------------------------
1 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/PrintDialogX/PrintDialogX.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Library
5 | net472;net6.0-windows
6 | true
7 | enable
8 | 14.0
9 |
10 |
11 |
12 | PrintDialogX
13 | 3.1.0
14 | FeiShengWu
15 | A custom WPF print dialog with lightning-fast real-time preview. Support a full scope of print settings for modern demands, with the flexibility for complete customization. Provide the ability to dynamically adjust documents according to changes in print settings. Empowers the user experience with a responsive, elegant, and configurable interface.
16 | Copyright © 2025 FeiShengWu
17 | https://github.com/Fei-Sheng-Wu/PrintDialogX
18 | MIT
19 | C#;WPF;PrintDialog;PrinterDialog;Dialog;Printer;Document;Print;Printing;Preview;Previewer;DocumentPreview;DocumentPrinting
20 |
21 |
22 |
23 | true
24 | true
25 | snupkg
26 | portable
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
52 |
53 |
--------------------------------------------------------------------------------
/PrintDialogX/PrintDocument.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Windows;
4 | using System.Windows.Media;
5 | using System.Windows.Threading;
6 |
7 | namespace PrintDialogX
8 | {
9 | ///
10 | /// Initializes a new instance of the class.
11 | ///
12 | public class PrintPage
13 | {
14 | ///
15 | /// Gets or sets the content of the page.
16 | ///
17 | public FrameworkElement? Content
18 | {
19 | get;
20 | set => field = value == null || VisualTreeHelper.GetParent(value) == null ? value : throw new PrintDocumentException(value, "The value is already the child of another element.");
21 | } = null;
22 | }
23 |
24 | ///
25 | /// Initializes a new instance of the class.
26 | ///
27 | public class PrintDocument()
28 | {
29 | ///
30 | /// Occurs when the print settings have changed.
31 | ///
32 | public event EventHandler? PrintSettingsChanged = null;
33 |
34 | ///
35 | /// Gets or sets the name of the document.
36 | ///
37 | public string DocumentName { get; set; } = string.Empty;
38 |
39 | ///
40 | /// Gets or sets the size of the document. If set to , the document automatically adapts to the sizes calculated from the print settings.
41 | ///
42 | public Enums.Size? DocumentSize { get; set; } = null;
43 |
44 | ///
45 | /// Gets or sets the default margin of the document in pixels.
46 | ///
47 | public double DocumentMargin
48 | {
49 | get;
50 | set => field = value >= 0 ? value : throw new ArgumentOutOfRangeException(nameof(DocumentMargin), "The value cannot be negative.");
51 | } = 60;
52 |
53 | ///
54 | /// Gets or sets the collection of pages in the document.
55 | ///
56 | public ICollection Pages { get; set; } = [];
57 |
58 | ///
59 | /// Gets the number of pages in the document.
60 | ///
61 | public int PageCount { get => Pages.Count; }
62 |
63 | ///
64 | /// Gets or sets the computed size of the available space for the content of the document, excluding the margin.
65 | ///
66 | public Size MeasuredSize { get; set; } = Size.Empty;
67 |
68 | ///
69 | /// Raises the event.
70 | ///
71 | /// The instance to be used to invoke the handler.
72 | /// The instance of the new print settings.
73 | public void OnPrintSettingsChanged(Dispatcher dispatcher, PrintSettingsEventArgs settings)
74 | {
75 | dispatcher.Invoke(() => PrintSettingsChanged?.Invoke(this, settings));
76 | }
77 | }
78 |
79 | ///
80 | /// Initializes a new instance of the class.
81 | ///
82 | /// The instance that caused the error.
83 | /// The message that describes the error.
84 | public class PrintDocumentException(FrameworkElement content, string message) : Exception(message)
85 | {
86 | ///
87 | /// Gets or sets the instance that caused the error.
88 | ///
89 | public FrameworkElement Content { get; set; } = content;
90 | }
91 | }
92 |
93 |
--------------------------------------------------------------------------------
/PrintDialogX/IPrintDialogHost.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Threading.Tasks;
3 | using System.Windows;
4 | using System.Windows.Input;
5 |
6 | namespace PrintDialogX
7 | {
8 | ///
9 | /// Initializes a new instance of the struct.
10 | ///
11 | public struct PrintDialogResult()
12 | {
13 | ///
14 | /// Gets or sets whether the document was successfully printed or the operation was cancelled.
15 | ///
16 | public bool IsSuccess { get; set; }
17 |
18 | ///
19 | /// Gets or sets the number of papers calculated to be used.
20 | ///
21 | public int PaperCount { get; set; }
22 | }
23 |
24 | ///
25 | /// Represents a host that can contain the actual control for the print operation.
26 | ///
27 | public interface IPrintDialogHost
28 | {
29 | ///
30 | /// Specifies the state of the print job progress.
31 | ///
32 | public enum PrintDialogProgressState
33 | {
34 | ///
35 | /// There is no available print job.
36 | ///
37 | None,
38 |
39 | ///
40 | /// The print job is initializing.
41 | ///
42 | Indeterminate,
43 |
44 | ///
45 | /// The print job is in progress.
46 | ///
47 | Normal,
48 |
49 | ///
50 | /// The print job failed or is cancelled.
51 | ///
52 | Error
53 | }
54 |
55 | ///
56 | /// Initializes a new instance of the struct.
57 | ///
58 | public struct PrintDialogProgress()
59 | {
60 | ///
61 | /// Gets or sets the state of the print job progress.
62 | ///
63 | public PrintDialogProgressState State { get; set; }
64 |
65 | ///
66 | /// Gets or sets the percentage value of the print job progress, from 0 to 100.
67 | ///
68 | public double Value { get; set; }
69 | }
70 |
71 | ///
72 | /// Starts the host with the specified settings and a callback to attach the actual control for the print operation.
73 | ///
74 | /// The instance with the specified settings.
75 | /// to start the host in a dialog style and return only when the operation is finished; otherwise, .
76 | /// The callback function to be invoked to attain the actual control for the print operation to be attached to the host.
77 | public void Start(PrintDialog dialog, bool isDialog, Func> callback);
78 |
79 | ///
80 | /// Gets the result of the print operation.
81 | ///
82 | ///
83 | public PrintDialogResult GetResult();
84 |
85 | ///
86 | /// Sets the result of the print operation.
87 | ///
88 | /// The result to be set to.
89 | public void SetResult(PrintDialogResult result);
90 |
91 | ///
92 | /// Sets the progress of the current print job.
93 | ///
94 | /// The progress to be set to.
95 | public void SetProgress(PrintDialogProgress progress);
96 |
97 | ///
98 | /// Sets the event handler that handles keyboard shortcuts.
99 | ///
100 | /// The event handler to be used.
101 | public void SetShortcutHandler(KeyEventHandler handler);
102 | }
103 | }
104 |
--------------------------------------------------------------------------------
/PrintDialogX/PrintDialogWindow.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.ComponentModel;
3 | using System.Threading.Tasks;
4 | using System.Windows;
5 | using System.Windows.Input;
6 | using System.Windows.Media;
7 | using System.Windows.Shell;
8 | using System.Windows.Controls;
9 |
10 | namespace PrintDialogX
11 | {
12 | internal partial class PrintDialogWindow : Wpf.Ui.Controls.FluentWindow, IPrintDialogHost
13 | {
14 | private bool isAvailable = true;
15 | private Func>? loader = null;
16 | private KeyEventHandler? handler = null;
17 | private PrintDialogResult result = new();
18 |
19 | public PrintDialogWindow()
20 | {
21 | InitializeComponent();
22 | }
23 |
24 | private async void AttachControl(object sender, EventArgs e)
25 | {
26 | if (loader == null)
27 | {
28 | return;
29 | }
30 |
31 | content.Child = await loader();
32 | }
33 |
34 | private void HandleShortcuts(object sender, KeyEventArgs e)
35 | {
36 | handler?.Invoke(sender, e);
37 | }
38 |
39 | public void Start(PrintDialog dialog, bool isDialog, Func> callback)
40 | {
41 | if (!isAvailable)
42 | {
43 | throw new InvalidOperationException("The print dialog has already been used.");
44 | }
45 |
46 | isAvailable = false;
47 | loader = callback;
48 |
49 | InterfaceToContentConverter.ApplyLanguage(Resources, dialog.InterfaceSettings.DisplayLanguage);
50 | title.Header = new TextBlock()
51 | {
52 | Margin = new(dialog.InterfaceSettings.Icon == null ? 16 : 0, 10, 0, 10),
53 | FontSize = title.FontSize,
54 | Text = dialog.InterfaceSettings.Title ?? Title
55 | };
56 | title.Icon = dialog.InterfaceSettings.Icon;
57 |
58 | Wpf.Ui.Appearance.ApplicationThemeManager.Apply(this);
59 | Wpf.Ui.Appearance.ApplicationThemeManager.Changed += UpdateTheme;
60 | Wpf.Ui.Appearance.SystemThemeWatcher.Watch(this);
61 |
62 | if (isDialog)
63 | {
64 | ShowDialog();
65 | }
66 | else
67 | {
68 | Show();
69 | }
70 | }
71 |
72 | public PrintDialogResult GetResult()
73 | {
74 | return result;
75 | }
76 |
77 | public void SetResult(PrintDialogResult value)
78 | {
79 | result = value;
80 | Close();
81 | }
82 |
83 | public void SetProgress(IPrintDialogHost.PrintDialogProgress progress)
84 | {
85 | TaskbarItemInfo.ProgressState = progress.State switch
86 | {
87 | IPrintDialogHost.PrintDialogProgressState.Indeterminate => TaskbarItemProgressState.Indeterminate,
88 | IPrintDialogHost.PrintDialogProgressState.Normal => TaskbarItemProgressState.Normal,
89 | IPrintDialogHost.PrintDialogProgressState.Error => TaskbarItemProgressState.Error,
90 | _ => TaskbarItemProgressState.None
91 | };
92 | TaskbarItemInfo.ProgressValue = progress.Value / 100;
93 | }
94 |
95 | public void SetShortcutHandler(KeyEventHandler value)
96 | {
97 | handler = value;
98 | }
99 |
100 | public void UpdateTheme(Wpf.Ui.Appearance.ApplicationTheme theme, Color accent)
101 | {
102 | Wpf.Ui.Appearance.ApplicationThemeManager.Apply(this);
103 |
104 | if (content.Child is FrameworkElement element)
105 | {
106 | Wpf.Ui.Appearance.ApplicationThemeManager.Apply(element);
107 | }
108 | }
109 |
110 | protected override void OnClosing(CancelEventArgs e)
111 | {
112 | Wpf.Ui.Appearance.ApplicationThemeManager.Changed -= UpdateTheme;
113 | Wpf.Ui.Appearance.SystemThemeWatcher.UnWatch(this);
114 |
115 | base.OnClosing(e);
116 | }
117 | }
118 | }
119 |
--------------------------------------------------------------------------------
/PrintDialogX.Test/MainWindow.xaml:
--------------------------------------------------------------------------------
1 |
7 |
8 |
11 |
15 |
19 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
--------------------------------------------------------------------------------
/PrintDialogX/PrintDialog.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Printing;
3 | using System.Threading.Tasks;
4 | using System.Windows;
5 |
6 | namespace PrintDialogX
7 | {
8 | ///
9 | /// Initializes a new instance of the class.
10 | ///
11 | /// The custom instance to be used to host the actual control for the print operation.
12 | public class PrintDialog(IPrintDialogHost host)
13 | {
14 | ///
15 | /// Initializes a new instance of the class.
16 | ///
17 | public PrintDialog() : this(new PrintDialogWindow()) { }
18 |
19 | ///
20 | /// Initializes a new instance of the class.
21 | ///
22 | /// The callback function that is invoked to customize the default instance, which derives from .
23 | public PrintDialog(Action callback) : this()
24 | {
25 | callback((Window)Host);
26 | }
27 |
28 | ///
29 | /// Gets or sets the instance to host the actual control for the print operation.
30 | ///
31 | public IPrintDialogHost Host { get; set; } = host;
32 |
33 | ///
34 | /// Gets or sets the document to be printed.
35 | ///
36 | public PrintDocument? Document { get; set; } = null;
37 |
38 | ///
39 | /// Gets ot sets the instance to be used to find printers. If set to , the default is used.
40 | ///
41 | public PrintServer? PrintServer { get; set; } = null;
42 |
43 | ///
44 | /// Gets or sets the default printer.
45 | ///
46 | public PrintQueue? DefaultPrinter { get; set; } = null;
47 |
48 | ///
49 | /// Gets or sets the default print settings.
50 | ///
51 | public PrintSettings PrintSettings { get; set; } = new();
52 |
53 | ///
54 | /// Gets or sets the interface settings.
55 | ///
56 | public InterfaceSettings InterfaceSettings { get; set; } = new();
57 |
58 | ///
59 | /// Gets the result of the print operation.
60 | ///
61 | public PrintDialogResult Result { get => Host.GetResult(); }
62 |
63 | ///
64 | /// Opens the dialog.
65 | ///
66 | public void Show()
67 | {
68 | Host.Start(this, false, GetCallback(null));
69 | }
70 |
71 | ///
72 | /// Opens the dialog.
73 | ///
74 | /// The callback function that is invoked asynchronously to generate the document while a spinner is displayed in the dialog.
75 | public void Show(Func generator)
76 | {
77 | Host.Start(this, false, GetCallback(generator));
78 | }
79 |
80 | ///
81 | /// Opens the dialog and returns only when the dialog is closed.
82 | ///
83 | /// if the document was successfully printed; otherwise, .
84 | public bool ShowDialog()
85 | {
86 | Host.Start(this, true, GetCallback(null));
87 |
88 | return Host.GetResult().IsSuccess;
89 | }
90 |
91 | ///
92 | /// Opens the dialog and returns only when the dialog is closed.
93 | ///
94 | /// The callback function that is invoked asynchronously to generate the document while a spinner is displayed in the dialog.
95 | /// if the document was successfully printed; otherwise, .
96 | public bool ShowDialog(Func generator)
97 | {
98 | Host.Start(this, true, GetCallback(generator));
99 |
100 | return Host.GetResult().IsSuccess;
101 | }
102 |
103 | private Func> GetCallback(Func? generator)
104 | {
105 | return async () =>
106 | {
107 | if (generator != null)
108 | {
109 | await generator();
110 | }
111 |
112 | return new PrintDialogControl(this, Host);
113 | };
114 | }
115 | }
116 | }
117 |
--------------------------------------------------------------------------------
/PrintDialogX/InterfaceSettings.cs:
--------------------------------------------------------------------------------
1 | namespace PrintDialogX
2 | {
3 | ///
4 | /// Initializes a new instance of the class.
5 | ///
6 | public class InterfaceSettings()
7 | {
8 | ///
9 | /// Specifies the interface control of a specific print setting.
10 | ///
11 | public enum Option
12 | {
13 | ///
14 | /// An empty gap with a height of 20 pixels.
15 | ///
16 | Void = -1,
17 |
18 | ///
19 | /// An option to select a printer.
20 | ///
21 | Printer,
22 |
23 | ///
24 | /// An option to open the printer preferences dialog.
25 | ///
26 | PrinterPreferences,
27 |
28 | ///
29 | /// An option to select the number of copies.
30 | ///
31 | Copies,
32 |
33 | ///
34 | /// An option to select a collation choice.
35 | ///
36 | Collation,
37 |
38 | ///
39 | /// An option to select the pages to be printed.
40 | ///
41 | Pages,
42 |
43 | ///
44 | /// An option to select a layout.
45 | ///
46 | Layout,
47 |
48 | ///
49 | /// An option to select a size.
50 | ///
51 | Size,
52 |
53 | ///
54 | /// An option to select a color.
55 | ///
56 | Color,
57 |
58 | ///
59 | /// An option to select a quality.
60 | ///
61 | Quality,
62 |
63 | ///
64 | /// An option to select the number of pages per sheet.
65 | ///
66 | PagesPerSheet,
67 |
68 | ///
69 | /// An option to select a page order.
70 | ///
71 | PageOrder,
72 |
73 | ///
74 | /// An option to select a scale.
75 | ///
76 | Scale,
77 |
78 | ///
79 | /// An option to select a margin.
80 | ///
81 | Margin,
82 |
83 | ///
84 | /// An option to select a double-sided choice.
85 | ///
86 | DoubleSided,
87 |
88 | ///
89 | /// An option to select a type.
90 | ///
91 | Type,
92 |
93 | ///
94 | /// An option to select a source.
95 | ///
96 | Source
97 | }
98 |
99 | ///
100 | /// Specifies the interface language.
101 | ///
102 | public enum Language
103 | {
104 | ///
105 | /// English (United States).
106 | ///
107 | en_US,
108 |
109 | ///
110 | /// Chinese (China).
111 | ///
112 | zh_CN
113 | }
114 |
115 | ///
116 | /// Gets or sets the title of the interface. If set to , the default title is used.
117 | ///
118 | public string? Title { get; set; } = null;
119 |
120 | ///
121 | /// Gets or sets the icon of the interface. If set to , no icon is used.
122 | ///
123 | public Wpf.Ui.Controls.IconElement? Icon { get; set; } = new Wpf.Ui.Controls.SymbolIcon()
124 | {
125 | Symbol = Wpf.Ui.Controls.SymbolRegular.Print20,
126 | FontSize = 18
127 | };
128 |
129 | ///
130 | /// Gets or sets the collection of basic interface controls to be placed outside the print settings expander.
131 | ///
132 | public Option[] BasicSettings { get; set; } = [Option.Printer, Option.PrinterPreferences, Option.Void, Option.Copies, Option.Collation, Option.Pages, Option.Layout, Option.Size];
133 |
134 | ///
135 | /// Gets or sets the collection of advanced interface controls to be placed inside the print settings expander.
136 | ///
137 | public Option[] AdvancedSettings { get; set; } = [Option.Color, Option.Quality, Option.PagesPerSheet, Option.PageOrder, Option.Scale, Option.Margin, Option.DoubleSided, Option.Type, Option.Source];
138 |
139 | ///
140 | /// Gets or sets the display language of the interface.
141 | ///
142 | public Language DisplayLanguage { get; set; } = Language.en_US;
143 | }
144 | }
145 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # PrintDialogX v3.1.0
2 |
3 | [](#)
4 | [](#)
5 | [](#)
6 | [](#)
7 | [](https://www.nuget.org/packages/PrintDialogX)
8 | [](https://github.com/Fei-Sheng-Wu/PrintDialogX/blob/master/LICENSE.txt)
9 |
10 | > A custom WPF print dialog with lightning-fast real-time preview. Support a full scope of print settings for modern demands, with the flexibility for complete customization. Provide the ability to dynamically adjust documents according to changes in print settings. Empowers the user experience with a responsive, elegant, and configurable interface.
11 |
12 | ## Preview
13 |
14 | 
15 |
16 | ## Features
17 |
18 | PrintDialogX is a powerful and user-friendly print dialog tailored for modern demands. It supports all essential and advanced features expected from a next-generation print dialog, delivering real-time document previews at lightning speed. Without relying on the built-in controls for document hosting and printing, this next-level print dialog is able to truly take full control over the print pipeline, enabling more thorough customizations and better performance.
19 |
20 | The print settings responsively adapt to the capabilities of specific printers, adhering to industry standards in addition to intelligently maintaining the user's preferences. With the ability to respond to any changes in print settings made by the user, documents remain flexible and dynamically reactive to these adjustments. Powered by [WPF-UI](https://wpfui.lepo.co), the compelling interface allows complete personalization to suit specific scenarios, while its carefully crafted structure minimizes lag and ensures a fluid, modern printing experience.
21 |
22 | - [x] Comprehensive printer selection
23 | - [x] Detailed printer information with graphics
24 | - [x] Options to add new printers or configure existing printers
25 | - [x] Personalizable print settings
26 | - [x] Full range of configurations for modern print dialogs
27 | - [x] Modifiable settings organization for personal needs
28 | - [x] Interactive real-time preview
29 | - [x] Responsive high-resolution zooming
30 | - [x] Customizable document arrangement and navigation
31 | - [x] Dynamically updatable documents
32 | - [x] Handler for print setting changes to adjust the contents on the fly
33 |
34 | ## Dependencies
35 |
36 | - WPF-UI ≥ 4.0.3
37 |
38 | ## How to Use
39 |
40 | An example project is included under the [PrintDialogX.Test](https://github.com/Fei-Sheng-Wu/PrintDialogX/tree/master/PrintDialogX.Test) folder, with custom configurations to generate the print dialog accordingly, and three template documents to showcase the capability of PrintDialogX.
41 |
42 | ### Quick Start
43 |
44 | The usage of PrintDialogX is straightforward:
45 |
46 | ```c#
47 | // Create a new document
48 | PrintDialogX.PrintDocument document = new PrintDialogX.PrintDocument();
49 |
50 | // Create the pages of the document
51 | for (int i = 0; i < 100; i++)
52 | {
53 | PrintDialogX.PrintPage page = new PrintDialogX.PrintPage();
54 | page.Content = GenerateContent(i);
55 | document.Pages.Add(page);
56 | }
57 |
58 | // Initialize the print dialog
59 | PrintDialogX.PrintDialog dialog = new PrintDialogX.PrintDialog();
60 | dialog.Document = document;
61 |
62 | // Open the print dialog
63 | dialog.ShowDialog();
64 |
65 | // Retrieve the result of the operation
66 | bool isSuccess = dialog.Result.IsSuccess;
67 | int paperCount = dialog.Result.PaperCount;
68 | ```
69 |
70 | ### Asynchronous Document Generation
71 |
72 | PrintDialogX supports the ability to delay the document generation until the dialog is loaded, so that a spinner is shown during the generation:
73 |
74 | ```c#
75 | // Initialize the print dialog
76 | PrintDialogX.PrintDialog dialog = new PrintDialogX.PrintDialog();
77 |
78 | // Open the print dialog
79 | dialog.ShowDialog(async () =>
80 | {
81 | // Create a new document
82 | PrintDialogX.PrintDocument document = new PrintDialogX.PrintDocument();
83 |
84 | // Create the pages of the document asynchronously
85 | for (int i = 0; i < 100; i++)
86 | {
87 | PrintDialogX.PrintPage page = new PrintDialogX.PrintPage();
88 | page.Content = await GenerateContentAsync(i);
89 | document.Pages.Add(page);
90 |
91 | // Allow for other UI updates
92 | await Dispatcher.Yield();
93 | }
94 | dialog.Document = document;
95 | });
96 | ```
97 |
98 | ### Document Configuration
99 |
100 | It is easy to customize the document information (by default, the document is dynamically sized and takes up the entirety of the available space, but one may also choose to fix the size of the document):
101 |
102 | ```c#
103 | document.DocumentName = "Untitled Document";
104 | document.DocumentSize = new PrintDialogX.Enums.Size(PrintDialogX.Enums.Size.DefinedSize.NorthAmericaLetter);
105 | document.DocumentMargin = 50.0;
106 | ```
107 |
108 | ### Dynamically Updatable Documents
109 |
110 | PrintDialogX raises an event when the print settings are changed:
111 |
112 | ```c#
113 | document.PrintSettingsChanged += HandlePrintSettingsChanged;
114 | ```
115 | ```c#
116 | private async void HandlePrintSettingsChanged(object? sender, PrintDialogX.PrintSettingsEventArgs e)
117 | {
118 | if (sender is not PrintDialogX.PrintDocument document)
119 | {
120 | return;
121 | }
122 |
123 | // Block the preview generation until the document is updated, due to the use of await
124 | e.IsBlocking = true;
125 |
126 | int index = 0;
127 | foreach (PrintDialogX.PrintPage page in document.Pages)
128 | {
129 | // Update the content according to the print settings
130 | page.Content = await UpdateContentAsync(index, e.CurrentSettings);
131 | index++;
132 |
133 | // Allow for other UI updates
134 | await Dispatcher.Yield();
135 | }
136 |
137 | e.IsBlocking = false;
138 | }
139 | ```
140 |
141 | ### Print Settings Customizations
142 |
143 | The default settings can be set individually (certain settings accept `null` and use `null` by default, which represents that the default configuration of the selected printer will be used):
144 |
145 | ```c#
146 | dialog.PrintSettings.Copies = 2;
147 | dialog.PrintSettings.Collation = PrintDialogX.Enums.Collation.Collated;
148 | dialog.PrintSettings.Pages = PrintDialogX.Enums.Pages.CustomPages;
149 | dialog.PrintSettings.CustomPages = "2-5, 8";
150 | dialog.PrintSettings.Layout = PrintDialogX.Enums.Layout.Landscape;
151 | dialog.PrintSettings.Color = PrintDialogX.Enums.Color.Grayscale;
152 | ```
153 |
154 | ### Interface Customizations
155 |
156 | PrintDialogX offers the ability to both customize the window of the print dialog and the exact interface to be used within the print dialog:
157 |
158 | ```c#
159 | // Initialize the print dialog
160 | PrintDialogX.PrintDialog dialog = new PrintDialogX.PrintDialog(window =>
161 | {
162 | // Customize the dialog window
163 | window.Topmost = true;
164 | window.ShowInTaskbar = false;
165 | });
166 |
167 | // Customize the interface
168 | dialog.InterfaceSettings.Title = "Test Print";
169 | dialog.InterfaceSettings.BasicSettings = [PrintDialogX.InterfaceSettings.Option.Printer, PrintDialogX.InterfaceSettings.Option.Void, PrintDialogX.InterfaceSettings.Option.Pages, PrintDialogX.InterfaceSettings.Option.Layout, PrintDialogX.InterfaceSettings.Option.Size];
170 | dialog.InterfaceSettings.AdvancedSettings = [PrintDialogX.InterfaceSettings.Option.Color, PrintDialogX.InterfaceSettings.Option.Quality, PrintDialogX.InterfaceSettings.Option.Scale, PrintDialogX.InterfaceSettings.Option.Margin, PrintDialogX.InterfaceSettings.Option.DoubleSided, PrintDialogX.InterfaceSettings.Option.Type, PrintDialogX.InterfaceSettings.Option.Source];
171 | ```
172 |
173 | ## License
174 |
175 | This project is under the [MIT License](https://github.com/Fei-Sheng-Wu/PrintDialogX/blob/master/LICENSE.txt).
176 |
--------------------------------------------------------------------------------
/PrintDialogX/Resources/Languages/zh-CN.xaml:
--------------------------------------------------------------------------------
1 |
4 |
5 | 打印
6 |
7 | 确认
8 | 打印
9 | 取消
10 | 添加新打印机
11 | 打印机属性
12 | 放大
13 | 缩小
14 | 实际尺寸
15 | 适应宽度
16 | 整页
17 | 双页
18 | 第一页
19 | 上一页
20 | 下一页
21 | 最后一页
22 |
23 | 打印机
24 | 份数
25 | 范围
26 | 自定义范围
27 | 尺寸
28 | 方向
29 | 颜色
30 | 质量
31 | 并打
32 | 并打顺序
33 | 缩放
34 | 自定义缩放
35 | 边距
36 | 自定义边距
37 | 双面打印
38 | 纸张类型
39 | 纸张来源
40 |
41 | 全部页
42 | 当前页
43 | 自定义
44 | 纵向
45 | 横向
46 | A0
47 | A1
48 | A10
49 | A2
50 | A3
51 | A3(横向)
52 | A3加长
53 | A4
54 | A4(横向)
55 | A4加长
56 | A5
57 | A5(横向)
58 | A5加长
59 | A6
60 | A6(横向)
61 | A7
62 | A8
63 | A9
64 | B0
65 | B1
66 | B10
67 | B2
68 | B3
69 | B4
70 | B4信封
71 | B5信封
72 | B5加长
73 | B7
74 | B8
75 | B9
76 | C0
77 | C1
78 | C10
79 | C2
80 | C3
81 | C3信封
82 | C4
83 | C4信封
84 | C5
85 | C5信封
86 | C6
87 | C6信封
88 | C6C5信封
89 | C7
90 | C8
91 | C9
92 | DL信封
93 | DL信封(横向)
94 | SRA3
95 | 四倍明信片
96 | JB0
97 | JB1
98 | JB10
99 | JB2
100 | JB3
101 | JB4
102 | JB4(横向)
103 | JB5
104 | JB5(横向)
105 | JB6
106 | JB6(横向)
107 | JB7
108 | JB8
109 | JB9
110 | C3信封
111 | C3信封(横向)
112 | C4信封
113 | C4信封(横向)
114 | 明信片
115 | 明信片(横向)
116 | K2信封
117 | K2信封(横向)
118 | K3信封
119 | K3信封(横向)
120 | Y4信封
121 | 10×11英寸
122 | 10×14英寸
123 | 11×17英寸
124 | 9×11英寸
125 | 建筑图纸A
126 | 建筑图纸B
127 | 建筑图纸C
128 | 建筑图纸D
129 | 建筑图纸E
130 | C图纸
131 | D图纸
132 | E图纸
133 | 行政用纸
134 | 德国法律连续纸
135 | 德国标准连续纸
136 | 法律用纸
137 | 法律用纸加长
138 | 信纸
139 | 信纸(横向)
140 | 信纸加长
141 | 信纸加大
142 | 君主信封
143 | 便条纸
144 | #10信封
145 | #10信封(横向)
146 | #9信封
147 | #11信封
148 | #12信封
149 | #14信封
150 | 个人信封
151 | 四开纸
152 | 声明纸
153 | 超A纸
154 | 超B纸
155 | 小报
156 | 小报加长
157 | A4加大
158 | A3加大
159 | 对开纸
160 | 请帖信封
161 | 意大利信封
162 | 1号信封
163 | 1号信封(横向)
164 | 10号信封
165 | 10号信封(横向)
166 | 16开
167 | 16开(横向)
168 | 2号信封
169 | 2号信封(横向)
170 | 32开
171 | 32开(横向)
172 | 大32开
173 | 3号信封
174 | 3号信封(横向)
175 | 4号信封
176 | 4号信封(横向)
177 | 5号信封
178 | 5号信封(横向)
179 | 6号信封
180 | 6号信封(横向)
181 | 7号信封
182 | 7号信封(横向)
183 | 8号信封
184 | 8号信封(横向)
185 | 9号信封
186 | 9号信封(横向)
187 | 4英寸卷纸
188 | 6英寸卷纸
189 | 8英寸卷纸
190 | 12英寸卷纸
191 | 15英寸卷纸
192 | 18英寸卷纸
193 | 22英寸卷纸
194 | 24英寸卷纸
195 | 30英寸卷纸
196 | 36英寸卷纸
197 | 54英寸卷纸
198 | 双倍明信片
199 | 双倍明信片(横向)
200 | L照片
201 | 2L照片
202 | Y1信封
203 | Y2信封
204 | Y3信封
205 | Y4信封(横向)
206 | Y6信封
207 | Y6信封(横向)
208 | 4×6英寸
209 | 4×8英寸
210 | 5×7英寸
211 | 8×10英寸
212 | 10×12英寸
213 | 14×17英寸
214 | 名片
215 | 信用卡
216 | 彩色
217 | 灰度
218 | 单色
219 | 自动
220 | 草稿
221 | 传真
222 | 高
223 | 普通
224 | 照片
225 | 文本
226 | 1
227 | 2
228 | 4
229 | 6
230 | 9
231 | 16
232 | 从左到右
233 | 从右到左
234 | 从上到下
235 | 从下到上
236 | 自动适应
237 | 25%
238 | 50%
239 | 75%
240 | 100%
241 | 150%
242 | 200%
243 | 自定义
244 | 默认
245 | 无
246 | 最小
247 | 单面
248 | 短边翻转
249 | 长边翻转
250 | 自动选择
251 | 档案纸
252 | 背面印刷胶片
253 | 信纸
254 | 卡纸
255 | 连续纸
256 | 标准信封
257 | 开窗信封
258 | 布料
259 | 高分辨率纸
260 | 标签纸
261 | 连体多联表单
262 | 单体多联表单
263 | 胶片相纸
264 | 光面相纸
265 | 高光相纸
266 | 哑光相纸
267 | 缎面相纸
268 | 半光相纸
269 | 普通纸
270 | 连续显示
271 | 分页显示
272 | 信笺纸
273 | 整页标签纸
274 | 预切标签纸
275 | 透明片
276 | T恤转印纸
277 | 纸盒
278 | 连续进纸器
279 | 自动进纸器
280 | 手动进纸
281 |
282 | 错误
283 | 更多设置
284 | 逐份打印
285 | 双面打印
286 | 未知
287 | 就绪
288 | 忙碌
289 | 机门打开
290 | 初始化中
291 | 数据传输中
292 | 需手动送纸
293 | 无碳粉
294 | 不可用
295 | 离线
296 | 内存不足
297 | 输出盒已满
298 | 当前页面打印失败
299 | 纸张卡住
300 | 缺字
301 | 纸张错误
302 | 已暂停
303 | 任务删除中
304 | 节能模式
305 | 打印中
306 | 处理中
307 | 服务器未知
308 | 碳粉不足
309 | 需用户操作
310 | 等待中
311 | 预热中
312 | 页
313 |
314 | 任务:
315 | 位置:
316 | 备注:
317 | 自定义:
318 | 进度:
319 |
320 | 例:1, 3-5, 8
321 |
322 | 数值无效!
323 | 未检测到打印机!
324 | 无法打开打印机属性窗口!
325 | 无法打开添加新打印机窗口!
326 | 无法启动打印任务!
327 | 打印任务已取消!
328 | 打印任务发生错误!
329 |
--------------------------------------------------------------------------------
/PrintDialogX/Resources/Languages/en-US.xaml:
--------------------------------------------------------------------------------
1 |
4 |
5 | Print
6 |
7 | OK
8 | Print
9 | Cancel
10 | Add New Printer
11 | Printer Preferences
12 | Zoom In
13 | Zoom Out
14 | Actual Size
15 | Fit to Width
16 | Whole Page
17 | Two Pages
18 | First Page
19 | Previous Page
20 | Next Page
21 | Last Page
22 |
23 | Printer
24 | Copies
25 | Pages
26 | Custom Pages
27 | Size
28 | Layout
29 | Color
30 | Quality
31 | Pages per Sheet
32 | Page Order
33 | Scale
34 | Custom Scale
35 | Margin
36 | Custom Margin
37 | Double-Sided
38 | Paper Type
39 | Paper Source
40 |
41 | All Pages
42 | Current Page
43 | Custom Pages
44 | Portrait
45 | Landscape
46 | A0
47 | A1
48 | A10
49 | A2
50 | A3
51 | A3 Rotated
52 | A3 Extra
53 | A4
54 | A4 Rotated
55 | A4 Extra
56 | A5
57 | A5 Rotated
58 | A5 Extra
59 | A6
60 | A6 Rotated
61 | A7
62 | A8
63 | A9
64 | B0
65 | B1
66 | B10
67 | B2
68 | B3
69 | B4
70 | B4 Envelope
71 | B5 Envelope
72 | B5 Extra
73 | B7
74 | B8
75 | B9
76 | C0
77 | C1
78 | C10
79 | C2
80 | C3
81 | C3 Envelope
82 | C4
83 | C4 Envelope
84 | C5
85 | C5 Envelope
86 | C6
87 | C6 Envelope
88 | C6C5 Envelope
89 | C7
90 | C8
91 | C9
92 | DL Envelope
93 | DL Envelope Rotated
94 | SRA3
95 | Quadruple Hagaki Postcard
96 | JB0
97 | JB1
98 | JB10
99 | JB2
100 | JB3
101 | JB4
102 | JB4 Rotated
103 | JB5
104 | JB5 Rotated
105 | JB6
106 | JB6 Rotated
107 | JB7
108 | JB8
109 | JB9
110 | C3 Envelope
111 | C3 Envelope Rotated
112 | C4 Envelope
113 | C4 Envelope Rotated
114 | Hagaki Postcard
115 | Hagaki Postcard Rotated
116 | K2 Envelope
117 | K2 Envelope Rotated
118 | K3 Envelope
119 | K3 Envelope Rotated
120 | Y4 Envelope
121 | 10" × 11"
122 | 10" × 14"
123 | 11" × 17"
124 | 9" × 11"
125 | Architecture A Sheet
126 | Architecture B Sheet
127 | Architecture C Sheet
128 | Architecture D Sheet
129 | Architecture E Sheet
130 | C Sheet
131 | D Sheet
132 | E Sheet
133 | Executive
134 | German Legal Fanfold
135 | German Standard Fanfold
136 | Legal
137 | Legal Extra
138 | Letter
139 | Letter Rotated
140 | Letter Extra
141 | Letter Plus
142 | Monarch Envelope
143 | Note
144 | #10 Envelope
145 | #10 Envelope Rotated
146 | #9 Envelope
147 | #11 Envelope
148 | #12 Envelope
149 | #14 Envelope
150 | Personal Envelope
151 | Quarto
152 | Statement
153 | Super A
154 | Super B
155 | Tabloid
156 | Tabloid Extra
157 | A4 Plus
158 | A3 Plus
159 | Folio
160 | Invite Envelope
161 | Italian Envelope
162 | Envelope #1
163 | Envelope #1 Rotated
164 | Envelope #10
165 | Envelope #10 Rotated
166 | 16K
167 | 16K Rotated
168 | Envelope #2
169 | Envelope #2 Rotated
170 | 32K
171 | 32K Rotated
172 | 32K Big
173 | Envelope #3
174 | Envelope #3 Rotated
175 | Envelope #4
176 | Envelope #4 Rotated
177 | Envelope #5
178 | Envelope #5 Rotated
179 | Envelope #6
180 | Envelope #6 Rotated
181 | Envelope #7
182 | Envelope #7 Rotated
183 | Envelope #8
184 | Envelope #8 Rotated
185 | Envelope #9
186 | Envelope #9 Rotated
187 | 4" Roll
188 | 6" Roll
189 | 8" Roll
190 | 12" Roll
191 | 15" Roll
192 | 18" Roll
193 | 22" Roll
194 | 24" Roll
195 | 30" Roll
196 | 36" Roll
197 | 54" Roll
198 | Double Hagaki Postcard
199 | Double Hagaki Postcard Rotated
200 | L Photo
201 | 2L Photo
202 | Y1 Envelope
203 | Y2 Envelope
204 | Y3 Envelope
205 | Y4 Envelope Rotated
206 | Y6 Envelope
207 | Y6 Envelope Rotated
208 | 4" × 6"
209 | 4" × 8"
210 | 5" × 7"
211 | 8" × 10"
212 | 10" × 12"
213 | 14" × 17"
214 | Business Card
215 | Credit Card
216 | Color
217 | Grayscale
218 | Monochrome
219 | Automatic
220 | Draft
221 | Fax
222 | High
223 | Normal
224 | Photographic
225 | Text
226 | 1
227 | 2
228 | 4
229 | 6
230 | 9
231 | 16
232 | Horizontal
233 | Horizontal Reverse
234 | Vertical
235 | Vertical Reverse
236 | Auto Fit
237 | 25%
238 | 50%
239 | 75%
240 | 100%
241 | 150%
242 | 200%
243 | Custom
244 | Default
245 | None
246 | Minimum
247 | One-Sided
248 | Flip on Short Edge
249 | Flip on Long Edge
250 | Auto Select
251 | Archival
252 | Back-Printing Film
253 | Bond
254 | Card Stock
255 | Continuous-Feed
256 | Standard Envelope
257 | Window Envelope
258 | Fabric
259 | High Resolution
260 | Label
261 | Attached Multipart Forms
262 | Individual Multipart Forms
263 | Film Photographic
264 | Glossy Photographic
265 | High-Gloss Photographic
266 | Matte Photographic
267 | Satin Photographic
268 | Semi-Gloss Photographic
269 | Plain
270 | Continuous Screen
271 | Paged Screen
272 | Stationery
273 | Full Tab Stock
274 | Precut Tab Stock
275 | Transparent
276 | T-Shirt Transfer
277 | Cassette
278 | Tractor
279 | Auto Sheet Feeder
280 | Manual
281 |
282 | Error
283 | More Settings
284 | Collate
285 | Print on Both Sides
286 | Unknown
287 | Ready
288 | Busy
289 | Door Open
290 | Initializing
291 | Exchanging Data
292 | Need Manual Feed
293 | No Toner
294 | Not Available
295 | Offline
296 | Out of Memory
297 | Output Bin Full
298 | Current Page Failed
299 | Paper Jam
300 | Out of Paper
301 | Paper Error
302 | Paused
303 | Deleting Job
304 | Power Save
305 | Printing
306 | Processing
307 | Server Unknown
308 | Toner Low
309 | Need User Intervention
310 | Waiting
311 | Warming Up
312 | Page
313 |
314 | Documents:
315 | Location:
316 | Comment:
317 | Custom:
318 | Progress:
319 |
320 | e.g. 1, 3-5, 8
321 |
322 | The value is invalid!
323 | No printer was detected!
324 | Unable to open the printer preferences dialog!
325 | Unable to open the system printer installation dialog!
326 | Unable to start the print job!
327 | The print job was cancelled!
328 | An error occurred during the print job!
329 |
--------------------------------------------------------------------------------
/PrintDialogX/ValueHelpers.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Linq;
3 | using System.Printing;
4 | using System.Reflection;
5 | using System.Collections;
6 | using System.Collections.Generic;
7 | using System.Globalization;
8 | using System.ComponentModel;
9 | using System.Runtime.InteropServices;
10 | using System.Windows;
11 | using System.Windows.Data;
12 | using System.Windows.Media;
13 | using System.Windows.Media.Effects;
14 | using System.Windows.Media.Imaging;
15 | using System.Windows.Shapes;
16 | using System.Windows.Interop;
17 | using System.Windows.Controls;
18 | using System.Windows.Documents;
19 |
20 | namespace PrintDialogX
21 | {
22 | internal class InterfaceToContentConverter : IValueConverter
23 | {
24 | public ResourceDictionary Resources { get; set; } = [];
25 |
26 | public object Convert(object value, Type type, object parameter, CultureInfo culture)
27 | {
28 | if (value is not InterfaceSettings settings || parameter is not ControlTemplate template)
29 | {
30 | return Binding.DoNothing;
31 | }
32 |
33 | ContentControl content = new()
34 | {
35 | Template = template,
36 | Focusable = false
37 | };
38 | content.ApplyTemplate();
39 | if (template.FindName("PART_Basic", content) is Panel basic)
40 | {
41 | ApplyInterface(basic, settings.BasicSettings, Resources);
42 | }
43 | if (template.FindName("PART_Advanced", content) is Panel advanced)
44 | {
45 | ApplyInterface(advanced, settings.AdvancedSettings, Resources);
46 | }
47 |
48 | return content;
49 | }
50 |
51 | public object ConvertBack(object value, Type type, object parameter, CultureInfo culture)
52 | {
53 | return Binding.DoNothing;
54 | }
55 |
56 | public static void ApplyInterface(Panel container, IEnumerable options, ResourceDictionary resources)
57 | {
58 | foreach (InterfaceSettings.Option option in options)
59 | {
60 | container.Children.Add(new ContentControl()
61 | {
62 | Template = (ControlTemplate)resources[option switch
63 | {
64 | InterfaceSettings.Option.Printer => "OptionPrinter",
65 | InterfaceSettings.Option.PrinterPreferences => "OptionPrinterPreferences",
66 | InterfaceSettings.Option.Copies => "OptionCopies",
67 | InterfaceSettings.Option.Collation => "OptionCollation",
68 | InterfaceSettings.Option.Pages => "OptionPages",
69 | InterfaceSettings.Option.Layout => "OptionLayout",
70 | InterfaceSettings.Option.Size => "OptionSize",
71 | InterfaceSettings.Option.Color => "OptionColor",
72 | InterfaceSettings.Option.Quality => "OptionQuality",
73 | InterfaceSettings.Option.PagesPerSheet => "OptionPagesPerSheet",
74 | InterfaceSettings.Option.PageOrder => "OptionPageOrder",
75 | InterfaceSettings.Option.Scale => "OptionScale",
76 | InterfaceSettings.Option.Margin => "OptionMargin",
77 | InterfaceSettings.Option.DoubleSided => "OptionDoubleSided",
78 | InterfaceSettings.Option.Type => "OptionType",
79 | InterfaceSettings.Option.Source => "OptionSource",
80 | _ => "OptionVoid"
81 | }],
82 | Focusable = false
83 | });
84 | }
85 | }
86 |
87 | public static void ApplyLanguage(ResourceDictionary resources, InterfaceSettings.Language language)
88 | {
89 | resources.MergedDictionaries.Add(new()
90 | {
91 | Source = new($"/PrintDialogX;component/Resources/Languages/{language switch
92 | {
93 | InterfaceSettings.Language.zh_CN => "zh-CN",
94 | _ => "en-US"
95 | }}.xaml", UriKind.Relative)
96 | });
97 | }
98 | }
99 |
100 | internal class ValueToDescriptionConverter : IValueConverter
101 | {
102 | public ResourceDictionary Resources { get; set; } = [];
103 |
104 | public object Convert(object value, Type type, object parameter, CultureInfo culture)
105 | {
106 | return value != null ? GetDescription(value, Resources) : Binding.DoNothing;
107 | }
108 |
109 | public object ConvertBack(object value, Type type, object parameter, CultureInfo culture)
110 | {
111 | return Binding.DoNothing;
112 | }
113 |
114 | public static object GetDescription(object value, ResourceDictionary resources)
115 | {
116 | return value.GetType().GetField(value.ToString() ?? string.Empty)?.GetCustomAttribute(typeof(DescriptionAttribute)) is DescriptionAttribute description ? resources[description.Description] : value;
117 | }
118 | }
119 |
120 | internal class ComparisonToStateConverter : IValueConverter
121 | {
122 | public enum Comparison
123 | {
124 | Equality,
125 | Threshold
126 | }
127 |
128 | public Comparison Mode { get; set; } = Comparison.Equality;
129 | public object StateTrue { get; set; } = true;
130 | public object StateFalse { get; set; } = false;
131 | public object Fallback { get; set; } = false;
132 | public bool IsInverted { get; set; } = false;
133 |
134 | public object Convert(object value, Type type, object parameter, CultureInfo culture)
135 | {
136 | bool comparison = Mode switch
137 | {
138 | Comparison.Threshold => System.Convert.ToInt32(value) >= System.Convert.ToInt32(parameter),
139 | _ => Equals(value, parameter)
140 | };
141 | return IsInverted ^ comparison ? StateTrue : StateFalse;
142 | }
143 |
144 | public object ConvertBack(object value, Type type, object parameter, CultureInfo culture)
145 | {
146 | return IsInverted ^ Equals(value, StateTrue) ? parameter : Fallback;
147 | }
148 | }
149 |
150 | internal class CollectionToRangeConverter : IValueConverter
151 | {
152 | public int TrimStart { get; set; } = 0;
153 | public int TrimEnd { get; set; } = 0;
154 |
155 | public object Convert(object value, Type type, object parameter, CultureInfo culture)
156 | {
157 | if (value is not IEnumerable collection)
158 | {
159 | return Binding.DoNothing;
160 | }
161 |
162 | List