基本信息
源码名称:winform 打印示例代码
源码大小:9.87KB
文件格式:.rar
开发语言:C#
更新时间:2015-09-21
×
请留下您的邮箱,我们将在2小时内将文件发到您的邮箱
源码介绍
// Version 2.2 // C# // Accept control other than a Form // You can add your own print functions for specific controls and for report title formatting // Controls can expand // Expendable TextBox multiline added // Expandable ListBox added // Expendable FlexGrid added (Grid from Component One : code in comments only [no references] ) // DataGrid printing // More comments in source code // Report printed can continue on many pages // Can display a trace of controls printed // Can print page number using your own String.Format // Report can be print to a multiframe Tif file (example: for faxing) // Better algorithm to compute extension of container control with rezizable side by side childs // Test using System; using System.Drawing; using System.Drawing.Printing; using System.Collections; using System.Windows.Forms; using System.Data; using System.Drawing.Imaging; namespace FormPrinting { public class FormPrinting { #region "public section" // publics property that can be changed public bool TextBoxBoxed = false; // box around TextBox controls public bool TabControlBoxed = true; // box around TabControl controls public bool LabelInBold = true; // Print all labels in bold public bool PrintPreview = true; // enabled Print preview instead of direct printing public bool DisabledControlsInGray = false; // Color for disabled controls public bool PageNumbering = false; //If true, reserve space at the bottom of each page and print page number public string PageNumberingFormat = "Page {0}"; // String format for page number public OrientationENum Orientation = OrientationENum.Automatic; // choose print orientation (Automatic, Protrait or Landscape) public ControlPrinting DelegatePrintingReportTitle; // Function that will print report title. Can be changed //public bool ControlsCanExpand = true; // Indicate if class accept control's expansion public Single TopMargin = -1; //If < 0, use default margin, else use this public Single BottomMargin = -1; //If < 0, use default margin, else use this public HorizontalAlignment HAlignment = HorizontalAlignment.Center; public System.Drawing.Printing.PageSettings PageSettings; public enum OrientationENum { Automatic = 1, Portrait = 2, Lanscape = 3 } public enum ParentControlPrinting { BeforeChilds = 1, AfterChilds = 2, } // delegate for providing of print function by control type public delegate void ControlPrinting(System.Windows.Forms.Control c, ParentControlPrinting typePrint, MultiPageManagement mp, Single x, Single y, ref Single extendedHeight, out bool ScanForChildControls); //Constructor public FormPrinting(System.Windows.Forms.Control f) { _f = f; _TextBoxLikeControl = new ArrayList(); _DelegatesforControls = new ArrayList(); _Pen = new Pen(Color.Black); // add build-in types and functions AddTextBoxLikeControl("ComboBox"); AddTextBoxLikeControl("DateTimePicker"); AddTextBoxLikeControl("DateTimeSlicker"); AddTextBoxLikeControl("NumericUpDown"); AddDelegateToPrintControl("TextBox", new ControlPrinting(PrintTextBox)); AddDelegateToPrintControl("System.Windows.Forms.Label", new ControlPrinting(PrintLabel)); AddDelegateToPrintControl("System.Windows.Forms.CheckBox", new ControlPrinting(PrintCheckBox)); AddDelegateToPrintControl("System.Windows.Forms.RadioButton", new ControlPrinting(PrintRadioButton)); AddDelegateToPrintControl("System.Windows.Forms.GroupBox", new ControlPrinting(PrintGroupBox)); AddDelegateToPrintControl("System.Windows.Forms.Panel", new ControlPrinting(PrintPanel)); AddDelegateToPrintControl("System.Windows.Forms.TabControl", new ControlPrinting(PrintTabControl)); AddDelegateToPrintControl("System.Windows.Forms.PictureBox", new ControlPrinting(PrintPictureBox)); AddDelegateToPrintControl("System.Windows.Forms.ListBox", new ControlPrinting(PrintListBox)); AddDelegateToPrintControl("System.Windows.Forms.DataGrid", new ControlPrinting(PrintDataGrid)); } /// <summary> /// Let user add TextBox like control type name /// </summary> /// <param name="stringType">TextBox like control type name</param> public void AddTextBoxLikeControl(string stringType) { _TextBoxLikeControl.Add(stringType); } /// <summary> /// Let users provide their own print function for specific control type /// </summary> /// <param name="stringType">Control type name</param> /// <param name="printFunction">function (must match with FormPrinting.ControlPrinting delegate)</param> public void AddDelegateToPrintControl(string stringType, ControlPrinting printFunction) { _DelegateforControls d = new _DelegateforControls(); d.typ = stringType; d.PrintFunction = printFunction; _DelegatesforControls.Add(d); } #endregion #region "Private data" // private Font _printFont; private Pen _Pen; private Brush _Brush; private System.Windows.Forms.Control _f; private ArrayList _TextBoxLikeControl; private System.Single _xform; private ArrayList _DelegatesforControls; private MultiPageManagement _MultiPage; private System.Text.StringBuilder _traceLog; private int _indent; private class _DelegateforControls { public string typ; public ControlPrinting PrintFunction; } #endregion #region "Managing PrintDocument or TIF object" /// <summary> /// Launch printing. Calculate start position and orientation /// </summary> public void Print() { try { PrintDocument pd = new PrintDocument(); if (this.PageSettings != null) { pd.DefaultPageSettings = this.PageSettings; } InitPrinting(ref pd); pd.PrintPage = new PrintPageEventHandler(this.pd_PrintPage); pd.DocumentName = _f.Text; if (PrintPreview) { PrintPreviewDialog pp = new PrintPreviewDialog(); pp.Document = pd; pp.WindowState = FormWindowState.Maximized; pp.ShowDialog(); } else { pd.Print(); } } catch (Exception ex) { MessageBox.Show(ex.ToString()); } } public void PrintToTifFile(string fileName) { try { // Compute bitmap propertiy about same as default printer PrintDocument pd = new PrintDocument(); InitPrinting(ref pd); System.Drawing.Bitmap bitmapAllPages, bitmapAdditionnalPage; bitmapAllPages = new Bitmap(pd.DefaultPageSettings.Bounds.Width, pd.DefaultPageSettings.Bounds.Height); bitmapAdditionnalPage = new Bitmap(pd.DefaultPageSettings.Bounds.Width, pd.DefaultPageSettings.Bounds.Height); Graphics g; //Prepare parameters to save multiframe image System.Drawing.Imaging.EncoderParameters eps; eps = new System.Drawing.Imaging.EncoderParameters(); bool firstPage = true; // Print pages do { if (firstPage) g = Graphics.FromImage(bitmapAllPages); else g = Graphics.FromImage(bitmapAdditionnalPage); g.Clear(System.Drawing.Color.White); _MultiPage.NewPage(g); Single extendedHeight; Single y; y = 0; extendedHeight = 0; bool scanForChildControls; if (DelegatePrintingReportTitle == null) PrintReportTitle(_f, ParentControlPrinting.BeforeChilds , _MultiPage, _xform, y, ref extendedHeight, out scanForChildControls); else DelegatePrintingReportTitle(_f, ParentControlPrinting.BeforeChilds , _MultiPage, _xform, y, ref extendedHeight, out scanForChildControls); y = extendedHeight; // Print each control on the form Single globalExtendedHeight; PrintControls(_f, _MultiPage, _xform, y, out globalExtendedHeight); if(firstPage) { //Create the parameter and choose multi-frame eps.Param[0]=new EncoderParameter(Encoder.SaveFlag,(long)EncoderValue.MultiFrame); //Get the correct encoder from the list of available encoders ImageCodecInfo[] infos=ImageCodecInfo.GetImageEncoders(); int n=0; while(infos[n].MimeType!="image/tiff") n ; //save the first page bitmapAllPages.Save(fileName ".tif",infos[n],eps); } else { //Create the parameter and choose FrameDimensionPage eps.Param[0]=new EncoderParameter(Encoder.SaveFlag,(long)EncoderValue.FrameDimensionPage); //save the first page bitmapAllPages.SaveAdd(bitmapAdditionnalPage,eps); } firstPage = false; } while (!_MultiPage.LastPage()); // Flush pages to file eps.Param[0]=new EncoderParameter(Encoder.SaveFlag,(long)EncoderValue.Flush); bitmapAllPages.SaveAdd(eps); } catch (Exception ex) { MessageBox.Show(ex.ToString()); } } public string GetTrace() { return _traceLog.ToString(); } private void InitPrinting(ref PrintDocument pd) { _traceLog = new System.Text.StringBuilder(); _indent = 0; // Calculate Form position for printing switch (Orientation) { case OrientationENum.Automatic: if (_f.Size.Width > (pd.DefaultPageSettings.Bounds.Width - pd.DefaultPageSettings.Margins.Right - pd.DefaultPageSettings.Margins.Left)) pd.DefaultPageSettings.Landscape = true; break; case OrientationENum.Lanscape: pd.DefaultPageSettings.Landscape = true; break; case OrientationENum.Portrait: pd.DefaultPageSettings.Landscape = false; break; } // Set page area Single pageTop = pd.DefaultPageSettings.Margins.Top; Single pageBottom = pd.DefaultPageSettings.Bounds.Height - pd.DefaultPageSettings.Margins.Bottom; Single pageLeft = pd.DefaultPageSettings.Margins.Left; Single pageRight = pd.DefaultPageSettings.Bounds.Width - pd.DefaultPageSettings.Margins.Right; if (TopMargin >= 0) pageTop = TopMargin; if (BottomMargin >= 0) pageBottom = pd.DefaultPageSettings.Bounds.Height - BottomMargin; // Calculate left position of print switch (this.HAlignment) { case HorizontalAlignment.Left: _xform = pageLeft; break; case HorizontalAlignment.Center: _xform = (pd.DefaultPageSettings.Bounds.Width - _f.Size.Width) / 2; break; case HorizontalAlignment.Right: _xform = pageRight - _f.Size.Width; break; } _MultiPage = new MultiPageManagement(pageTop, pageBottom, pageLeft, pageRight, _f.Font, PageNumbering, PageNumberingFormat); } /// <summary> /// Event handler called by the print document engine. Called for each pages /// </summary> /// <param name="sender"></param> /// <param name="ev"></param> private void pd_PrintPage(object sender, PrintPageEventArgs ev) { _MultiPage.NewPage(ev.Graphics); Single extendedHeight; Single y; y = 0; extendedHeight = 0; bool scanForChildControls; if (DelegatePrintingReportTitle == null) PrintReportTitle(_f, ParentControlPrinting.BeforeChilds , _MultiPage, _xform, y, ref extendedHeight, out scanForChildControls); else DelegatePrintingReportTitle(_f, ParentControlPrinting.BeforeChilds , _MultiPage, _xform, y, ref extendedHeight, out scanForChildControls); y = extendedHeight; // Print each control on the form Single globalExtendedHeight; PrintControls(_f, _MultiPage, _xform, y, out globalExtendedHeight); if (_MultiPage.LastPage()) { ev.HasMorePages = false; _MultiPage.ResetPage(); } else ev.HasMorePages = true; } public void PrintReportTitle(System.Windows.Forms.Control c, ParentControlPrinting typePrint, MultiPageManagement mp, Single x, Single y, ref Single extendedHeight, out bool ScanForChildControls) { ScanForChildControls = false; Font printFont = new Font(c.Font.Name, (Single) (c.Font.Size * 1.3), FontStyle.Bold); float fontHeight = mp.FontHeight(printFont); Pen pen = new Pen(Color.Black, 2); extendedHeight = fontHeight 3 pen.Width 1; mp.BeginPrintUnit(y, extendedHeight); mp.DrawString(c.Text, printFont, Brushes.Black, x, y, c.Width, fontHeight); y = fontHeight 3; mp.DrawLines(pen, x, y, x c.Size.Width, y); mp.EndPrintUnit(); } #endregion #region "Recursive printing of controls" /// <summary> /// Print child controls of a "parent" control. /// Controls are printed from top to bottom. /// This is the function that calculate position of each control depending of the extension of child controls /// </summary> /// <param name="c">"parent" control</param> /// <param name="mp">printing page object</param> /// <param name="x">X position of "parent" control</param> /// <param name="y">Y position of "parent" control</param> /// <param name="globalExtendedHeight">necessary height grow of "parent" control to fit with combination of child control growing</param> public void PrintControls(System.Windows.Forms.Control c, MultiPageManagement mp, Single x, Single y, out Single globalExtendedHeight) { int nbCtrl = c.Controls.Count; Single[] yPos = new Single[nbCtrl]; System.Windows.Forms.Control[] controls = new System.Windows.Forms.Control[nbCtrl]; //Do a list of child controls for (int i = 0; i < nbCtrl; i ) { controls[i] = c.Controls[i]; yPos[i] = c.Controls[i].Location.Y; } //Sort them by vertical position System.Array.Sort(yPos, controls); //Print them from top to bottom globalExtendedHeight = 0; //Single globalextendedYPos = 0; System.Collections.ArrayList extendedYPos = new System.Collections.ArrayList(); // ***************************************************************** // This loop over child controls calculate position of them. // Algorithm take care of controls that expand besides and above. // It keep an arraylist of original and printed (after expansion) bottom // position of expanded control. // So control is push down if it was originally below expanded controls // ***************************************************************** for (int i = 0; i < nbCtrl; i ) { // Set y position of control depending of extension of controls above him Single pushDownHeight = 0; foreach (Element e in extendedYPos) if (controls[i].Location.Y >= e.originalBottom) //completely under it { if (e.totalPushDown > pushDownHeight) pushDownHeight = e.totalPushDown; } Single cp = controls[i].Location.Y pushDownHeight; Single extendedHeight; PrintControl(controls[i], mp, x controls[i].Location.X, y cp, out extendedHeight); if (extendedHeight > 0) { //Keep extention with y position Element e = new Element(); e.originalBottom = controls[i].Location.Y controls[i].Height; e.printedBottom = cp controls[i].Height extendedHeight; extendedYPos.Add(e); } } // same computation for bottom of container control. Its bottom line is // below all child controls. So it is extended the same as the most pushed // child control. globalExtendedHeight = 0; foreach (Element e in extendedYPos) if (e.totalPushDown > globalExtendedHeight) globalExtendedHeight = e.totalPushDown; } private class Element { public Single originalBottom; public Single printedBottom; public Single totalPushDown {get {return printedBottom - originalBottom;} } } /// <summary> /// This sub simply use recursivity to print child controls and print /// the parent control (height may grow depending of child controls). /// Extension is push up to the previous parent. /// </summary> /// <param name="c"></param> /// <param name="mp"></param> /// <param name="x"></param> /// <param name="y"></param> /// <param name="extendedHeight"></param> public void PrintControl(System.Windows.Forms.Control c, MultiPageManagement mp, Single x, Single y, out Single extendedHeight) { extendedHeight = 0; if (c.Visible == true) { bool scanForChildControls; try { // Print my header PrintOneControl(c, ParentControlPrinting.BeforeChilds, mp, x, y, ref extendedHeight, out scanForChildControls); // Print Contained controls if (scanForChildControls) { y = extendedHeight; _indent = 1; Single ChildControlsExtendedHeight; PrintControls(c, mp, x, y, out ChildControlsExtendedHeight); _indent -= 1; // Print my bottom (habitually a frame arround child controls) PrintOneControl(c, ParentControlPrinting.AfterChilds, mp, x, y, ref ChildControlsExtendedHeight, out scanForChildControls); extendedHeight = ChildControlsExtendedHeight; } } catch (Exception ex) { MessageBox.Show("Error printing control of type " c.GetType().ToString() System.Environment.NewLine System.Environment.NewLine ex.ToString()); } } } /// <summary> /// Print a control (not is children). Call the print function depending of the type of the control /// </summary> /// <param name="c"></param> /// <param name="mp"></param> /// <param name="x"></param> /// <param name="y"></param> /// <param name="extendedHeight"></param> public void PrintOneControl(System.Windows.Forms.Control c, ParentControlPrinting typePrint, MultiPageManagement mp, Single x, Single y, ref Single extendedHeight, out bool ScanForChildControls) { // Silver color if disable if (c.Enabled || !DisabledControlsInGray) { _Pen = new Pen(Color.Black); _Brush = Brushes.Black; } else { _Pen = new Pen(Color.Silver); _Brush = Brushes.Silver; } ScanForChildControls = true; string s = c.GetType().ToString(); bool founded = false; //First check if it's a text box like control if (!founded) foreach (string sType in _TextBoxLikeControl) if (s.IndexOf(sType) >= 0) { Single h; h = mp.FontHeight(new Font(c.Font.Name, c.Font.Size)); extendedHeight = mp.BeginPrintUnit(y, h); PrintText(c, mp, x, y, TextBoxBoxed, false, TextBoxBoxed, HorizontalAlignment.Left); mp.EndPrintUnit(); founded = true; ScanForChildControls = false; break; } //Process other type of control, beginning at the end of the list (use last add for a type) if (!founded) for (int i = _DelegatesforControls.Count-1; i>=0; i--) // from end to the beginning { _DelegateforControls d = (_DelegateforControls) _DelegatesforControls[i]; if (s.EndsWith(d.typ)) { d.PrintFunction(c, typePrint, mp, x, y, ref extendedHeight, out ScanForChildControls); break; } } _traceLog.Append(_indent.ToString() " - " typePrint.ToString() " " s " (" c.Text ":" c.Name ") X=" x.ToString() " Y=" y.ToString() " H=" c.Height.ToString() " " extendedHeight.ToString() System.Environment.NewLine); } #endregion #region "Text printing" /// <summary> /// Print a single line text for many controls. Do some formatting /// </summary> /// <param name="c">Control to print (must have these properties :font, text, width and height)</param> /// <param name="mp">Graphics object (printed page)</param> /// <param name="x">X position</param> /// <param name="y">Y position</param> /// <param name="tbBoxed">Draw a box arround text</param> /// <param name="inBold">use bold font</param> /// <param name="verticalCentering">Adjust vertical to obtain precise alignment from different type of control</param> /// <param name="hAlignment">Horizontal alignment of text in control print area</param> public void PrintText(System.Windows.Forms.Control c, MultiPageManagement mp, Single x, Single y, bool tbBoxed, bool inBold, bool verticalCentering, HorizontalAlignment hAlignment) { Single yAdjusted = y; //Box if (tbBoxed) mp.DrawRectangle(_Pen, x, y, c.Width, c.Height); //Text Font printFont; if (inBold) printFont = new Font(c.Font.Name, c.Font.Size, FontStyle.Bold); else printFont = new Font(c.Font.Name, c.Font.Size); if (verticalCentering) { Single fontHeight = printFont.GetHeight(mp.Graphics()); Single deltaHeight = (c.Height - fontHeight) / 2; yAdjusted = deltaHeight; } else yAdjusted = 2; mp.DrawString(c.Text, printFont, _Brush, x, yAdjusted, c.Width, c.Height, BuildFormat(hAlignment)); } public StringFormat BuildFormat(HorizontalAlignment hAlignment) { StringFormat drawFormat = new StringFormat(); switch (hAlignment) { case HorizontalAlignment.Left: drawFormat.Alignment = StringAlignment.Near; break; case HorizontalAlignment.Center: drawFormat.Alignment = StringAlignment.Center; break; case HorizontalAlignment.Right: drawFormat.Alignment = StringAlignment.Far; break; } return drawFormat; } public string TrimBlankLines(string s) { if (s == null) return s; else { for (int i = s.Length; i==1; i--) if ((s[i].ToString() != Keys.Enter.ToString()) && (s[i].ToString() != Keys.LineFeed.ToString()) && (s[i].ToString() != " ")) return s.Substring(0, i); return s; } } #endregion #region "Controls printing" /// <summary> /// Print single line or multi lines TextBox. /// </summary> public void PrintTextBox(System.Windows.Forms.Control c, ParentControlPrinting typePrint, MultiPageManagement mp, Single x, Single y, ref Single extendedHeight, out bool ScanForChildControls) { ScanForChildControls = false; TextBox tb = (System.Windows.Forms.TextBox) c; Single h = mp.FontHeight(new Font(tb.Font.Name, tb.Font.Size)); if (!tb.Multiline) { extendedHeight = mp.BeginPrintUnit(y, h); PrintText(c, mp, x, y, TextBoxBoxed, tb.Font.Bold, TextBoxBoxed, tb.TextAlign); mp.EndPrintUnit(); } else //multiline { // cut text into lines that fit in printed textBox width // Define an area of one line height and call MeasureString on it // This method return charactersFitted for the line ArrayList lines = new ArrayList(); System.Drawing.Graphics g = mp.Graphics(); SizeF areaForOneLineOfText = new SizeF(); areaForOneLineOfText.Height = h; areaForOneLineOfText.Width = tb.Width; int charactersFitted; int linesFilled; int separatorCharPos; Font printFont = new Font(tb.Font.Name, tb.Font.Size); int pos = 0; do { g.MeasureString(tb.Text.Substring(pos), printFont, areaForOneLineOfText, new StringFormat(), out charactersFitted, out linesFilled); // this method with one line cut the last word.... // So, I have to go bak in the string to find a separator // Happyly, MeasureString count separator character in charactersFitted // For example, return "this is the first line " with space at the end // even if there is not room for last space separatorCharPos = charactersFitted; if (charactersFitted < tb.Text.Substring(pos).Length) //le restant n'entre pas au complet sur la ligne { do { separatorCharPos --; } while ((separatorCharPos > pos) && !System.Char.IsSeparator(tb.Text, pos separatorCharPos)); if (separatorCharPos == pos) // no separator separatorCharPos = charactersFitted; else separatorCharPos ; } lines.Add(tb.Text.Substring(pos, separatorCharPos)); pos = separatorCharPos; } while ((pos < tb.Text.Length) && (charactersFitted > 0)); // Print lines one by one Single yItem = y; Single extraHeight; Single extraHeightFirstLine = 0; //Remenber if first line is pull down for (int i=0; i < lines.Count; i ) { extraHeight = mp.BeginPrintUnit(yItem, h); //Space required for tab page caption if (i == 0) extraHeightFirstLine = extraHeight; mp.DrawString((string) lines[i], printFont, _Brush, x, yItem, tb.Width, h); mp.EndPrintUnit(); yItem = h extraHeight; } if ((yItem - y) > tb.Height) extendedHeight = (yItem - y) - tb.Height; if (TextBoxBoxed) { _Pen = new Pen(Color.Black); //Draw a rectangle arround list box. Start downer if first line pulled down mp.DrawFrame(_Pen, x, y extraHeightFirstLine, tb.Width, tb.Height extendedHeight - extraHeightFirstLine); } } } public void PrintLabel(System.Windows.Forms.Control c, ParentControlPrinting typePrint, MultiPageManagement mp, Single x, Single y, ref Single extendedHeight, out bool ScanForChildControls) { ScanForChildControls = false; // Convert ContentAlignment (property of labels) to HorizontalAlignment (Left, center, Right) HorizontalAlignment ha ; string ss = c.Text; ContentAlignment ha2 = ((Label) c).TextAlign; switch (ha2) { case ContentAlignment.BottomLeft: ha = HorizontalAlignment.Left; break; case ContentAlignment.TopLeft: ha = HorizontalAlignment.Left; break; case ContentAlignment.MiddleLeft: ha = HorizontalAlignment.Left; break; case ContentAlignment.BottomCenter: ha = HorizontalAlignment.Center; break; case ContentAlignment.TopCenter: ha = HorizontalAlignment.Center; break; case ContentAlignment.MiddleCenter: ha = HorizontalAlignment.Center; break; case ContentAlignment.BottomRight: ha = HorizontalAlignment.Right; break; case ContentAlignment.TopRight: ha = HorizontalAlignment.Right; break; case ContentAlignment.MiddleRight: ha = HorizontalAlignment.Right; break; default: ha = HorizontalAlignment.Left; break; } Single h = mp.FontHeight(new Font(c.Font.Name, c.Font.Size)); if (c.Height > h) h = c.Height; extendedHeight = mp.BeginPrintUnit(y, h); PrintText(c, mp, x, y, false, LabelInBold, false, ha); mp.EndPrintUnit(); } public void PrintCheckBox(System.Windows.Forms.Control c, ParentControlPrinting typePrint, MultiPageManagement mp, Single x, Single y, ref Single extendedHeight, out bool ScanForChildControls) { ScanForChildControls = false; Single h = mp.FontHeight(new Font(c.Font.Name, c.Font.Size)); extendedHeight = mp.BeginPrintUnit(y, h); mp.DrawRectangle(_Pen, x, y, h, h); if ( ((CheckBox) c).Checked ) { Single d = 3; mp.DrawLines(_Pen, x d, y d, x h - d, y h - d); PointF[] points2 = new PointF[] {new PointF(x h - d, y d), new PointF(x d, y h - d)}; mp.DrawLines(_Pen, x h - d, y d, x d, y h - d); } PrintText(c, mp, (float) (x (h * 1.4)), (float) y - 2, false, false, false, HorizontalAlignment.Left); mp.EndPrintUnit(); } public void PrintRadioButton(System.Windows.Forms.Control c, ParentControlPrinting typePrint, MultiPageManagement mp, Single x, Single y, ref Single extendedHeight, out bool ScanForChildControls) { ScanForChildControls = false; Single h = mp.FontHeight(new Font(c.Font.Name, c.Font.Size)); extendedHeight = mp.BeginPrintUnit(y, h); mp.DrawEllipse(_Pen, x, y, h, h); if ( ((RadioButton) c).Checked) { Single d = 3; mp.FillEllipse(_Brush, x d, y d, h - d - d, h - d - d); } PrintText(c, mp, (float) (x (h * 1.4)), y - 2, false, false, false, HorizontalAlignment.Left); mp.EndPrintUnit(); } public void PrintPanel(System.Windows.Forms.Control c, ParentControlPrinting typePrint, MultiPageManagement mp, Single x, Single y, ref Single extendedHeight, out bool ScanForChildControls) { ScanForChildControls = true; if (typePrint == ParentControlPrinting.AfterChilds) if ( ((System.Windows.Forms.Panel) c).BorderStyle != BorderStyle.None) { if (((System.Windows.Forms.Panel) c).BorderStyle == BorderStyle.Fixed3D) _Pen = new Pen(Color.Silver); // if height less than 10, just print an horizontal line if ((c.Height < 10) && (c.Controls.Count == 0)) { extendedHeight = mp.BeginPrintUnit(y, 1); mp.DrawLines(_Pen, x, y, x c.Width, y); mp.EndPrintUnit(); } else mp.DrawFrame(_Pen, x, y, c.Width, c.Height extendedHeight); } } public void PrintGroupBox(System.Windows.Forms.Control c, ParentControlPrinting typePrint, MultiPageManagement mp, Single x, Single y, ref Single extendedHeight, out bool ScanForChildControls) { ScanForChildControls = true; Font printFont = new Font(c.Font.Name, c.Font.Size); Single h = mp.FontHeight(printFont); _Pen = new Pen(Color.Silver); switch (typePrint) { case ParentControlPrinting.BeforeChilds : // if height less than 10, just print an horizontal line if ((c.Height < 10) && (c.Controls.Count == 0)) { extendedHeight = mp.BeginPrintUnit(y, 1); mp.DrawLines(_Pen, x, y, x c.Width, y); mp.EndPrintUnit(); } else { Single extraHeight = mp.BeginPrintUnit(y, h); //Space required for group caption //PrintText(c, mp, x h, y, false, true, false, HorizontalAlignment.Left); mp.DrawString(c.Text, printFont, Brushes.Black, x h, y, c.Width - h - h, h); mp.EndPrintUnit(); extendedHeight = extraHeight; }; break; case ParentControlPrinting.AfterChilds : mp.DrawFrame(_Pen, x, y, c.Width, c.Height extendedHeight); break; } } public void PrintTabControl(System.Windows.Forms.Control c, ParentControlPrinting typePrint, MultiPageManagement mp, Single x, Single y, ref Single extendedHeight, out bool ScanForChildControls) { ScanForChildControls = true; System.Windows.Forms.TabControl tc = (TabControl) c; _Pen = new Pen(Color.Gray); switch (typePrint) { case ParentControlPrinting.BeforeChilds : //Nom du TabPage Single extraHeight = mp.BeginPrintUnit(y, tc.ItemSize.Height); //Space required for tab page caption System.Windows.Forms.TabPage tp = tc.SelectedTab; Font printFont = new Font(tp.Font.Name, tp.Font.Size, FontStyle.Bold); Single h = mp.FontHeight(printFont); if (h > tc.ItemSize.Height) h = tc.ItemSize.Height; mp.DrawString(tp.Text, printFont, Brushes.Black, x, y (tc.ItemSize.Height - h) / 2, tp.Width, h); mp.DrawLines(_Pen, x, y tc.ItemSize.Height, x tc.Width, y tc.ItemSize.Height); mp.EndPrintUnit(); extendedHeight = extraHeight; break; case ParentControlPrinting.AfterChilds : if (TabControlBoxed) mp.DrawFrame(_Pen, x, y, c.Width, c.Height extendedHeight); break; } } public void PrintPictureBox(System.Windows.Forms.Control c, ParentControlPrinting typePrint, MultiPageManagement mp, Single x, Single y, ref Single extendedHeight, out bool ScanForChildControls) { ScanForChildControls = false; extendedHeight = mp.BeginPrintUnit(y, c.Height); PictureBox pic = (PictureBox) c; mp.DrawImage(pic.Image, x, y, c.Width, c.Height); mp.EndPrintUnit(); } public void PrintListBox(System.Windows.Forms.Control c, ParentControlPrinting typePrint, MultiPageManagement mp, Single x, Single y, ref Single extendedHeight, out bool ScanForChildControls) { ScanForChildControls = false; ListBox lb = (ListBox) c; Single yItem = y; Single extraHeight; Single extraHeightFirstLine = 0; //Remenber if first line is pull down Font printFont = new Font(lb.Font.Name, lb.Font.Size, FontStyle.Bold); int oldPos = lb.SelectedIndex; //save position for (int i = 0; i < lb.Items.Count; i ) { extraHeight = mp.BeginPrintUnit(yItem, lb.ItemHeight); //Space required for tab page caption if (i == 0) extraHeightFirstLine = extraHeight; lb.SelectedIndex = i; // set position to obtain Text of current item mp.DrawString(lb.Text, printFont, _Brush, x, yItem, lb.Width, lb.ItemHeight); mp.EndPrintUnit(); yItem = lb.ItemHeight extraHeight; } lb.SelectedIndex = oldPos; //restore position if ((yItem - y) > lb.Height) extendedHeight = (yItem - y) - lb.Height; _Pen = new Pen(Color.Gray); //Draw a rectangle arround list box. Start downer if first line pulled down mp.DrawFrame(_Pen, x, y extraHeightFirstLine, c.Width, c.Height extendedHeight - extraHeightFirstLine); } public void PrintDataGrid(System.Windows.Forms.Control c, ParentControlPrinting typePrint, MultiPageManagement mp, Single x, Single y, ref Single extendedHeight, out bool ScanForChildControls) { ScanForChildControls = false; DataGrid dg = (DataGrid) c; Single extraHeight = 0; Single extraHeightHeaderLine = 0; Font printFont = new Font(dg.Font.Name, dg.Font.Size, FontStyle.Bold); Single h = mp.FontHeight(printFont); // Column header DataGridTableStyle myGridTableStyle; if (dg.TableStyles.Count == 0) { myGridTableStyle = new DataGridTableStyle(); dg.TableStyles.Add(myGridTableStyle); } // Header of each column Single xPos = x; Single yPos = y; Single w; extraHeightHeaderLine = mp.BeginPrintUnit(yPos, h 1); //Space required for header text for (int i = 0; i < dg.TableStyles[0].GridColumnStyles.Count; i ) { string caption = dg.TableStyles[0].GridColumnStyles[i].HeaderText; w = dg.TableStyles[0].GridColumnStyles[i].Width; if (xPos w > x dg.Width) w = x dg.Width - xPos; if (xPos < x dg.Width) mp.DrawString(caption, printFont, _Brush, xPos, yPos, w, h); if (i == 0) // Draw horizontal line below header mp.DrawLines(_Pen, x, yPos h, x dg.Width, yPos h); xPos = w; } mp.EndPrintUnit(); yPos = h 1 extraHeightHeaderLine; // Get dataTable displayed in DataGrid // This function only support DataGrid with DataTable as DataSource // This is the only case I code to obtain data in DataGrid DataTable dt = null; if (dg.DataSource is System.Data.DataTable) dt = (DataTable) dg.DataSource; else if ((dg.DataSource is System.Data.DataSet) && (dg.DataMember != null)) { DataSet ds = (DataSet) dg.DataSource; if (ds.Tables.Contains(dg.DataMember)) dt = ds.Tables[dg.DataMember]; } // Loop on DataRow, with embed loop on columns if (dt != null) foreach (DataRow dr in dt.Rows) { extraHeight = mp.BeginPrintUnit(yPos, h); //Space required for header text xPos = x; for (int i = 0; i < dg.TableStyles[0].GridColumnStyles.Count; i ) { string caption = dr[i].ToString(); w = dg.TableStyles[0].GridColumnStyles[i].Width; if (xPos w > x dg.Width) w = x dg.Width - xPos; if (xPos < x dg.Width) mp.DrawString(caption, printFont, _Brush, xPos, yPos, w, h); xPos = w; }; mp.EndPrintUnit(); yPos = h extraHeight; } // Draw horizontal line at the bottom of DataGrid if (yPos < y dg.Height extraHeightHeaderLine) yPos = y dg.Height extraHeightHeaderLine; mp.BeginPrintUnit(yPos, 1); mp.DrawLines(_Pen, x, yPos, x dg.Width, yPos); mp.EndPrintUnit(); // Finally, Compute extendedHeight if ((yPos - y) > dg.Height) extendedHeight = (yPos - y) - dg.Height; } // public void PrintFlexGrid(System.Windows.Forms.Control c, // ParentControlPrinting typePrint, // MultiPageManagement mp, // Single x, Single y, // ref Single extendedHeight, out bool ScanForChildControls) // { // ScanForChildControls = false; // C1.Win.C1FlexGrid.C1FlexGrid g = (C1.Win.C1FlexGrid.C1FlexGrid) c; // // // print rows and column header (row[0]) // RectangleF r = new RectangleF(); // PointF[] points; // r.Y = y; // r.Height _Pen.Width ; // r.Height = g.Font.GetHeight(ev.Graphics); // // for (int i = 0; i < g.Rows.Count; i ) // each row // { // r.X = x; // for (int j = 0; j<g.Cols.Count; j ) // each column // if ((g.Cols[j].Visible) && (r.X < x g.Width)) //if not out of grid // { // r.Width = g.Cols[j].Width; // if ((r.X r.Width) > (x g.Width)) //overtaking // r.Width = (x g.Width) - r.X; // ev.Graphics.DrawString(g.GetDataDisplay(i,j), g.Font, _Brush, r, new StringFormat()); // r.X = r.Width; // } // r.Y = r.Height; // if (i == 0) //Columns header, Add an horizontal line below // { // r.Y = 1; // points = new PointF[] {new PointF(x, r.Y), new PointF(x g.Width, r.Y)}; // ev.Graphics.DrawLines(_Pen, points); // r.Y = _Pen.Width ; // } // } // // // Add a bottom line // points = new PointF[] {new PointF(x, r.Y), new PointF(x g.Width, r.Y)}; // ev.Graphics.DrawLines(_Pen, points); // r.Y = _Pen.Width ; // // // Compute extendedHeight // if (r.Y > y g.Height) // extendedHeight = r.Y - (y g.Height); // } // StringFormat _StringFormatFromFlexGridAlign(C1.Win.C1FlexGrid.TextAlignEnum fg) // { // StringFormat sf = new StringFormat(); // string s = fg.ToString().ToUpper(); // if (s.IndexOf("LEFT") == 0) // sf.Alignment = System.Drawing.StringAlignment.Near; // if (s.IndexOf("RIGHT") == 0) // sf.Alignment = System.Drawing.StringAlignment.Far; // if (s.IndexOf("CENTER") == 0) // sf.Alignment = System.Drawing.StringAlignment.Center; // return sf; // } #endregion #region "Multi page class" public class MultiPageManagement { private bool _PageOverflow; private Single _realPageTop, _realPageHeight, _UsablePageHeight; private Single _realPageLeft, _realPageRight; private Single _CurrentPageTop, _CurrentPageBottom; private int _PageNumber = 0; //private PrintPageEventArgs _Ev; private Graphics _G; private bool _PrintUnit; private bool _PrintInCurrentPage; private Single _PrintUnitPullDown; private bool _pageNumbering; private Font _FontForPageNumering; private string _PageNumberingFormat; public System.Drawing.Graphics Graphics() { return _G; } // Constructor public MultiPageManagement(Single pageTop, Single pageBottom, Single pageLeft, Single pageRight, Font formFont, bool pageNumbering, string pageNumberingFormat) { _realPageTop = pageTop; _realPageHeight = pageBottom - pageTop; _realPageLeft = pageLeft; _realPageRight = pageRight; _pageNumbering = pageNumbering; if (_pageNumbering) { _PageNumberingFormat = pageNumberingFormat; _FontForPageNumering = new Font(formFont.Name, (Single) (formFont.Size * 0.8)); } } /// <summary> /// Check if items printed below current page /// </summary> /// <returns>Return true if there is need for another page</returns> public bool LastPage() { return (! _PageOverflow); } /// <summary> /// Change page. Reset page properties /// </summary> /// <param name="g">Graphics object</param> public void NewPage(Graphics g) { _G = g; _PageNumber = 1; _UsablePageHeight = _realPageHeight; if (_pageNumbering) { Single fontHeightForPageNumbering = FontHeight(_FontForPageNumering); _UsablePageHeight -= (Single) (fontHeightForPageNumbering * 1.5); // Compute rectangular space for page number RectangleF _recForPageNumbering = new RectangleF(); _recForPageNumbering.X = _realPageLeft; _recForPageNumbering.Y = _realPageTop _realPageHeight - fontHeightForPageNumbering; _recForPageNumbering.Width = _realPageRight - _realPageLeft; _recForPageNumbering.Height = fontHeightForPageNumbering; // impression StringFormat drawFormat = new StringFormat(); drawFormat.Alignment = StringAlignment.Far; _G.DrawString(String.Format(_PageNumberingFormat, _PageNumber), _FontForPageNumering, Brushes.Black, _recForPageNumbering, drawFormat); } _CurrentPageTop = _UsablePageHeight * (_PageNumber - 1); _CurrentPageBottom = _CurrentPageTop _UsablePageHeight; _PageOverflow = false; } public void ResetPage() { _PageNumber = 0; } public Single BeginPrintUnit(Single y, Single neededHeight) { if (neededHeight > _UsablePageHeight) throw new Exception("Needed height cannot exceed 1 page. Page height = " _UsablePageHeight); _PrintUnit = true; // Verify if unit goes accross a page break // if it's the case, calculate vertical push down height to place the // top of unit just below page break Single pageBreakPos; Single printingPos = y; for (pageBreakPos = _UsablePageHeight; pageBreakPos < (y neededHeight); pageBreakPos = _UsablePageHeight) if( (y <= pageBreakPos) && ((y neededHeight - 1) > pageBreakPos) ) //Accross printingPos = pageBreakPos; _PrintUnitPullDown = printingPos - y; // test if unit is in current page else if another page is needed _PrintInCurrentPage = false; if (printingPos neededHeight - 1 > _CurrentPageBottom) _PageOverflow = true; else if (printingPos >= _CurrentPageTop) _PrintInCurrentPage = true; return _PrintUnitPullDown; } private Single _ConvertToPage(Single y) { Single newY = y - _CurrentPageTop _realPageTop; if (_PrintUnit) return newY = _PrintUnitPullDown; return newY; } public void EndPrintUnit() { _PrintUnit = false; } private bool PrintUnitIsInCurrentPage() { if (!_PrintUnit) throw new Exception("Must be in a print unit to print"); return _PrintInCurrentPage; } public Single FontHeight(Font font) { return font.GetHeight(_G); } public void DrawLines(Pen pen, Single x1, Single y1, Single x2, Single y2) { if (PrintUnitIsInCurrentPage()) { Single y1page = _ConvertToPage(y1); Single y2page = _ConvertToPage(y2); PointF[] points = new PointF[2]; points[0].X = x1; points[0].Y = y1page; points[1].X = x2; points[1].Y = y2page; _G.DrawLines(pen, points); } } public void DrawString(string s, Font printFont, Brush brush, Single x, Single y, Single w, Single h) { DrawString(s, printFont, brush, x, y, w, h, new StringFormat()); } public void DrawString(string s, Font printFont, Brush brush, Single x, Single y, Single w, Single h, StringFormat sf) { if (PrintUnitIsInCurrentPage()) { Single yPage = _ConvertToPage(y); RectangleF r = new RectangleF(); r.X = x; r.Y = yPage; r.Width = w; r.Height = h; _G.DrawString(s, printFont, brush, r, sf); } } public void DrawRectangle(Pen pen, Single x, Single y, Single w, Single h) { if (PrintUnitIsInCurrentPage()) { Single yPage = _ConvertToPage(y); _G.DrawRectangle(pen, x, yPage, w, h); } } public void DrawEllipse(Pen pen, Single x, Single y, Single w, Single h) { if (PrintUnitIsInCurrentPage()) { Single yPage = _ConvertToPage(y); _G.DrawEllipse(pen, x, yPage, w, h); } } public void FillEllipse(Brush brush, Single x, Single y, Single w, Single h) { if (PrintUnitIsInCurrentPage()) { Single yPage = _ConvertToPage(y); _G.FillEllipse(brush, x, yPage, w, h); } } public void DrawImage(Image image, Single x, Single y, Single w, Single h) { if (PrintUnitIsInCurrentPage()) { Single yPage = _ConvertToPage(y); _G.DrawImage(image, x, yPage, w, h); } } public void DrawFrame(Pen pen, Single x, Single y, Single w, Single h) { PointF[] points = new PointF[2]; Single yTop = _CurrentPageTop; Single yBottom = _CurrentPageBottom; if (y h <= _CurrentPageTop ) //Bottom of Frame above current page return; if (y >= _CurrentPageBottom) //Top of Frame below current page { _PageOverflow = true; return; } // Assign X coordinate for horizontal lines points[0].X = x; points[1].X = x w; // Draw top line if (y >= _CurrentPageTop) //Top in current page { yTop = y; points[0].Y = _ConvertToPage(yTop); points[1].Y = _ConvertToPage(yTop); _G.DrawLines(pen, points); } // Draw bottom line if (y h <= _CurrentPageBottom) //Bottom in current page { yBottom = y h; points[0].Y = _ConvertToPage(yBottom); points[1].Y = _ConvertToPage(yBottom); _G.DrawLines(pen, points); } else _PageOverflow = true; // Assign Y coordinate for vertical lines points[0].Y = _ConvertToPage(yTop); points[1].Y = _ConvertToPage(yBottom); // Draw left line points[0].X = x; points[1].X = x; _G.DrawLines(pen, points); // Draw right line points[0].X = x w; points[1].X = x w; _G.DrawLines(pen, points); } } #endregion } }