2013-10-03 14 views
6

Mój program: Zawiera formularz z kilkoma polami tekstowymi i jednym przyciskiem. "Drukarka domyślna" jest ustawiona na moim komputerze jako Adobe PDF.Drukowanie formularza/UserControl w języku C#

Mój cel: Chcesz zrobić zrzut ekranu formularza/kontrolki użytkownika, gdy użytkownik kliknie przycisk "Drukuj". Zrzut ekranu jest następnie zapisywany na pulpicie w formacie .pdf.

Mój problem: Mam następujące dwa problemy z kodem:

  1. wielkość Screenshot: Rozmiar ekranu jest zbyt duża i nie pasuje do rozmiaru strony (domyślne rozmiar strony) po wydrukowaniu/konwersji do .pdf. Proszę zapoznać się z dwoma obrazkami poniżej. Chcę, aby cały zrzut ekranu pasował do strony.
  2. 2 Pyta dwa razy, gdzie dokonać konwersji i zapisać: Po kliknięciu przycisku "Formularz wydruku", programy pytają mnie DWÓCH miejsca, gdzie wydrukować/przekonwertować i zapisać plik. Chcę, aby program zapytał mnie tylko raz, gdzie wydrukować i zapisać plik.

Problem 1: Zrzut ekranu przechwycony przez program nie pasuje do strony po wydrukowaniu. Problem 1: The screenshot captured by the program does not fit the page when printed.

Chcę obraz ekranu, aby dopasować tak na jednej stronie .pdf: enter image description here

Kod:

public partial class Form1 : Form 
{ 
    public Form1() 
    { 
     InitializeComponent(); 
     button1.Text = "Print Form"; 
     button1.Click += new EventHandler(button1_Click); 
     printDocument1.PrintPage += new PrintPageEventHandler(printDocument1_PrintPage); 
     this.Controls.Add(button1); 
    } 

    private void button1_Click(object sender, EventArgs e) 
    { 
     CaptureScreen(); 
     printDocument1.Print(); 
    } 

    Bitmap memoryImage; 

    private void CaptureScreen() 
    { 
     Graphics myGraphics = this.CreateGraphics(); 
     Size s = this.Size; 
     memoryImage = new Bitmap(s.Width, s.Height, myGraphics); 
     Graphics memoryGraphics = Graphics.FromImage(memoryImage); 
     memoryGraphics.CopyFromScreen(this.Location.X, this.Location.Y, 0, 0, s); 
    } 

    private void printDocument1_PrintPage(System.Object sender, System.Drawing.Printing.PrintPageEventArgs e) 
    { 
     e.Graphics.DrawImage(memoryImage, 0, 0); 
    } 
} 

Dzięki za pomoc z góry. Jestem początkującym, uczącym się języka C#, a twoja pomoc będzie bardzo doceniana. :)

+1

Spójrz na ten Q/A dla próbki skalowania obrazu C#: http://stackoverflow.com/questions/249587 –

+0

Dla drugiego numeru (podwójne okno dialogowe), to tylko zgadnij, ale spróbuj usunąć ten wiersz 'printDocument1 .PrintPage + = ... 'od twojego konstruktora. Zgaduję, że to już dzieje się wewnątrz 'InitializeComponent()', co oznacza, że ​​jawnie obsługiwać zdarzenie dwa razy. Otwórz plik Form1.Designer.cs, aby sprawdzić, czy istnieją inne rzeczy, które duplikujesz. (Z wyjątkiem wywołania Init wszystko inne w konstruktorze może być zbędne). –

+0

@PaulSasik: Nie. W przypadku problemu 2 usunięcie tego wiersza daje mi biały plik PDF i nie można go zapisać. ._. – Smith

Odpowiedz

3

Ok, to sprawdzić, a zmodyfikowany printDocument1_PrintPage w szczególności:

 private void printDocument1_PrintPage(object sender, PrintPageEventArgs e) 
     { 
      // calculate width and height scalings taking page margins into account 
      var wScale = e.MarginBounds.Width/(float)_memoryImage.Width; 
      var hScale = e.MarginBounds.Height/(float)_memoryImage.Height; 

      // choose the smaller of the two scales 
      var scale = wScale < hScale ? wScale : hScale; 

      // apply scaling to the image 
      e.Graphics.ScaleTransform(scale, scale); 

      // print to default printer's page 
      e.Graphics.DrawImage(_memoryImage, 0, 0); 
     } 

