.NET System Information Example

This .NET application is a nice example of printing to multiple pages. It contains one source file. Download the source code: DOTNETSYSINFO.ZIP

using Microsoft.Win32;
using System;
using System.Drawing;
using System.Drawing.Printing;
using System.Windows.Forms;
using System.Reflection;
using System.Text;

namespace SysInfo
{
	internal class SysInfoStrings
	{
		static bool bValid = false;
		static int iCount;
		static string[] asLabels;
		static string[] asValues;

		static SysInfoStrings()
		{
			SystemEvents.UserPreferenceChanged += 
				new UserPreferenceChangedEventHandler(SystemEvents_UserPreferenceChanged);
			SystemEvents.DisplaySettingsChanged += 
				new EventHandler(SystemEvents_DisplaySettingsChanged);
		}

		static void SystemEvents_DisplaySettingsChanged(object sender, EventArgs e)
		{
			bValid = false;
		}

		static void SystemEvents_UserPreferenceChanged(object sender, UserPreferenceChangedEventArgs e)
		{
			bValid = false;
		}

		public static string[] Labels
		{
			get
			{
				GetSysInfo();
				return asLabels;
			}
		}
		public static string[] Values
		{
			get
			{
				GetSysInfo();
				return asValues;
			}
		}
		public static int Count
		{
			get
			{
				GetSysInfo();
				return iCount;
			}
		}

		public static float MaxLabelWidth(Graphics g, Font font)
		{
			return MaxWidth(Labels, g, font);
		}

		public static float MaxValueWidth(Graphics g, Font font)
		{
			return MaxWidth(Values, g, font);
		}

		private static float MaxWidth(string[] astr, Graphics g, Font font)
		{
			float fMax = 0.0F;
			GetSysInfo();
			foreach (string str in astr)
			{
				fMax = Math.Max(fMax, g.MeasureString(str, font).Width);
			}
			return fMax;
		}

		private static void GetSysInfo()
		{
			if (bValid)
				return;

			Type type = typeof(SystemInformation);
			PropertyInfo[] apinfo = type.GetProperties();

			iCount = 0;
			foreach (PropertyInfo pi in apinfo)
			{
				if (pi.CanRead && pi.GetGetMethod().IsStatic) iCount++;
			}

			asLabels = new string[iCount];
			asValues = new string[iCount];

			iCount = 0;
			foreach (PropertyInfo pi in apinfo)
			{
				if (pi.CanRead && pi.GetGetMethod().IsStatic)
				{
					asLabels[iCount] = pi.Name;
					asValues[iCount++] = pi.GetValue(type, null).ToString();
				}
			}

			Array.Sort(asLabels, asValues);
			bValid = true;
		}

	}
	class SysInfo : Form
	{
		protected int iCount, cySpace, iPrintIndex;
		protected string[] asLabels, asValues;
		protected float cxCol;
		private PrintDocument pdoc = new PrintDocument();
		private PrintDialog pdlg = new PrintDialog();
		private PageSetupDialog psdlg = new PageSetupDialog();
		private PrintPreviewDialog prdlg = new PrintPreviewDialog();

		static void Main()
		{
			Application.Run(new SysInfo());
		}

		public SysInfo()
		{
			iPrintIndex = 0;
			Text = "System Information";
			BackColor = SystemColors.Window;
			ForeColor = SystemColors.WindowText;
			AutoScroll = true;

			SystemEvents.UserPreferenceChanged += 
				new UserPreferenceChangedEventHandler(SystemEvents_UserPreferenceChanged);
			SystemEvents.DisplaySettingsChanged += 
				new EventHandler(SystemEvents_DisplaySettingsChanged);
			UpdateAllInfo();

			pdoc.PrintPage += new PrintPageEventHandler(pdoc_PrintPage);
			pdlg.Document = pdoc;
			psdlg.Document = pdoc;
			prdlg.Document = pdoc;

			Menu = new MainMenu();
			Menu.MenuItems.Add("&Print");
			Menu.MenuItems.Add("&Help");
			Menu.MenuItems[0].MenuItems.Add("&Print...", MenuOnPrint);
			Menu.MenuItems[0].MenuItems.Add("Print Pre&view...", MenuOnPrintPreview);
			Menu.MenuItems[0].MenuItems.Add("Page &Setup...", MenuOnPageSetup);
			Menu.MenuItems[1].MenuItems.Add("God, &Help Me!...", MenuOnHelp);
		}

