Click here to Skip to main content
15,892,480 members
Articles / Programming Languages / C#

Flood Fill Algorithms in C# and GDI+

Rate me:
Please Sign up or sign in to vote.
4.76/5 (43 votes)
4 Oct 20033 min read 265.6K   8.5K   80  
Discusses and demonstrates flood fill algorithms in C# with GDI+.
//**********************************************
// Project: Flood Fill Algorithms in C# & GDI+
// File Description: Flood Fill Class
//
// Copyright: Copyright 2003 by Justin Dunlap.
//    Any code herein can be used freely in your own 
//    applications, provided that:
//     * You agree that I am NOT to be held liable for
//       any damages caused by this code or its use.
//     * You give proper credit to me if you re-publish
//       this code.
//**********************************************
using System;
using System.Windows.Forms;
using System.Drawing;
using System.Collections;
using System.Drawing.Imaging;
using System.Diagnostics;
using System.Xml;
using System.IO;
using System.Threading;
using System.Runtime.InteropServices;

namespace FloodFill 
{
	
	public class MainForm : System.Windows.Forms.Form
	{
		private System.Windows.Forms.TextBox textboxFillG;
		private System.Windows.Forms.HScrollBar hscrollbarFillG;
		private System.Windows.Forms.CheckBox checkboxDiagonal;
		private System.Windows.Forms.StatusBarPanel mousepos;
		private System.Windows.Forms.TextBox textboxTolR;
		private System.Windows.Forms.GroupBox groupboxTolerance;
		private System.Windows.Forms.HScrollBar hscrollbarFillR;
		private System.Windows.Forms.TextBox textboxFillR;
		private System.Windows.Forms.StatusBarPanel timetaken;
		private System.Windows.Forms.HScrollBar hscrollbarTolB;
		private System.Windows.Forms.GroupBox groupboxFillColor;
		private System.Windows.Forms.Label labelColorPreview;
		private System.Windows.Forms.Button buttonStop;
		private System.Windows.Forms.TabPage tabAbout;
		private System.Windows.Forms.TextBox textboxTolB;
		private System.Windows.Forms.HScrollBar hscrollbarTolG;
		private System.Windows.Forms.StatusBar statusBar;
		private System.Windows.Forms.HScrollBar hscrollbarFillB;
		private System.Windows.Forms.Panel panel;
		private System.Windows.Forms.TextBox textboxTolG;
		private System.Windows.Forms.TextBox textboxAbout;
		private System.Windows.Forms.HScrollBar hscrollbarTolR;
		private System.Windows.Forms.TabPage tabSettings;
		private System.Windows.Forms.ComboBox comboNamedColor;
		private System.Windows.Forms.RadioButton optFullSpeed;
		private System.Windows.Forms.RadioButton optSlow;
		private System.Windows.Forms.TextBox textboxFillB;
		private System.Windows.Forms.TabControl tabControl;
		private System.Windows.Forms.ComboBox comboFillStyle;
		
		
		
		FloodFiller floodfiller=new FloodFiller();
		DemoFloodFiller demofloodfiller=new DemoFloodFiller();
		AbstractFloodFiller chosenfloodfiller=null;
		
		bool mousedown=false;
		bool slow=false;
		XmlDocument xml=new XmlDocument();
		MainMenu mainMenu=new MainMenu();
		
		Thread thread;
		int time=0;
		
		

		[DllImport("winmm.dll")]
		protected static extern int timeGetTime();
		
		public MainForm()
		{
			InitializeComponent();
			Init();
		}
		
