I
ilya00
продолжаю мучить 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;
}
}
}
з.ы. в редакторе кодов есть все языки кроме шарпа -_- странно)))