		protected override void OnPaint(PaintEventArgs e)
		{
			Graphics g = e.Graphics;
			SolidBrush br = new SolidBrush(this.ForeColor);
			Point pt = this.AutoScrollPosition;
			int iFirst = (int)((e.ClipRectangle.Top - pt.Y) / (float)cySpace);
			int iLast = (int)((e.ClipRectangle.Bottom - pt.Y) / (float)cySpace);
			iLast = Math.Min(iCount - 1, iLast);
			for (int i = 0; i <= iLast; i++)
			{
				g.DrawString(asLabels[i], this.Font, br, pt.X, pt.Y + i * cySpace);
				g.DrawString(asValues[i], this.Font, br, pt.X + cxCol, pt.Y + i * cySpace);
			}
		}

		void pdoc_PrintPage(object sender, PrintPageEventArgs e)
		{
			SolidBrush br = new SolidBrush(this.ForeColor);
			RectangleF rectf = new RectangleF(
				e.MarginBounds.Left - (e.PageBounds.Width - e.Graphics.VisibleClipBounds.Width) / 2, 
				e.MarginBounds.Top - (e.PageBounds.Height - e.Graphics.VisibleClipBounds.Height) / 2, 
				e.MarginBounds.Width, 
				e.MarginBounds.Height);
			float iLinesPerPage = (int)(rectf.Bottom - rectf.Top) / this.Font.Height;
			for (int i = 0; iPrintIndex < asValues.Length && i < iLinesPerPage; i++)
			{
				e.Graphics.DrawString(asLabels[iPrintIndex], this.Font, 
					br, rectf.Left, rectf.Top + i * this.Font.Height);
				e.Graphics.DrawString(asValues[iPrintIndex], this.Font, 
					br, rectf.Left + cxCol, rectf.Top + i * this.Font.Height);
				iPrintIndex++;
			}
			if (iPrintIndex < asValues.Length)
				e.HasMorePages = true;
			else
				iPrintIndex = 0;
		}

		void MenuOnHelp(object sender, EventArgs e)
		{
			MessageBox.Show("Keep praying... maybe help will come", "Help System");
		}

		void MenuOnPrint(object sender, EventArgs e)
		{
			if (pdlg.ShowDialog() == DialogResult.OK)
			{
				pdoc.DocumentName = Text;
				pdoc.Print();
			}
		}

		void MenuOnPrintPreview(object sender, EventArgs e)
		{
			prdlg.ShowDialog();
		}

		void MenuOnPageSetup(object sender, EventArgs e)
		{
			psdlg.ShowDialog();
		}

		private void SystemEvents_DisplaySettingsChanged(object sender, EventArgs e)
		{
			UpdateAllInfo();
			Invalidate();
		}

		private void SystemEvents_UserPreferenceChanged(object sender, UserPreferenceChangedEventArgs e)
		{
			UpdateAllInfo();
			Invalidate();
		}

		void UpdateAllInfo()
		{
			iCount = SysInfoStrings.Count;
			asLabels = SysInfoStrings.Labels;
			asValues = SysInfoStrings.Values;

			using(Graphics g = this.CreateGraphics())
			{
				SizeF szf = g.MeasureString(" ", this.Font);
				cxCol = szf.Width + SysInfoStrings.MaxLabelWidth(g, this.Font);
				cySpace = Font.Height;
				this.AutoScrollMinSize = new Size(
					(int)Math.Ceiling(cxCol + SysInfoStrings.MaxValueWidth(g, this.Font)),
					(int)Math.Ceiling((double)cySpace * iCount)
					);
			}
		}
		protected override void OnKeyDown(KeyEventArgs e)
		{
			Point pt = AutoScrollPosition;
			pt.X = -pt.X;
			pt.Y = -pt.Y;
			switch (e.KeyCode)
			{
				case Keys.Right:
					if ((e.Modifiers & Keys.Control) == Keys.Control)
						pt.X += ClientSize.Width;
					else
						pt.X += Font.Height;
					break;
				case Keys.Left:
					if ((e.Modifiers & Keys.Control) == Keys.Control)
						pt.X -= ClientSize.Width;
					else
						pt.X -= Font.Height;
					break;
				case Keys.Down:
					pt.Y += Font.Height;
					break;
				case Keys.Up:
					pt.Y -= Font.Height;
					break;
				case Keys.PageDown:
					pt.Y += (int)(Font.Height * (ClientSize.Height / (float)Font.Height));
					break;
				case Keys.PageUp:
					pt.Y -= (int)(Font.Height * (ClientSize.Height / (float)Font.Height));
					break;
				case Keys.Home:
					pt = Point.Empty;
					break;
				case Keys.End:
					pt.Y = 1000000;
					break;
			}
			AutoScrollPosition = pt;
		}
	}
}