		// THIS METHOD IS MAINTAINED BY THE FORM DESIGNER
		// DO NOT EDIT IT MANUALLY! YOUR CHANGES ARE LIKELY TO BE LOST
		

		
		void InitializeComponent() {
			this.comboFillStyle = new System.Windows.Forms.ComboBox();
			this.tabControl = new System.Windows.Forms.TabControl();
			this.textboxFillB = new System.Windows.Forms.TextBox();
			this.optSlow = new System.Windows.Forms.RadioButton();
			this.optFullSpeed = new System.Windows.Forms.RadioButton();
			this.comboNamedColor = new System.Windows.Forms.ComboBox();
			this.tabSettings = new System.Windows.Forms.TabPage();
			this.hscrollbarTolR = new System.Windows.Forms.HScrollBar();
			this.textboxAbout = new System.Windows.Forms.TextBox();
			this.textboxTolG = new System.Windows.Forms.TextBox();
			this.panel = new System.Windows.Forms.Panel();
			this.hscrollbarFillB = new System.Windows.Forms.HScrollBar();
			this.statusBar = new System.Windows.Forms.StatusBar();
			this.hscrollbarTolG = new System.Windows.Forms.HScrollBar();
			this.textboxTolB = new System.Windows.Forms.TextBox();
			this.tabAbout = new System.Windows.Forms.TabPage();
			this.buttonStop = new System.Windows.Forms.Button();
			this.labelColorPreview = new System.Windows.Forms.Label();
			this.groupboxFillColor = new System.Windows.Forms.GroupBox();
			this.hscrollbarTolB = new System.Windows.Forms.HScrollBar();
			this.timetaken = new System.Windows.Forms.StatusBarPanel();
			this.textboxFillR = new System.Windows.Forms.TextBox();
			this.hscrollbarFillR = new System.Windows.Forms.HScrollBar();
			this.groupboxTolerance = new System.Windows.Forms.GroupBox();
			this.textboxTolR = new System.Windows.Forms.TextBox();
			this.mousepos = new System.Windows.Forms.StatusBarPanel();
			this.checkboxDiagonal = new System.Windows.Forms.CheckBox();
			this.hscrollbarFillG = new System.Windows.Forms.HScrollBar();
			this.textboxFillG = new System.Windows.Forms.TextBox();
			((System.ComponentModel.ISupportInitialize)(this.timetaken)).BeginInit();
			((System.ComponentModel.ISupportInitialize)(this.mousepos)).BeginInit();
			this.SuspendLayout();
			this.groupboxTolerance.SuspendLayout();
			this.groupboxFillColor.SuspendLayout();
			this.tabAbout.SuspendLayout();
			this.tabSettings.SuspendLayout();
			this.tabControl.SuspendLayout();
			// 
			// comboFillStyle
			// 
			this.comboFillStyle.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
			this.comboFillStyle.Location = new System.Drawing.Point(8, 8);
			this.comboFillStyle.Name = "comboFillStyle";
			this.comboFillStyle.Size = new System.Drawing.Size(184, 21);
			this.comboFillStyle.TabIndex = 1;
			this.comboFillStyle.SelectedIndexChanged += new System.EventHandler(this.comboFillStyleSelectedIndexChanged);
			// 
			// tabControl
			// 
			this.tabControl.Controls.AddRange(new System.Windows.Forms.Control[] {
						this.tabAbout,
						this.tabSettings});
			this.tabControl.Location = new System.Drawing.Point(0, 56);
			this.tabControl.Name = "tabControl";
			this.tabControl.SelectedIndex = 0;
			this.tabControl.Size = new System.Drawing.Size(200, 272);
			this.tabControl.TabIndex = 0;
			// 
			// textboxFillB
			// 
			this.textboxFillB.Location = new System.Drawing.Point(136, 96);
			this.textboxFillB.Name = "textboxFillB";
			this.textboxFillB.Size = new System.Drawing.Size(32, 20);
			this.textboxFillB.TabIndex = 5;
			this.textboxFillB.Text = "2";
			this.textboxFillB.TextChanged += new System.EventHandler(this.textboxFillBTextChanged);
			// 
			// optSlow
			// 
			this.optSlow.Location = new System.Drawing.Point(312, 0);
			this.optSlow.Name = "optSlow";
			this.optSlow.TabIndex = 5;
			this.optSlow.Text = "Slow";
			this.optSlow.CheckedChanged += new System.EventHandler(this.optSlowCheckedChanged);
			// 
			// optFullSpeed
			// 
			this.optFullSpeed.Checked = true;
			this.optFullSpeed.Location = new System.Drawing.Point(200, 0);
			this.optFullSpeed.Name = "optFullSpeed";
			this.optFullSpeed.TabIndex = 6;
			this.optFullSpeed.TabStop = true;
			this.optFullSpeed.Text = "Full Speed";
			this.optFullSpeed.CheckedChanged += new System.EventHandler(this.optFullSpeedCheckedChanged);
			// 
			// comboNamedColor
			// 
			this.comboNamedColor.DrawMode = System.Windows.Forms.DrawMode.OwnerDrawFixed;
			this.comboNamedColor.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
			this.comboNamedColor.Location = new System.Drawing.Point(16, 16);
			this.comboNamedColor.Name = "comboNamedColor";
			this.comboNamedColor.Size = new System.Drawing.Size(120, 21);
			this.comboNamedColor.TabIndex = 7;
			this.comboNamedColor.SelectedIndexChanged += new System.EventHandler(this.comboNamedColorSelectedIndexChanged);
			this.comboNamedColor.DrawItem += new System.Windows.Forms.DrawItemEventHandler(this.comboNamedColorDrawItem);
			// 
			// tabSettings
			// 
			this.tabSettings.Controls.AddRange(new System.Windows.Forms.Control[] {
						this.textboxAbout});
			this.tabSettings.Location = new System.Drawing.Point(4, 22);
			this.tabSettings.Name = "tabSettings";
			this.tabSettings.Size = new System.Drawing.Size(192, 246);
			this.tabSettings.TabIndex = 1;
			this.tabSettings.Text = "About";
			// 
			// hscrollbarTolR
			// 
			this.hscrollbarTolR.Location = new System.Drawing.Point(16, 24);
			this.hscrollbarTolR.Maximum = 255;
			this.hscrollbarTolR.Name = "hscrollbarTolR";
			this.hscrollbarTolR.Size = new System.Drawing.Size(112, 16);
			this.hscrollbarTolR.TabIndex = 6;
			this.hscrollbarTolR.Value = 2;
			this.hscrollbarTolR.Scroll += new System.Windows.Forms.ScrollEventHandler(this.hscrollbarTolRScroll);
			// 
			// textboxAbout
			// 
			this.textboxAbout.Location = new System.Drawing.Point(8, 8);
			this.textboxAbout.Multiline = true;
			this.textboxAbout.Name = "textboxAbout";
			this.textboxAbout.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
			this.textboxAbout.Size = new System.Drawing.Size(176, 232);
			this.textboxAbout.TabIndex = 0;
			this.textboxAbout.Text = "";
			// 
			// textboxTolG
			// 
			this.textboxTolG.Location = new System.Drawing.Point(132, 46);
			this.textboxTolG.Name = "textboxTolG";
			this.textboxTolG.Size = new System.Drawing.Size(32, 20);
			this.textboxTolG.TabIndex = 9;
			this.textboxTolG.Text = "2";
			this.textboxTolG.TextChanged += new System.EventHandler(this.textboxTolGTextChanged);
			// 
			// panel
			// 
			this.panel.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 
						| System.Windows.Forms.AnchorStyles.Left) 
						| System.Windows.Forms.AnchorStyles.Right)));
			this.panel.AutoScroll = true;
			this.panel.Location = new System.Drawing.Point(192, 24);
			this.panel.Name = "panel";
			this.panel.Size = new System.Drawing.Size(304, 336);
			this.panel.TabIndex = 0;
			this.panel.MouseUp += new System.Windows.Forms.MouseEventHandler(this.panelMouseUp);
			this.panel.MouseMove += new System.Windows.Forms.MouseEventHandler(this.panelMouseMove);
			this.panel.MouseDown += new System.Windows.Forms.MouseEventHandler(this.panelMouseDown);
			// 
			// hscrollbarFillB
			// 
			this.hscrollbarFillB.LargeChange = 1;
			this.hscrollbarFillB.Location = new System.Drawing.Point(16, 96);
			this.hscrollbarFillB.Maximum = 255;
			this.hscrollbarFillB.Name = "hscrollbarFillB";
			this.hscrollbarFillB.Size = new System.Drawing.Size(120, 16);
			this.hscrollbarFillB.TabIndex = 4;
			this.hscrollbarFillB.Scroll += new System.Windows.Forms.ScrollEventHandler(this.hscrollbarFillBScroll);
			// 
			// statusBar
			// 
			this.statusBar.Location = new System.Drawing.Point(0, 365);
			this.statusBar.Name = "statusBar";
			this.statusBar.Panels.AddRange(new System.Windows.Forms.StatusBarPanel[] {
						this.timetaken,
						this.mousepos});
			this.statusBar.Size = new System.Drawing.Size(496, 16);
			this.statusBar.TabIndex = 3;
			this.statusBar.Text = "statusBar";
			// 
			// hscrollbarTolG
			// 
			this.hscrollbarTolG.Location = new System.Drawing.Point(16, 46);
			this.hscrollbarTolG.Maximum = 255;
			this.hscrollbarTolG.Name = "hscrollbarTolG";
			this.hscrollbarTolG.Size = new System.Drawing.Size(112, 16);
			this.hscrollbarTolG.TabIndex = 8;
			this.hscrollbarTolG.Value = 2;
			this.hscrollbarTolG.Scroll += new System.Windows.Forms.ScrollEventHandler(this.hscrollbarTolGScroll);
			// 
			// textboxTolB
			// 
			this.textboxTolB.Location = new System.Drawing.Point(132, 70);
			this.textboxTolB.Name = "textboxTolB";
			this.textboxTolB.Size = new System.Drawing.Size(32, 20);
			this.textboxTolB.TabIndex = 11;
			this.textboxTolB.Text = "2";
			this.textboxTolB.TextChanged += new System.EventHandler(this.textboxTolBTextChanged);
			// 
			// tabAbout
			// 
			this.tabAbout.Controls.AddRange(new System.Windows.Forms.Control[] {
						this.groupboxFillColor,
						this.groupboxTolerance});
			this.tabAbout.Location = new System.Drawing.Point(4, 22);
			this.tabAbout.Name = "tabAbout";
			this.tabAbout.Size = new System.Drawing.Size(192, 246);
			this.tabAbout.TabIndex = 0;
			this.tabAbout.Text = "Settings";
			// 
			// buttonStop
			// 
			this.buttonStop.Enabled = false;
			this.buttonStop.Location = new System.Drawing.Point(48, 336);
			this.buttonStop.Name = "buttonStop";
			this.buttonStop.Size = new System.Drawing.Size(80, 24);
			this.buttonStop.TabIndex = 4;
			this.buttonStop.Text = "Stop";
			this.buttonStop.Click+=new EventHandler(this.buttonStopClick);
			// 
			// labelColorPreview
			// 
			this.labelColorPreview.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D;
			this.labelColorPreview.Location = new System.Drawing.Point(144, 16);
			this.labelColorPreview.Name = "labelColorPreview";
			this.labelColorPreview.Size = new System.Drawing.Size(24, 24);
			this.labelColorPreview.TabIndex = 6;
			// 
			// groupboxFillColor
			// 
			this.groupboxFillColor.Controls.AddRange(new System.Windows.Forms.Control[] {
						this.comboNamedColor,
						this.labelColorPreview,
						this.textboxFillB,
						this.hscrollbarFillB,
						this.textboxFillG,
						this.hscrollbarFillG,
						this.textboxFillR,
						this.hscrollbarFillR});
			this.groupboxFillColor.Location = new System.Drawing.Point(8, 112);
			this.groupboxFillColor.Name = "groupboxFillColor";
			this.groupboxFillColor.Size = new System.Drawing.Size(176, 128);
			this.groupboxFillColor.TabIndex = 1;
			this.groupboxFillColor.TabStop = false;
			this.groupboxFillColor.Text = "Fill Color";
			// 
			// hscrollbarTolB
			// 
			this.hscrollbarTolB.Location = new System.Drawing.Point(16, 70);
			this.hscrollbarTolB.Maximum = 255;
			this.hscrollbarTolB.Name = "hscrollbarTolB";
			this.hscrollbarTolB.Size = new System.Drawing.Size(112, 16);
			this.hscrollbarTolB.TabIndex = 10;
			this.hscrollbarTolB.Value = 2;
			this.hscrollbarTolB.Scroll += new System.Windows.Forms.ScrollEventHandler(this.hscrollbarTolBScroll);
			// 
			// timetaken
			// 
			this.timetaken.Text = "Time Taken:";
		    this.timetaken.Width=250;
			// 
			// textboxFillR
			// 
			this.textboxFillR.Location = new System.Drawing.Point(136, 48);
			this.textboxFillR.Name = "textboxFillR";
			this.textboxFillR.Size = new System.Drawing.Size(32, 20);
			this.textboxFillR.TabIndex = 1;
			this.textboxFillR.Text = "2";
			this.textboxFillR.TextChanged += new System.EventHandler(this.textboxFillRTextChanged);
			// 
			// hscrollbarFillR
			// 
			this.hscrollbarFillR.LargeChange = 1;
			this.hscrollbarFillR.Location = new System.Drawing.Point(16, 48);
			this.hscrollbarFillR.Maximum = 255;
			this.hscrollbarFillR.Name = "hscrollbarFillR";
			this.hscrollbarFillR.Size = new System.Drawing.Size(120, 16);
			this.hscrollbarFillR.TabIndex = 0;
			this.hscrollbarFillR.Scroll += new System.Windows.Forms.ScrollEventHandler(this.hscrollbarFillRScroll);
			// 
			// groupboxTolerance
			// 
			this.groupboxTolerance.Controls.AddRange(new System.Windows.Forms.Control[] {
						this.textboxTolB,
						this.hscrollbarTolB,
						this.textboxTolG,
						this.hscrollbarTolG,
						this.textboxTolR,
						this.hscrollbarTolR});
			this.groupboxTolerance.Location = new System.Drawing.Point(8, 8);
			this.groupboxTolerance.Name = "groupboxTolerance";
			this.groupboxTolerance.Size = new System.Drawing.Size(176, 96);
			this.groupboxTolerance.TabIndex = 0;
			this.groupboxTolerance.TabStop = false;
			this.groupboxTolerance.Text = "Tolerance";
			// 
			// textboxTolR
			// 
			this.textboxTolR.Location = new System.Drawing.Point(132, 22);
			this.textboxTolR.Name = "textboxTolR";
			this.textboxTolR.Size = new System.Drawing.Size(32, 20);
			this.textboxTolR.TabIndex = 7;
			this.textboxTolR.Text = "2";
			this.textboxTolR.TextChanged += new System.EventHandler(this.textboxTolRTextChanged);
			// 
			// mousepos
			// 
			this.mousepos.Text = "Position: --,--";
			// 
			// checkboxDiagonal
			// 
			this.checkboxDiagonal.Location = new System.Drawing.Point(8, 32);
			this.checkboxDiagonal.Name = "checkboxDiagonal";
			this.checkboxDiagonal.Size = new System.Drawing.Size(152, 16);
			this.checkboxDiagonal.TabIndex = 2;
			this.checkboxDiagonal.Text = "Fill Diagonally";
			this.checkboxDiagonal.CheckedChanged += new System.EventHandler(this.checkboxDiagonalCheckedChanged);
			// 
			// hscrollbarFillG
			// 
			this.hscrollbarFillG.LargeChange = 1;
			this.hscrollbarFillG.Location = new System.Drawing.Point(16, 72);
			this.hscrollbarFillG.Maximum = 255;
			this.hscrollbarFillG.Name = "hscrollbarFillG";
			this.hscrollbarFillG.Size = new System.Drawing.Size(120, 16);
			this.hscrollbarFillG.TabIndex = 2;
			this.hscrollbarFillG.Scroll += new System.Windows.Forms.ScrollEventHandler(this.hscrollbarFillGScroll);
			// 
			// textboxFillG
			// 
			this.textboxFillG.Location = new System.Drawing.Point(136, 72);
			this.textboxFillG.Name = "textboxFillG";
			this.textboxFillG.Size = new System.Drawing.Size(32, 20);
			this.textboxFillG.TabIndex = 3;
			this.textboxFillG.Text = "2";
			this.textboxFillG.TextChanged += new System.EventHandler(this.textboxFillGTextChanged);
			// 
			// MainForm
			// 
			this.ClientSize = new System.Drawing.Size(496, 381);
			this.Controls.AddRange(new System.Windows.Forms.Control[] {
						this.optSlow,
						this.buttonStop,
						this.statusBar,
						this.panel,
						this.checkboxDiagonal,
						this.comboFillStyle,
						this.tabControl,
						this.optFullSpeed});
			this.Text = "Flood Fill Example";
			this.Load += new System.EventHandler(this.MainFormLoad);
			((System.ComponentModel.ISupportInitialize)(this.timetaken)).EndInit();
			((System.ComponentModel.ISupportInitialize)(this.mousepos)).EndInit();
			this.tabControl.ResumeLayout(false);
			this.tabSettings.ResumeLayout(false);
			this.tabAbout.ResumeLayout(false);
			this.groupboxFillColor.ResumeLayout(false);
			this.groupboxTolerance.ResumeLayout(false);
			this.ResumeLayout(false);
		}
		
		
		
		[STAThread]
		public static void Main(string[] args)
		{
			Application.Run(new MainForm());
		}
		
		///<summary>Does all non-designer initialization</summary>
		void Init()
		{
			//load default image
			panel.BackgroundImage=(Image)new Bitmap(@"demo.png");//((File.Exists(@"c:\windows\webshots.bmp")?@"c:\windows\webshots.bmp":"demo.bmp"));
			panel.AutoScrollMinSize=new Size(panel.BackgroundImage.Width,panel.BackgroundImage.Height);
		    //b=panel.BackgroundImage.Clone();
			
			//populate combo boxes
			comboNamedColor.Items.Add("<Custom>");
			comboNamedColor.Items.AddRange(Enum.GetNames(typeof(System.Drawing.KnownColor)));
			comboFillStyle.Items.AddRange(Enum.GetNames(typeof(FloodFillStyle)));
			comboNamedColor.SelectedIndex=0;
			comboFillStyle.SelectedIndex=0;
			
			//make menu (Sorry folks, I didn't use the menu designer, as 
			//at the time I did this, SharpDevelop didn't have a menu designer.)
			this.Menu=mainMenu;
			MenuItem filemenu=new MenuItem("&File", new MenuItem[]{new MenuItem("&Open", new EventHandler(this.MenuClicked),Shortcut.CtrlO),new MenuItem("&Save As", new EventHandler(this.MenuClicked),Shortcut.CtrlS),new MenuItem("-"),new MenuItem("E&xit", new EventHandler(this.MenuClicked),Shortcut.AltF4)});
			mainMenu.MenuItems.Add(filemenu);

			//misc
			statusBar.ShowPanels=true;			
			xml.Load("abouttext.xml");
			
			//raise events to set values
			ChangeFill();
			comboFillStyleSelectedIndexChanged(comboFillStyle,EventArgs.Empty);
		}		
		
		void comboFillStyleSelectedIndexChanged(object sender, System.EventArgs e)
		{
			if(comboFillStyle.SelectedIndex==-1) comboFillStyle.SelectedIndex=0;

			floodfiller.FillStyle=(FloodFillStyle)Enum.Parse(typeof(FloodFillStyle),comboFillStyle.SelectedItem.ToString());
			demofloodfiller.FillStyle=(FloodFillStyle)Enum.Parse(typeof(FloodFillStyle),comboFillStyle.SelectedItem.ToString());
			XmlNodeList nodes=xml.SelectNodes(@"/abouttext/about");
			XmlNode node=null;
			foreach(XmlNode n in nodes)
			{
				if(n.Attributes["id"].InnerText==comboFillStyle.SelectedItem.ToString())
				{
					node=n;
				}
			}
			if (node!=null)
			{
				textboxAbout.Text=node.InnerText;
			}
		}
		
		///<summary>Custom-draws the color combo.  A modified version of Steve McMahon's
		/// owner-drawn combo box in his HLS-To-RGB example, available at www.vbaccelerator.com</summary>
		void comboNamedColorDrawItem(object sender, System.Windows.Forms.DrawItemEventArgs e)
		{
			int itemIndex = e.Index;

			e.DrawBackground();

			if (itemIndex > 0)
			{
				string knownColorName = comboNamedColor.Items[itemIndex].ToString();

				Rectangle textRectangle = e.Bounds;
				Rectangle colorRectangle = e.Bounds;			
				colorRectangle.X += 2;
				colorRectangle.Y += 2;
				colorRectangle.Width = 16;
				colorRectangle.Height -= 4;

				KnownColor k = (KnownColor)Enum.Parse(typeof(System.Drawing.KnownColor), knownColorName);
				Color color = Color.FromKnownColor(k);
				SolidBrush colorBrush = new SolidBrush(color);
				e.Graphics.FillRectangle(colorBrush, colorRectangle);
				colorBrush.Dispose();
				e.Graphics.DrawRectangle(SystemPens.ControlDarkDark, colorRectangle);

				textRectangle.X += 20;
				textRectangle.Width -= 20;

				Brush textBrush;
				if ((e.State & DrawItemState.Selected) == DrawItemState.Selected)
				{
					textBrush = SystemBrushes.HighlightText;
				}
				else
				{
					textBrush = SystemBrushes.ControlText;
				}
				e.Graphics.DrawString(knownColorName, e.Font, textBrush, textRectangle);
			}
			else if(itemIndex==0)
			{
				Rectangle textRectangle = e.Bounds;
				Brush textBrush;
				if ((e.State & DrawItemState.Selected) == DrawItemState.Selected)
				{
					textBrush = SystemBrushes.HighlightText;
				}
				else
				{
					textBrush = SystemBrushes.ControlText;
				}
				e.Graphics.DrawString(comboNamedColor.Items[itemIndex].ToString(), e.Font, textBrush, textRectangle);
			}

			if ((e.State & DrawItemState.Focus) == DrawItemState.Focus)
			{
				e.DrawFocusRectangle();
			}			
		}
		
		void checkboxDiagonalCheckedChanged(object sender, System.EventArgs e)
		{
			floodfiller.FillDiagonal=checkboxDiagonal.Checked;
			demofloodfiller.FillDiagonal=checkboxDiagonal.Checked;
		}		
		
		void comboNamedColorSelectedIndexChanged(object sender, System.EventArgs e)
		{
			int itemIndex = comboNamedColor.SelectedIndex;
			if (itemIndex > 0)
			{
				string knownColorName = comboNamedColor.Items[itemIndex].ToString();
				KnownColor k = (KnownColor)Enum.Parse(typeof(System.Drawing.KnownColor), knownColorName);
				Color color = Color.FromKnownColor(k);
				hscrollbarFillR.Value=(int)color.R;
				hscrollbarFillG.Value=(int)color.G;
				hscrollbarFillB.Value=(int)color.B;
				ChangeFill();
			}
		}
		
		//COLOR TOLERANCE
		//***************
		
		//Tolerance TextBox Events
		//------------------------
		void textboxTolRTextChanged(object sender, System.EventArgs e)
		{
			Color textcolor=Color.Black;
			try
			{
				hscrollbarTolR.Value=Int32.Parse(textboxTolR.Text);
				floodfiller.Tolerance[0]=(byte)hscrollbarTolR.Value;
				demofloodfiller.Tolerance[0]=(byte)hscrollbarTolR.Value;
			}catch{
				textcolor=Color.DarkRed;
			}
			textboxTolR.ForeColor=textcolor;
		}
	
		
		void textboxTolGTextChanged(object sender, System.EventArgs e)
		{
			Color textcolor=Color.Black;
			try
			{
				hscrollbarTolG.Value=Int32.Parse(textboxTolG.Text);
				floodfiller.Tolerance[1]=(byte)hscrollbarTolG.Value;
				demofloodfiller.Tolerance[1]=(byte)hscrollbarTolG.Value;
			}catch{
				textcolor=Color.DarkRed;
			}
			textboxTolG.ForeColor=textcolor;			
		}
		void textboxTolBTextChanged(object sender, System.EventArgs e)
		{
			Color textcolor=Color.Black;
			try
			{
				hscrollbarTolB.Value=Int32.Parse(textboxTolB.Text);
				floodfiller.Tolerance[2]=(byte)hscrollbarTolB.Value;
				demofloodfiller.Tolerance[2]=(byte)hscrollbarTolB.Value;
			}catch{
				textcolor=Color.DarkRed;
			}
			textboxTolB.ForeColor=textcolor;
		}

		
		//Color Tolerance Scrollbar Events
		//--------------------------------
		
		void hscrollbarTolRScroll(object sender, System.Windows.Forms.ScrollEventArgs e)
		{
			textboxTolR.Text=hscrollbarTolR.Value.ToString();
			floodfiller.Tolerance[0]=(byte)hscrollbarTolR.Value;
			demofloodfiller.Tolerance[0]=(byte)hscrollbarTolR.Value;
		}
		void hscrollbarTolGScroll(object sender, System.Windows.Forms.ScrollEventArgs e)
		{
			textboxTolG.Text=hscrollbarTolG.Value.ToString();
			floodfiller.Tolerance[1]=(byte)hscrollbarTolG.Value;
			demofloodfiller.Tolerance[1]=(byte)hscrollbarTolG.Value;
		}
		void hscrollbarTolBScroll(object sender, System.Windows.Forms.ScrollEventArgs e)
		{
			textboxTolB.Text=hscrollbarTolB.Value.ToString();
			floodfiller.Tolerance[2]=(byte)hscrollbarTolB.Value;
			demofloodfiller.Tolerance[2]=(byte)hscrollbarTolB.Value;
		}

		
		
		//FILL COLOR
		//**********
		
		//Fill Color Scrollbar Events
		//---------------------------
		
		void hscrollbarFillRScroll(object sender, System.Windows.Forms.ScrollEventArgs e)
		{
			ChangeFill();
		}
		void hscrollbarFillGScroll(object sender, System.Windows.Forms.ScrollEventArgs e)
		{
			ChangeFill();
		}
		void hscrollbarFillBScroll(object sender, System.Windows.Forms.ScrollEventArgs e)
		{
			ChangeFill();
		}
		
		//Fill Color TextBox Events
		//-------------------------
		void textboxFillRTextChanged(object sender, System.EventArgs e)
		{
			Color textcolor=Color.Black;
			try
			{
				hscrollbarFillR.Value=Math.Min(Int32.Parse(textboxFillR.Text),255);
				ChangeFill();
			}catch{
				textcolor=Color.DarkRed;
			}
			textboxFillR.ForeColor=textcolor;
			textboxFillR.Refresh();
		}
		void textboxFillGTextChanged(object sender, System.EventArgs e)
		{
			Color textcolor=Color.Black;
			try
			{
				hscrollbarFillG.Value=Math.Min(Int32.Parse(textboxFillG.Text),255);
				ChangeFill();
			}catch{
				textcolor=Color.DarkRed;
			}
			textboxFillG.ForeColor=textcolor;
			textboxFillG.Refresh();
		}
		void textboxFillBTextChanged(object sender, System.EventArgs e)
		{
			Color textcolor=Color.Black;
			try
			{
				hscrollbarFillB.Value=Math.Min(Int32.Parse(textboxFillB.Text),255);
				ChangeFill();
			}catch{
				textcolor=Color.DarkRed;
			}
			textboxFillB.ForeColor=textcolor;
			textboxFillB.Refresh();
		}
		
		void ChangeFill()
		{
			floodfiller.FillColor=ColorTranslator.FromWin32(FloodFiller.RGB((byte)hscrollbarFillR.Value,(byte)hscrollbarFillG.Value,(byte)hscrollbarFillB.Value));
			demofloodfiller.FillColor=ColorTranslator.FromWin32(FloodFiller.RGB((byte)hscrollbarFillR.Value,(byte)hscrollbarFillG.Value,(byte)hscrollbarFillB.Value));
			this.labelColorPreview.BackColor=floodfiller.FillColor;
			Color color=floodfiller.FillColor;
			textboxFillR.Text=color.R.ToString();
			textboxFillG.Text=color.G.ToString();
			textboxFillB.Text=color.B.ToString();
			
			//Color[]Values=(Color[])
			KnownColor[] Values=(KnownColor[])Enum.GetValues(typeof(System.Drawing.KnownColor));
			int i=0;
			foreach(KnownColor val in Values)
			{
				i++;
				
				if(Color.FromKnownColor(val)==color)
				{
					
					comboNamedColor.SelectedIndex=i;
					return;
				}
			}
			comboNamedColor.SelectedIndex=0;
		}
		
		void panelMouseDown(object sender, System.Windows.Forms.MouseEventArgs ev)
		{
			mousedown=true;
		}
		
		void panelMouseUp(object sender, System.Windows.Forms.MouseEventArgs ev)
		{
			//make sure :
			//1) we recieved a mousedown message before this
			//2) the coordinates are not above the top of the bitmap
			if(!mousedown || ev.X-panel.AutoScrollPosition.X<0 || ev.Y-panel.AutoScrollPosition.Y<0) return;
			
			
			if (ev.Button==System.Windows.Forms.MouseButtons.Left) //if the left button was pressed
			{
				if(thread==null)//if there's not a thread already doing something
				{
					time=timeGetTime();
					
					//choose the floodfiller to use
					chosenfloodfiller=(AbstractFloodFiller)(slow?(AbstractFloodFiller)demofloodfiller:(AbstractFloodFiller)floodfiller);
					//get the actual point that was clicked on the bitmap
					Point Pt=new Point(ev.X-panel.AutoScrollPosition.X,ev.Y-panel.AutoScrollPosition.Y);
					
					Pt.X%= panel.BackgroundImage.Width;
					Pt.Y%= panel.BackgroundImage.Height;
					
					//initialize the data - we can't pass it directly
					chosenfloodfiller.Pt=Pt;
					
                    Bitmap b=null;
					if(slow)
					{
					    b=(Bitmap)panel.BackgroundImage.Clone();
					}
					else
				    {
				        b=(Bitmap)panel.BackgroundImage;
				        //panel.SuspendLayout();
				        //panel.BackgroundImage=null;
				    }
					chosenfloodfiller.Bmp=b;
					
					
					if(slow)
					{
    					//create and start the thread
    					thread=new Thread(new ThreadStart(chosenfloodfiller.FloodFill));
    					//thread.IsBackground=true;
    					//if(!slow) thread.Priority=ThreadPriority.AboveNormal;//jack up the priority a bit
    					thread.Start();
    					Thread.Sleep(0);//yield
					}
					else
					{
					    chosenfloodfiller.FloodFill();
					}
					buttonStop.Enabled=true;
				}
			}
		}
		
		void panelMouseMove(object sender, System.Windows.Forms.MouseEventArgs e)
		{
			statusBar.Panels[1].Text="Position: " + (e.X-panel.AutoScrollPosition.X).ToString()+", " + (e.Y-panel.AutoScrollPosition.Y).ToString();
		}
		
		void MainFormLoad(object sender, System.EventArgs e)
		{
			ChangeFill();
			floodfiller.FillFinished+=new FillFinishedEventHandler(this.FillFinished);		
			demofloodfiller.FillFinished+=new FillFinishedEventHandler(this.FillFinished);		
			demofloodfiller.FillProgress+=new FillProgressEventHandler(this.FillProgress);		
			
		}
		
		void MenuClicked(object sender, System.EventArgs e)
		{
			MenuItem menu=(MenuItem)sender;
			switch(menu.Text)
			{
				case "&Open":
					OpenBitmap();
					break;
				case "&Save As":
					SaveBitmap();
					break;
				case "E&xit":
					Application.Exit();
					break;
			}
		}

		///<summary>Called by the DemoFloodFiller when it has filled a pixel</summary>
		public void FillProgress(object sender, FillProgressEventArgs e)
		{
			//Invoke OnProgress so it will be called on the native thread.
			this.Invoke(new FillProgressEventHandler(this.OnProgress),new object[] {sender,e});
		}
		
		private void OnProgress(object sender, FillProgressEventArgs e)
		{			
			((Bitmap)panel.BackgroundImage).SetPixel(e.CurrentPt.X,e.CurrentPt.Y,floodfiller.FillColor);
			panel.Refresh();			
		}
		
		//called by the flood filler when it is finished
		public void FillFinished(object sender, FillFinishedEventArgs ev)
		{
			//exception handling
			if(ev.exception!=null && ev.exception.GetType()!=typeof(System.Threading.ThreadAbortException))
			MessageBox.Show(String.Format("An error of type '{0}' occurred when using the {1} algorithm.",ev.exception.ToString(),Enum.GetName(typeof(FloodFillStyle),floodfiller.FillStyle)));
			
			//join and close the floodfill thread
			if(thread!=null) thread.Join();
			thread=null;
			
			//update image
			panel.ResumeLayout();
			panel.BackgroundImage=(Image)chosenfloodfiller.Bmp;
			panel.Refresh();
			
			//update the statusbar & button
			statusBar.Panels[0].Text="Time Taken - " + " Fill: " + floodfiller.TimeBenchmark + ",  Total: " + (timeGetTime()-time);
			buttonStop.Enabled=false;
		}
		
		void optFullSpeedCheckedChanged(object sender, System.EventArgs e)
		{
			slow=false;
		}
		
		void optSlowCheckedChanged(object sender, System.EventArgs e)
		{
			slow=true;
		}
		
		void buttonStopClick(object sender, System.EventArgs e)
		{
			if(thread!=null)
			{
				thread.Abort();
				thread=null;
			}
		}
		
		
		void OpenBitmap()
		{
			OpenFileDialog dlg=new OpenFileDialog();

			//get available image format decoders, and create a filter string from them
			//TODO: Filter out metafile formats!
			ImageCodecInfo[] decoders=System.Drawing.Imaging.ImageCodecInfo.GetImageDecoders();
			string allfiltersname="All Supported Bitmap Files (";
			string allfilters="";
			ArrayList filters=new ArrayList();
			for(int i=0;i<decoders.GetUpperBound(0);i++)
			{
				allfilters+=(i==0?"":";")+decoders[i].FilenameExtension;
				filters.Add(decoders[i].CodecName+ " (" + decoders[i].FilenameExtension + ")|" + decoders[i].FilenameExtension);
			}
			dlg.Filter=allfiltersname+allfilters+"|"+allfilters+"|"+
					String.Join("|",((string[])(filters.ToArray(typeof(string)))));
			
			
			dlg.Title="Open a Bitmap";
			dlg.ShowDialog((IWin32Window)this);
			
            OpenBitmap(dlg.FileName);
		}
		
		void OpenBitmap(string filename)
		{
		    if(filename!="")
			{
				Bitmap b=null;
				try{b = new Bitmap(filename);}
				catch{MessageBox.Show("The bitmap could not be loaded, because there was an error.","Error Loading Bitmap!",MessageBoxButtons.OK,MessageBoxIcon.Error);}
				if(b!=null)
				{
					
					if(b.PixelFormat==PixelFormat.Format32bppArgb || b.PixelFormat==PixelFormat.Format24bppRgb)
					{
						panel.BackgroundImage=(Image)b;
						panel.AutoScrollMinSize=new Size(panel.BackgroundImage.Width,panel.BackgroundImage.Height);
					}else
					{
						MessageBox.Show("The bitmap you selected is the wrong pixel format!  This demo only works with 24bpp RGB and 32bpp ARGB pixel formats.","Wrong Pixel Format!",MessageBoxButtons.OK,MessageBoxIcon.Error);
					}
				}
				
			}
		}
		
		///<summary>Shows Save As dialog, and saves image to a file.</summary>
		void SaveBitmap()
		{
			if(panel.BackgroundImage==null)return;
			ImageCodecInfo[] encoders=System.Drawing.Imaging.ImageCodecInfo.GetImageEncoders();
			//ImageCodecInfo encoder;
			
			SaveFileDialog dlg=new SaveFileDialog();
			
			string allfiltersname="All Supported Bitmap Files (";
			string allfilters="";
			ArrayList filters=new ArrayList();
			for(int i=0;i<encoders.GetUpperBound(0);i++)
			{
				allfilters+=(i==0?"":";")+encoders[i].FilenameExtension;
				filters.Add(encoders[i].FormatDescription+ " (" + encoders[i].FilenameExtension + ")|" + encoders[i].FilenameExtension);
			}
			dlg.Filter=allfiltersname+allfilters+"|"+allfilters+"|"+
					String.Join("|",((string[])(filters.ToArray(typeof(string)))));
			

			dlg.DefaultExt="*.bmp";
			dlg.OverwritePrompt=true;
			dlg.Title="Save a Bitmap";
			dlg.ShowDialog((IWin32Window)this);
			if (dlg.FileName=="") return; //empty filename means cancel.
			panel.BackgroundImage.Save(dlg.FileName);
		}
	}
	
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
United States United States
My main goal as a developer is to improve the way software is designed, and how it interacts with the user. I like designing software best, but I also like coding and documentation. I especially like to work with user interfaces and graphics.

I have extensive knowledge of the .NET Framework, and like to delve into its internals. I specialize in working with VG.net and MyXaml. I also like to work with ASP.NET, AJAX, and DHTML.

Comments and Discussions