przeniosłem wszystkie zdarzenia wireup w InitializeComponent, gdzie jest zwykle jechać ale to kod bardziej zaangażować:

using System; 
using System.Drawing; 
using System.Drawing.Printing; 
using System.Windows.Forms; 

namespace testScreenCapScale 
{ 
    public partial class Form1 : Form 
    { 
     public Form1() { InitializeComponent(); } 

     private void button1_Click(object sender, EventArgs e) 
     { 
      CaptureScreen(); 
      printDocument1.Print(); 
     } 

     private Bitmap _memoryImage; 

     private void CaptureScreen() 
     { 
      // put into using construct because Graphics objects do not 
      // get automatically disposed when leaving method scope 
      using (var myGraphics = CreateGraphics()) 
      { 
       var s = Size; 
       _memoryImage = new Bitmap(s.Width, s.Height, myGraphics); 
       using (var memoryGraphics = Graphics.FromImage(_memoryImage)) 
       { 
        memoryGraphics.CopyFromScreen(Location.X, Location.Y, 0, 0, s); 
       } 
      } 
     } 

     private void printDocument1_PrintPage(object sender, PrintPageEventArgs e) 
     { 
      // calculate width and height scalings taking page margins into account 
      var wScale = e.MarginBounds.Width/(float)_memoryImage.Width; 
      var hScale = e.MarginBounds.Height/(float)_memoryImage.Height; 

      // choose the smaller of the two scales 
      var scale = wScale < hScale ? wScale : hScale; 

      // apply scaling to the image 
      e.Graphics.ScaleTransform(scale, scale); 

      // print to default printer's page 
      e.Graphics.DrawImage(_memoryImage, 0, 0); 
     } 
    } 
} 

Form1.Designer.cs

namespace testScreenCapScale 
{ 
    partial class Form1 
    { 
     private System.ComponentModel.IContainer components = null; 

     protected override void Dispose(bool disposing) 
     { 
      if (disposing && (components != null)) 
       components.Dispose(); 
      base.Dispose(disposing); 
     } 

     private void InitializeComponent() 
     { 
      this.printDocument1 = new System.Drawing.Printing.PrintDocument(); 
      this.button1 = new System.Windows.Forms.Button(); 
      this.SuspendLayout(); 
      // 
      // printDocument1 
      // 
      this.printDocument1.PrintPage += new System.Drawing.Printing.PrintPageEventHandler(this.printDocument1_PrintPage); 
      // 
      // button1 
      // 
      this.button1.Location = new System.Drawing.Point(64, 220); 
      this.button1.Name = "button1"; 
      this.button1.Size = new System.Drawing.Size(75, 23); 
      this.button1.TabIndex = 0; 
      this.button1.Text = "button1"; 
      this.button1.UseVisualStyleBackColor = true; 
      this.button1.Click += new System.EventHandler(this.button1_Click); 
      // 
      // Form1 
      // 
      this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 
      this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 
      this.ClientSize = new System.Drawing.Size(384, 377); 
      this.Controls.Add(this.button1); 
      this.Name = "Form1"; 
      this.Text = "Form1"; 
      this.ResumeLayout(false); 

     } 

     private System.Drawing.Printing.PrintDocument printDocument1; 
     private System.Windows.Forms.Button button1; 
    } 
} 
+0

Wielkie dzięki! Doceniam twoją pomoc. Spróbuję i przetestuję to. Dzięki jeszcze raz. :) – Smith

+0

@Smith: Tak jak mówiłem, na początek (szybki test) wystarczy skopiować i wkleić zawartość metody 'printDocument1_PrintPage'. Skalowanie jest samoistne i nic więcej nie musi się zmieniać. To obsługa zdarzeń jest bardziej zaangażowana, z którą możesz pracować osobno. –

+0

Fantastyczny! Działa Paul! Jesteś niesamowity .. jeszcze raz dziękuję :) – Smith