1. Уважаемые участники и гости, 19 октября codeby будет работать в режиме "Только чтение". Регистрация новых участников будет закрыта. 20 октября портал продолжит работу в прежнем режиме.

Paint

Тема в разделе ".NET - WinForms", создана пользователем ilya00, 21 май 2015.

  1. ilya00

    ilya00 Member

    Репутация:
    0
    Регистрация:
    13 янв 2013
    Сообщения:
    23
    Симпатии:
    0
    продолжаю мучить Paint =)) короче щас я так резко продвинулся уже, в общем посмотрите код, проблема в том что все инструменты получаются одного цвета :( что то перемудрил с лямбдами... и еще никак не соображу как мне сделать выделение области (как в паинте), с одной стороны мне кажется это вообще должен быть еще один UserControl, с другой стороны хочется все наследовать от ToolBase...

    Код:
    using System;
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using System.Linq;
    using System.Drawing;
    using System.Drawing.Drawing2D;
    using System.Windows.Forms;
     
     
     
     
    public class PaintBox : UserControl
    {
    	public enum PaintTools : int { Curve, Line, Figure, Eraser };
     
     
     
     
    	public class PaintProperties
    	{
    		public Color Color = Color.Black;
     
     
     
     
    		public int Transparency = 255;
     
     
     
     
    		public int Size = 10;
     
     
     
     
    		public readonly ReadOnlyCollection<Func<Bitmap>> DefaultTextures;
     
     
     
     
    		public Func<Bitmap> Texture;
     
     
     
     
    		public Brush Brush
    		{
    			get
    			{
    				return new TextureBrush(Texture());
    			}
    		}
     
     
     
     
    		public Pen Pen
    		{
    			get
    			{
    				return new Pen(Brush, Size);
    			}
    		}
     
     
     
     
    		public Rectangle GetPaintRect(Point center, int padding = 0)
    		{
    			int x = center.X - Size - padding;
    			int y = center.Y - Size - padding;
    			int width = (Size + padding) * 2 + 1;
    			int height = (Size + padding) * 2 + 1;
    			return new Rectangle(x, y, width, height);
    		}
     
     
     
     
    		public PaintProperties()
    		{
    			var dt = new List<Func<Bitmap>>();
     
     
     
     
    			dt.Add(() =>
    			{
    				var bmp = new Bitmap(100, 100);
    				var gr = Graphics.FromImage(bmp);
    				gr.FillRectangle(new SolidBrush(Color), 0, 0, bmp.Width, bmp.Height);
    				return bmp;
    			});
     
     
     
     
    			dt.Add(() =>
    			{
    				var bmp = new Bitmap(100, 100);
    				var gr = Graphics.FromImage(bmp);
    				var pen = new Pen(Color);
    				for (int i = 0; i < bmp.Height; i += 10)
    					gr.DrawLine(pen, 0, i, bmp.Width, i);
    				return bmp;
    			});
     
     
     
     
    			dt.Add(() =>
    			{
    				var bmp = new Bitmap(100, 100);
    				var gr = Graphics.FromImage(bmp);
    				var pen = new Pen(Color);
    				for (int i = 0; i <= bmp.Width; i += 10)
    					gr.DrawLine(pen, i, 0, i, bmp.Height);
    				return bmp;
    			});
     
     
     
     
    			DefaultTextures = new ReadOnlyCollection<Func<Bitmap>>(dt);
    			Texture = DefaultTextures[0];
    		}
     
     
     
     
    		public PaintProperties(PaintProperties prop) : this()
    		{
    			Color = prop.Color;
    			Transparency = prop.Transparency;
    			Size = prop.Size;
    			Texture = prop.Texture;
    		}
    	}
     
     
     
     
    	private abstract class ToolBase
    	{
    		public PaintProperties Properties = new PaintProperties();
     
     
     
     
    		protected List<Point> Points = new List<Point>();
     
     
     
     
    		public abstract void Draw(Graphics graphics);
     
     
     
     
    		public virtual void Add(Point point)
    		{
    			Points.Add(point);
    		}
     
     
     
     
    		public virtual void Clear()
    		{
    			Points.Clear();
    		}
    	}
     
     
     
     
    	private class Curve : ToolBase
    	{
    		public override void Draw(Graphics graphics)
    		{
    			if (Points.Count > 1)
    				graphics.DrawLines(Properties.Pen, Points.ToArray());
     
     
     
     
    			if (Points.Count == 1)
    				graphics.FillEllipse(Properties.Brush, Properties.GetPaintRect(Points[0]));
    		}
    	}
     
     
     
     
    	private class Line : ToolBase
    	{
    		public override void Draw(Graphics graphics)
    		{
    			if (Points.Count > 1)
    				graphics.DrawLine(Properties.Pen, Points[0], Points[1]);
    		}
     
     
     
     
    		public override void Add(Point point)
    		{
    			if (Points.Count < 2)
    				Points.Add(point);
    			else
    				Points[0] = point;
    		}
    	}
     
     
     
     
    	public PaintProperties Properties = new PaintProperties();
    	public PaintTools CurrentTool = PaintTools.Curve;
    	private ToolBase Tool;
    	private Bitmap Buffer;
    	private List<ToolBase> History = new List<ToolBase>();
    	private const int MaxHystoryLength = 100;
    	private List<ToolBase> HistoryReceive = new List<ToolBase>();
     
     
     
     
    	public PaintBox()
    	{
    		SetStyle(ControlStyles.AllPaintingInWmPaint |
    				 ControlStyles.OptimizedDoubleBuffer |
    				 ControlStyles.UserPaint,
    				 true);
    	}
     
     
     
     
    	protected override void OnLoad(EventArgs e)
    	{
    		base.OnLoad(e);
    		Buffer = new Bitmap(ClientSize.Width, ClientSize.Height);
    		var graphics = Graphics.FromImage(Buffer);
    		graphics.FillRectangle(Brushes.White, 0, 0, Buffer.Width, Buffer.Height);
    	}
     
     
     
     
    	protected override void OnPaintBackground(PaintEventArgs e)
    	{
    		e.Graphics.DrawImageUnscaled(Buffer, Point.Empty);
    	}
     
     
     
     
    	protected override void OnPaint(PaintEventArgs e)
    	{
    		e.Graphics.SmoothingMode = SmoothingMode.HighQuality;
     
     
     
     
    		foreach (var tool in History)
    			tool.Draw(e.Graphics);
     
     
     
     
    		if (Tool != null)
    			Tool.Draw(e.Graphics);
    	}
     
     
     
     
    	protected override void OnMouseMove(MouseEventArgs e)
    	{
    		base.OnMouseMove(e);
    		if (e.Button == MouseButtons.Left)
    		{
    			Tool.Add(e.Location);
    			Invalidate(Tool.Properties.GetPaintRect(e.Location, 5));
    		}
    	}
     
     
     
     
    	protected override void OnMouseDown(MouseEventArgs e)
    	{
    		base.OnMouseMove(e);
    		if (e.Button == MouseButtons.Left)
    		{
    			switch (CurrentTool)
    			{
    				case PaintTools.Curve: Tool = new Curve(); break;
    				case PaintTools.Line: Tool = new Line(); break;
    				default: Tool = null; break;
    			}
    			Tool.Properties = new PaintProperties(Properties);
    		}
    	}
     
     
     
     
    	protected override void OnMouseUp(MouseEventArgs e)
    	{
    		base.OnMouseUp(e);
     
     
     
     
    		if (Tool != null)
    		{
    			History.Add(Tool);
    			HistoryReceive.Clear();
    		}
     
     
     
     
    		Tool = null;
     
     
     
     
    		if (History.Count > MaxHystoryLength)
    		{
    			Rasterize(new[] { History[0] }, Buffer);
    			History.RemoveAt(0);
    		}
     
     
     
     
    		Invalidate();
    	}
     
     
     
     
    	private void Rasterize(IEnumerable<ToolBase> tools, Bitmap bitmap)
    	{
    		var graphics = Graphics.FromImage(bitmap);
    		foreach (var tool in tools)
    			tool.Draw(graphics);
    	}
     
     
     
     
    	public Bitmap Image
    	{
    		get
    		{
    			var result = new Bitmap(Buffer);
    			var graphics = Graphics.FromImage(result);
    			graphics.DrawImageUnscaled(Buffer, Point.Empty);
    			Rasterize(History, result);
    			return result;
    		}
    		set
    		{
    			Buffer = new Bitmap(value);
    		}
    	}
     
     
     
     
    	public bool CanCancel
    	{
    		get
    		{
    			return History.Count > 0;
    		}
    	}
     
     
     
     
    	public bool CanReceive
    	{
    		get
    		{
    			return HistoryReceive.Count > 0;
    		}
    	}
     
     
     
     
    	public void Cancel()
    	{
    		if (CanCancel)
    		{
    			HistoryReceive.Add(History[History.Count - 1]);
    			History.RemoveAt(History.Count - 1);
    			Invalidate();
    		}
    	}
     
     
     
     
    	public void Receive()
    	{
    		if (CanReceive)
    		{
    			History.Add(HistoryReceive[HistoryReceive.Count - 1]);
    			HistoryReceive.RemoveAt(HistoryReceive.Count - 1);
    			Invalidate();
    		}
    	}
    }
    Код:
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows.Forms;
     
     
     
     
    namespace Paint
    {
    	public partial class Form1 : Form
    	{
    		PaintBox pb = new PaintBox { Left = 100, Top = 100, Width = 600, Height = 600 };
    		SaveFileDialog sfdlg = new SaveFileDialog() { Filter = "Image|*.png;*.bmp;*.jpg", DefaultExt = ".png" };
    		ColorDialog cdlg = new ColorDialog();
     
     
     
     
    		public Form1()
    		{
    			InitializeComponent();
     
     
     
     
    			pb.Parent = this;
     
     
     
     
    			var btn = new Button { Parent = this, Text = "Color" };
    			btn.Click += SelectColor;
     
     
     
     
    			int index = 1;
    			btn = new Button { Parent = this, Text = "Fill", Left = 100 };
    			btn.Click += delegate { pb.Properties.Texture = 
    				pb.Properties.DefaultTextures[index++ % pb.Properties.DefaultTextures.Count]; };
     
     
     
     
    			btn = new Button { Parent = this, Text = "Size", Left = 200 };
    			btn.Click += delegate { pb.Properties.Size = (pb.Properties.Size + 2) % 11; };
     
     
     
     
    			btn = new Button { Parent = this, Text = "Transparency", Left = 300 };
    			btn.Click += delegate { pb.Properties.Transparency = (pb.Properties.Transparency + 40) % 255; };
     
     
     
     
    			btn = new Button { Parent = this, Text = "Type", Left = 400 };
    			btn.Click += delegate { pb.CurrentTool = (PaintBox.PaintTools)((int)(pb.CurrentTool + 1) % 2); };
     
     
     
     
    			btn = new Button { Parent = this, Text = "Cancel", Left = 500 };
    			btn.Click += delegate { pb.Cancel(); };
     
     
     
     
    			btn = new Button { Parent = this, Text = "Receive", Left = 600 };
    			btn.Click += delegate { pb.Receive(); };
     
     
     
     
    			btn = new Button { Parent = this, Text = "Save", Left = 700 };
    			btn.Click += SaveDialog;
     
     
     
     
    			Size = new Size(800, 800);
    		}
     
     
     
     
    		private void SaveDialog(object sender, EventArgs e)
    		{
    			if (sfdlg.ShowDialog() == DialogResult.OK)
    				pb.Image.Save(sfdlg.FileName);
    		}
     
     
     
     
    		private void SelectColor(object sender, EventArgs e)
    		{
    			if (cdlg.ShowDialog() == DialogResult.OK)
    				pb.Properties.Color = cdlg.Color;
    		}
    	}
    }
    
    з.ы. в редакторе кодов есть все языки кроме шарпа -_- странно)))
     
  2. ilya00

    ilya00 Member

    Репутация:
    0
    Регистрация:
    13 янв 2013
    Сообщения:
    23
    Симпатии:
    0
    короче с изменением цветов разобрался, оказывается я то присваивал функцию от объекта, она продолжала на него ссылаться и цвет менялся соответственно, щас сделал весь этот список статическим и норм... остается вопрос с выделением и пожалуй надо сделать какие то стандартные фигуры (прямоугольник, треугольник, эллипс...) тоже чет пока никак не соображу
     
Загрузка...

Поделиться этой страницей