0
پیاده سازی undo & redo در برنامه paint با سی شارپ
درووود به همه دوستان و اساتید عزیز .
یه برنامه paint به وسیله سی شارپ ساختم که میخام امکان undo & redo هم داشته باشه . واسه این کار از پشته استفاده کردم ولی خب متاسفانه جواب نمیده و نمیدونمم که مشکل از کجاست . اگه کسی در این رابطه اطلاعاتی داره لطفا راهنمایی کنه . خیلی ضروریه . ضمنا کد های برناممو این پایین گذاشتم که میتونید ببینید . با سپاس فراوان
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;
using System.Drawing.Imaging;
using System.Drawing.Drawing2D;
namespace Saman_drawing_board
{
public partial class Form1 : Form
{
public void undo()
{
lock (_undoRrdolocker)
{
if (_undostack.Count > 0)
{
_redostack.Push(_undostack.Pop());
pictureBox1.Image = _redostack.Peek();
pictureBox1.Refresh();
}
}
}
public void redo()
{
lock (_undoRrdolocker)
{
if (_redostack.Count > 0)
{
_undostack.Push(_redostack.Pop());
pictureBox1.Image = _undostack.Peek();
pictureBox1.Refresh();
}
}
}
public Form1()
{
InitializeComponent();
}
Bitmap bmp;
int x, y;
Color currentcolor = Color .Black;
string act = "";
int drawingsize = 2;
int x1, y1;
int x2, y2;
Rectangle rect = new Rectangle(0, 0, 0, 0);
private Stack<Image> _undostack = new Stack<Image>();
private Stack<Image> _redostack = new Stack<Image>();
private readonly object _undoRrdolocker = new object();
private void groupBox1_Enter(object sender, EventArgs e)
{
}
private void pictureBox1_Click(object sender, EventArgs e)
{
}
private void Form1_Load(object sender, EventArgs e)
{
bmp = new Bitmap(pictureBox1.Width, pictureBox1.Height);
}
private void settool(PictureBox pic)
{
pictureBox2.BorderStyle = pictureBox3.BorderStyle = pictureBox5.BorderStyle = BorderStyle.None;
pic.BorderStyle = BorderStyle.FixedSingle;
}
private void setcolor(PictureBox pic)
{
currentcolor = pic.BackColor;
pictureBox13.BackColor = currentcolor;
}
private void pictureBox2_Click(object sender, EventArgs e)
{
label1.Visible = false;
settool(pictureBox2);
act = "pen";
pictureBox1.Cursor = Cursors.Cross;
pictureBox14.Visible = false;
pictureBox16.Visible = false;
pictureBox18.Visible = false;
pictureBox19.Visible = false;
pictureBox20.Visible = false;
}
private void pictureBox3_Click(object sender, EventArgs e)
{
label1.Visible = false;
settool(pictureBox3);
pictureBox1.Cursor = Cursors.Cross;
act = "eraser";
pictureBox14.Visible = false;
pictureBox16.Visible = false;
pictureBox18.Visible = false;
pictureBox19.Visible = false;
pictureBox20.Visible = false;
}
private void pictureBox5_Click(object sender, EventArgs e)
{
label1.Visible = false;
settool(pictureBox5);
pictureBox14.Visible = true;
pictureBox16.Visible = true;
pictureBox18.Visible = true;
pictureBox19.Visible = true;
pictureBox20.Visible = true;
act = "shape";
}
private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
{
Graphics g = Graphics.FromImage(bmp);
Pen p = new Pen(currentcolor, drawingsize);
SolidBrush brush = new SolidBrush(Color.White);
if (act == "pen")
{
if (e.Button == MouseButtons.Left)
{
g.DrawLine(p, x, y, e.X, e.Y);
x = e.X;
y = e.Y;
}
x = e.X;
y = e.Y;
pictureBox1.Image = bmp;
_undostack.Push(pictureBox1.Image);
}
else if (act == "eraser")
{
if (e.Button == MouseButtons.Left)
{
g.FillEllipse(brush, new Rectangle(e.X - drawingsize, e.Y - drawingsize, drawingsize * 5, drawingsize * 5));
pictureBox1.Image = bmp;
_undostack.Push(pictureBox1.Image);
}
}
else if (act == "shape-line")
{
if (e.Button == MouseButtons.Left)
{
pictureBox1.Image = bmp;
Bitmap temp = new Bitmap(bmp);
Graphics g1 = Graphics.FromImage(temp);
g1.DrawLine(p, x1, y1, e.X, e.Y);
pictureBox1.Image = temp;
_undostack.Push(pictureBox1.Image);
}
}
else if (act == "shape-rect")
{
if (e.Button == MouseButtons.Left)
{
pictureBox1.Image = bmp;
Bitmap temp = new Bitmap(bmp);
Graphics g1 = Graphics.FromImage(temp);
if (e.X - x1 > 0 && e.Y - y1 > 0)
{
rect = new Rectangle(x1, y1, e.X - x1, e.Y - y1);
}
if (e.X - x1 < 0 && e.Y - y1 > 0)
{
rect = new Rectangle(e.X, y1, x1 - e.X, e.Y - y1);
}
if (e.X - x1 > 0 && e.Y - y1 < 0)
{
rect = new Rectangle(x1, e.Y, e.X - x1, y1 - e.Y);
}
if (e.X - x1 < 0 && e.Y - y1 < 0)
{
rect = new Rectangle(e.X, e.Y, x1 - e.X, y1 - e.Y);
}
g1.DrawRectangle(p, rect);
pictureBox1.Image = temp;
_undostack.Push(pictureBox1.Image);
}
}
else if (act == "shape-circle")
{
if (e.Button == MouseButtons.Left)
{
pictureBox1.Image = bmp;
Bitmap temp = new Bitmap(bmp);
Graphics g1 = Graphics.FromImage(temp);
if (e.X - x1 > 0 && e.Y - y1 > 0)
{
rect = new Rectangle(x1, y1, e.X - x1, e.Y - y1);
}
if (e.X - x1 < 0 && e.Y - y1 > 0)
{
rect = new Rectangle(e.X, y1, x1 - e.X, e.Y - y1);
}
if (e.X - x1 > 0 && e.Y - y1 < 0)
{
rect = new Rectangle(x1, e.Y, e.X - x1, y1 - e.Y);
}
if (e.X - x1 < 0 && e.Y - y1 < 0)
{
rect = new Rectangle(e.X, e.Y, x1 - e.X, y1 - e.Y);
}
g1.DrawEllipse(p, rect);
pictureBox1.Image = temp;
_undostack.Push(pictureBox1.Image);
}
}
else if (act == "shape-mosalas")
{
if (e.Button == MouseButtons.Left)
{
pictureBox1.Image = bmp;
Bitmap temp = new Bitmap(bmp);
Graphics g1 = Graphics.FromImage(temp);
Point[] points = { new Point(x1, y1), new Point(e.X - x1, e.Y - y1), new Point((x1 + (e.X - x1)) / 2, e.Y) };
g1.DrawPolygon(p, points);
pictureBox1.Image = temp;
_undostack.Push(pictureBox1.Image);
}
}
}
private void pictureBox4_Click(object sender, EventArgs e)
{
setcolor(pictureBox4);
}
private void pictureBox6_Click(object sender, EventArgs e)
{
setcolor(pictureBox6);
}
private void pictureBox8_Click(object sender, EventArgs e)
{
setcolor(pictureBox8);
}
private void pictureBox7_Click(object sender, EventArgs e)
{
setcolor(pictureBox7);
}
private void pictureBox12_Click(object sender, EventArgs e)
{
setcolor(pictureBox12);
}
private void pictureBox11_Click(object sender, EventArgs e)
{
setcolor(pictureBox11);
}
private void pictureBox10_Click(object sender, EventArgs e)
{
setcolor(pictureBox10);
}
private void pictureBox9_Click(object sender, EventArgs e)
{
setcolor(pictureBox9);
}
private void radioButton1_CheckedChanged(object sender, EventArgs e)
{
if (radioButton1.Checked) {
drawingsize = 2;
}
}
private void radioButton2_CheckedChanged(object sender, EventArgs e)
{
if (radioButton2.Checked)
{
drawingsize = 3;
}
}
private void radioButton3_CheckedChanged(object sender, EventArgs e)
{
if (radioButton3.Checked)
{
drawingsize = 4;
}
}
private void radioButton4_CheckedChanged(object sender, EventArgs e)
{
if (radioButton4.Checked)
{
drawingsize = 5;
}
}
private void openToolStripMenuItem_Click(object sender, EventArgs e)
{
try
{
OpenFileDialog op = new OpenFileDialog();
if (op.ShowDialog() == DialogResult.OK) {
pictureBox1.Image = Image.FromFile(op.FileName);
bmp = (Bitmap)pictureBox1.Image;
}
}
catch (Exception ex) {
MessageBox.Show(ex.Message);
}
}
private void saveToolStripMenuItem_Click(object sender, EventArgs e)
{
SaveFileDialog save = new SaveFileDialog();
save.Filter = " image files |*.jpg|*.gif|*.bmp|";
save.ShowDialog();
pictureBox1.Image.Save(save.FileName);
}
private void exitToolStripMenuItem_Click(object sender, EventArgs e)
{
Application.Exit();
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
if (MessageBox.Show("آیا برای خروج مطمئن هستید؟", "exit", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question) == DialogResult.Yes)
{
Application.Exit();
}
else
e.Cancel = true;
}
private void pictureBox14_Click(object sender, EventArgs e)
{
act = "shape-line";
label1.Visible = false;
}
private void pictureBox15_Click(object sender, EventArgs e)
{
act = "shape-sequar";
label1.Visible = false;
}
private void pictureBox16_Click(object sender, EventArgs e)
{
act = "shape-rect";
label1.Visible = false;
}
private void pictureBox18_Click(object sender, EventArgs e)
{
act = "shape-circle";
label1.Visible = false;
}
private void pictureBox17_Click(object sender, EventArgs e)
{
act = "shape-bey";
label1.Visible = false;
}
private void pictureBox20_Click(object sender, EventArgs e)
{
act = "shape-mosalas";
label1.Visible = false;
}
private void pictureBox19_Click(object sender, EventArgs e)
{
act = "shape-poly";
label1.Visible = true;
}
private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
{
x1 = e.X;
y1 = e.Y;
undoToolStripMenuItem.Enabled = true;
}
private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
{
Graphics g = Graphics.FromImage(bmp);
Pen p = new Pen(currentcolor, drawingsize);
if (act == "shape-line")
{
if (e.Button == MouseButtons.Left)
{
g.DrawLine(p, x1, y1, e.X, e.Y);
pictureBox1.Image = bmp;
_undostack.Push(pictureBox1.Image);
}
}
else if (act == "shape-rect")
{
if (e.Button == MouseButtons.Left)
{
g.DrawRectangle(p, rect);
pictureBox1.Image = bmp;
_undostack.Push(pictureBox1.Image);
}
}
else if (act == "shape-circle")
{
if (e.Button == MouseButtons.Left)
{
g.DrawEllipse(p, rect);
pictureBox1.Image = bmp;
_undostack.Push(pictureBox1.Image);
}
}
else if (act == "shape-poly")
{
if (e.Button == MouseButtons.Left)
{
g.DrawLine(p, x2, y2, e.X, e.Y);
x2 = e.X;
y2 = e.Y;
}
if (e.Button == MouseButtons.Right)
{
x2 = e.X;
y2 = e.Y;
}
pictureBox1.Image = bmp;
_undostack.Push(pictureBox1.Image);
}
else if (act == "shape-mosalas")
{
if (e.Button == MouseButtons.Left)
{
Point[] points = { new Point(x1, y1), new Point(e.X - x1, e.Y - y1), new Point((x1 + (e.X - x1)) / 2, e.Y) };
g.DrawPolygon(p, points);
pictureBox1.Image = bmp;
_undostack.Push(pictureBox1.Image);
}
}
}
private void undoToolStripMenuItem_Click(object sender, EventArgs e)
{
undo();
redoToolStripMenuItem.Enabled = true;
undoToolStripMenuItem.Enabled = false;
}
private void redoToolStripMenuItem_Click(object sender, EventArgs e)
{
redo();
redoToolStripMenuItem.Enabled = false;
undoToolStripMenuItem.Enabled = true;
}
}
}
2 پاسخ
0
سلام
ببخشید من اون قسمت undoRrdolocker رو قبلا از برنامم حذف کردم اینجا یادم رفته ویرایشش کنم . با این undoRrdolocker کاری نداریم . الان من باید چیکار کنم که این undo redo کار کنه .
اینم اون قسمته که حذفش کردم
private void UpdateImageData(Action updateImage)
{
lock (_undoRedoLocker)
{
_undoStack.Push(pictureBox1.Image);//image);
try
{
//manipulate the image here.
updateImage();
}
catch
{
_undoStack.Pop();//because of exception remove the last added frame from stack
throw;
}
}
}
0
متغیر فقط خواندنی undoRrdolocker کارش چیه؟
چرا تابع های undo و redo که از متغیر undoRrdolocker استفاده می کنن قبل از تعریف متغیر undoRrdolocker نعریف کردی؟