using Grpc.Core; using System; using System.Collections.Generic; using System.Drawing; using System.Drawing.Printing; using System.IO; using System.Threading.Tasks; using System.Windows.Forms; using UltraCombos.Utility; using grpc = global::Grpc.Core; using Newtonsoft.Json; namespace TestPrinter { public partial class Form1 : Form { private PrintDocument pdDocument = new PrintDocument(); private PageSetupDialog setupDlg = new PageSetupDialog(); private PrintPreviewDialog previewDlg = new PrintPreviewDialog(); private PageSettings pageSettings; private bool is_preview = false; private bool is_pressed_ok = false; private bool is_loaded_ok = false; private string path = @"printer_settings.json"; //private System.Drawing.Image testing_image; PrinterService service; public enum ScaleMode { ScaleFit = 0, ScaleFill, ScaleFullFit, ScaleFullFill, ScaleFullPageFit, ScaleFullPageFill, MaxNum, } public Form1() { InitializeComponent(); for (int i = 0; i < (int)ScaleMode.MaxNum; ++i) { comboBox1.Items.Add((ScaleMode)(i)); } comboBox1.SelectedIndex = 0; pdDocument.DefaultPageSettings.Landscape = true; pdDocument.PrinterSettings.DefaultPageSettings.Landscape = true; pdDocument.PrintPage += new PrintPageEventHandler(OnPrintPage); PaperSize papersize = null; foreach (PaperSize size in pdDocument.PrinterSettings.PaperSizes) { if(size.PaperName.StartsWith("A4")) { papersize = size; break; } } if (papersize != null) { pdDocument.DefaultPageSettings.PaperSize = papersize; pdDocument.PrinterSettings.DefaultPageSettings.PaperSize = papersize; var hard_area = pdDocument.PrinterSettings.DefaultPageSettings.PrintableArea; Margins margins = new Margins( (int)Math.Round(hard_area.X), (int)Math.Round(hard_area.Y), (int)Math.Round(papersize.Width - (hard_area.X + hard_area.Width)), (int)Math.Round(papersize.Height - (hard_area.Y + hard_area.Height)) ); pdDocument.DefaultPageSettings.Margins = margins; } pageSettings = pdDocument.DefaultPageSettings.Clone() as PageSettings; PrintSettings s = Utils.LoadPrintSettings(path, pageSettings); is_loaded_ok = s != null; if (is_loaded_ok) { pdDocument.DefaultPageSettings = pageSettings.Clone() as PageSettings; comboBox1.SelectedItem = s.ScaleMode; } var options = new List { new Grpc.Core.ChannelOption(ChannelOptions.MaxReceiveMessageLength, int.MaxValue) }; var services = new ServerServiceDefinition[] { Printer.BindService(new PrinterImpl(print_impl)) }; service = new PrinterService(); service.StartServer(options, services, 54578); } RectangleF getPrintableArea() { var rect = pdDocument.DefaultPageSettings.PrintableArea; if (pdDocument.DefaultPageSettings.Landscape) { float tmp = rect.X; rect.X = rect.Y; rect.Y = tmp; tmp = rect.Width; rect.Width = rect.Height; rect.Height = tmp; } return rect; } RectangleF getFullPageArea() { var rect = new RectangleF(0, 0, pdDocument.DefaultPageSettings.PaperSize.Width, pdDocument.DefaultPageSettings.PaperSize.Height); if (pdDocument.DefaultPageSettings.Landscape) { float tmp = rect.Width; rect.Width = rect.Height; rect.Height = tmp; } return rect; } private void OnPrintPage(object sender, PrintPageEventArgs e) { Console.WriteLine("OnPrintPage()"); float dpiX = (float)e.PageSettings.PrinterSettings.DefaultPageSettings.PrinterResolution.X; float dpiY = (float)e.PageSettings.PrinterSettings.DefaultPageSettings.PrinterResolution.Y; e.Graphics.PageUnit = GraphicsUnit.Pixel; e.Graphics.ScaleTransform(dpiX*0.01f, dpiY*0.01f); var printable_area = getPrintableArea(); RectangleF hot_area; switch (comboBox1.SelectedItem) { default: case ScaleMode.ScaleFit: case ScaleMode.ScaleFill: hot_area = RectangleF.Intersect(e.MarginBounds, printable_area); break; case ScaleMode.ScaleFullFit: case ScaleMode.ScaleFullFill: hot_area = printable_area; break; case ScaleMode.ScaleFullPageFit: case ScaleMode.ScaleFullPageFill: hot_area = getFullPageArea(); break; } { var state = e.Graphics.Save(); e.Graphics.TranslateTransform(hot_area.X, hot_area.Y); if(is_preview == false) e.Graphics.TranslateTransform(-printable_area.X, -printable_area.Y); var image = pictureBox.Image; float area_aspect = hot_area.Width / hot_area.Height; float img_aspect = (float)image.Width / image.Height; float x, y, w, h; switch (comboBox1.SelectedItem) { default: case ScaleMode.ScaleFit: case ScaleMode.ScaleFullFit: case ScaleMode.ScaleFullPageFit: if (img_aspect > area_aspect) { w = hot_area.Width; h = w / img_aspect; } else { h = hot_area.Height; w = h * img_aspect; } break; case ScaleMode.ScaleFill: case ScaleMode.ScaleFullFill: case ScaleMode.ScaleFullPageFill: w = hot_area.Width; h = hot_area.Height; break; } x = 0.5f * (hot_area.Width - w); y = 0.5f * (hot_area.Height - h); Rectangle myRect = new Rectangle( (int)Math.Round(x), (int)Math.Round(y), (int)Math.Round(w), (int)Math.Round(h) ); e.Graphics.DrawImage( image, myRect, 0, 0, image.Width, image.Height, GraphicsUnit.Pixel); e.Graphics.Restore(state); } if (is_preview) { e.Graphics.DrawRectangle(new Pen(Color.Red, 1), printable_area.X, printable_area.Y, printable_area.Width, printable_area.Height); e.Graphics.DrawRectangle(new Pen(Color.Blue, 1), e.MarginBounds); is_preview = false; } } private void printer_preview_Click(object sender, EventArgs e) { previewDlg.Document = pdDocument; is_preview = true; previewDlg.ShowDialog(); } private void printer_setup_Click(object sender, EventArgs e) { setupDlg.Document = pdDocument; setupDlg.AllowMargins = true; setupDlg.AllowOrientation = true; setupDlg.AllowPaper = true; setupDlg.AllowPrinter = true; setupDlg.PageSettings = pageSettings; PrintSettings s = Utils.LoadPrintSettings(path, setupDlg.PageSettings); if (is_pressed_ok || s != null) { Utils.FixMarginsBug(setupDlg.PageSettings); } DialogResult ret = setupDlg.ShowDialog(); is_pressed_ok = ret == DialogResult.OK; if (is_pressed_ok) { pdDocument.DefaultPageSettings = setupDlg.PageSettings.Clone() as PageSettings; Utils.SavePrintSettings(path, setupDlg.PageSettings, (ScaleMode)comboBox1.SelectedItem); } } private void print_impl(UltraCombos.Utility.Image request) { var data = request.Content.ToByteArray(); MemoryStream ms = new MemoryStream(data); pictureBox.Image = System.Drawing.Image.FromStream(ms); pdDocument.Print(); Console.WriteLine("print_impl"); } private void printer_scale_mode_Changed(object sender, EventArgs e) { if (pageSettings == null) { return; } Utils.SavePrintSettings(path, pageSettings, (ScaleMode)comboBox1.SelectedItem); } } sealed class Utils { //WTF Bug... static public void FixMarginsBug(PageSettings s) { double left = s.Margins.Left; double right = s.Margins.Right; double top = s.Margins.Top; double Bottom = s.Margins.Bottom; s.Margins.Left = Convert.ToInt32(left * 2.54); s.Margins.Right = Convert.ToInt32(right * 2.54); s.Margins.Top = Convert.ToInt32(top * 2.54); s.Margins.Bottom = Convert.ToInt32(Bottom * 2.54); } static public PrintSettings LoadPrintSettings(string path, PageSettings s) { if (!File.Exists(path)) { return null; } string json = File.ReadAllText(path); var obj = JsonConvert.DeserializeObject(json); if (obj == null) { return null; } obj.To(s); return obj; } static public bool SavePrintSettings(string path, PageSettings s, Form1.ScaleMode scale_mode) { var obj = new PrintSettings(); obj.From(s); obj.ScaleMode = scale_mode; string json = JsonConvert.SerializeObject(obj, Formatting.Indented); File.WriteAllText(path, json); return true; } } public class PrintSettings { public PaperSize PaperSize; public PaperSource PaperSource; public Margins Margins; public bool Landscape; public Form1.ScaleMode ScaleMode; public void To(PageSettings s) { s.PaperSize = PaperSize; s.PaperSource = PaperSource; s.Margins = Margins; s.Landscape = Landscape; } public void From(PageSettings s) { PaperSize = s.PaperSize; PaperSource = s.PaperSource; Margins = s.Margins; Landscape = s.Landscape; } } public class PrinterService { //public int port = 54578; protected Server server; public void StartServer(IEnumerable options, IEnumerable services, int port) { try { server = new Server(options) { Ports = { new ServerPort("0.0.0.0", port, ServerCredentials.Insecure) } }; foreach (var def in services) server.Services.Add(def); server.Start(); //Log("Start Grpc Server"); Console.WriteLine("Start Grpc Server"); } catch (System.Exception e) { //Log(e.Message, LogType.Error); Console.WriteLine(e.Message); } } ~PrinterService() { Shutdown(); } protected void Shutdown() { if (server != null) { try { server.ShutdownAsync().Wait(); server = null; } catch { } } } /* protected void Log(object msg, LogType type = LogType.Log) { Debug.unityLogger.Log(type, $"[Grpc Server] {msg}"); } */ } public class PrinterImpl : Printer.PrinterBase { public delegate void PrintDelegate(UltraCombos.Utility.Image request); public event PrintDelegate onPrint; public PrinterImpl(PrintDelegate func) { onPrint += func; } public override Task Print(UltraCombos.Utility.Image request, grpc::ServerCallContext context) { //throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, "")); onPrint.Invoke(request); return Task.FromResult(new Empty()); } } }