C#自制窗体绘画程序0.2.1代码
仅供自用
效果展示
有一个bug待解决:切换橡皮时会自动更改画笔粗细
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.IO;
namespace DrawForms02
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
pB_penColor.BackColor = pen1.Color; //画笔颜色显示框初始化
}
private void Form1_KeyDown(object sender, KeyEventArgs e) //快捷键
{
if(e.KeyCode == Keys.C)
{
CleanPicture(bm_main, g_main, pB_main); //清理屏幕
}
if(e.KeyCode == Keys.G)
{
this.Cursor = Cursors.Cross; // 将鼠标指针设置为十字光标,表示取色状态
this.mouseState = MouseState.colorPicker; // 切换笔的状态
}
if(e.KeyCode == Keys.S)
{
DialogResult dialogResult = colorDialog1.ShowDialog();
if (dialogResult == DialogResult.OK)
{
selectColor = colorDialog1.Color;
pen1.Color = selectColor;
pB_penColor.BackColor = selectColor;
}
}
if(e.KeyCode == Keys.E) //橡皮
{
pen1.Color = Color.White;
pB_penColor.BackColor = Color.White;
pen1.Width = 20;
trackBar_penSize.Value = 20;
textBox_penSize.Text = "20";
}
}
enum MouseState //区分好是 画笔状态 还是 取色器状态
{
pen, //画笔
colorPicker //取色器
}
MouseState mouseState = MouseState.pen;
Bitmap bm_main; //画图bitmap
Graphics g_main;
Point p1, p2; //线段的两个点
Pen pen1 = new Pen(Color.Red, 1); //画笔
bool is_pen_down = false; //判断画笔是否落下
bool is_first_point = true; //记录第一个点 即落笔位置
private void pB_main_Resize(object sender, EventArgs e) //初始化事件
{
bm_main = new Bitmap(pB_main.Width, pB_main.Height);
g_main = Graphics.FromImage(bm_main);
g_main.Clear(Color.White);
}
private void pB_main_MouseDown(object sender, MouseEventArgs e)
{
is_pen_down = true;
is_first_point = true;
/*旧版v0.1取色功能
if (mouseState == MouseState.colorPicker)
{
Point p = this.PointToScreen(e.Location);
Color pickedColor = GetPixelColor(p);
pen1.Color = pickedColor; // 将颜色值用于你想要的操作,例如显示在标签上或者将其应用到其他控件上
pB_penColor.BackColor = pickedColor;
this.Cursor = Cursors.Default; // 恢复鼠标指针为默认状态
this.mouseState = MouseState.pen; //笔的状态恢复
//this.MouseDown -= Form1_MouseDown; // 移除鼠标按下事件处理程序
//this.MouseDown -= pB_main_MouseDown;
//this.MouseDown -= pB_color_MouseDown;
}
*/
if (mouseState == MouseState.colorPicker) //直接取色(原图无放缩)
{
Point p = new Point(e.X, e.Y);
Color pickedColor = this.bm_main.GetPixel(p.X, p.Y);
pen1.Color = pickedColor; // 将颜色值用于你想要的操作,例如显示在标签上或者将其应用到其他控件上
pB_penColor.BackColor = pickedColor;
this.Cursor = Cursors.Default; // 恢复鼠标指针为默认状态
this.mouseState = MouseState.pen; //笔的状态恢复
}
}
private void pB_main_MouseUp(object sender, MouseEventArgs e)
{
is_pen_down = false;
}
private void pB_main_MouseMove(object sender, MouseEventArgs e) //重点
{
if(mouseState == MouseState.pen) //画笔状态
{
if (is_first_point) //确定落笔时第一点位置
{
p1 = new Point(e.X, e.Y);
is_first_point = false;
}
if (is_pen_down)
{
p2 = new Point(e.X, e.Y);
//pen1.Color = Color.Blue;
//pen1.Width = 1;
g_main.DrawLine(pen1, p1, p2); //画线
p1 = p2;
pB_main.Image = bm_main; //在控件上显示bitmap的内容
}
}
if (mouseState == MouseState.colorPicker) //取色时,即时显示颜色
{
Point p = new Point(e.X, e.Y);
pB_penColor.BackColor = this.bm_main.GetPixel(p.X, p.Y);
}
}
private void b_clean_Click(object sender, EventArgs e) //清理屏幕按钮
{
//g_main.Clear(Color.White);
//pB_main.Image = bm_main; //在控件上显示bitmap的内容
CleanPicture(bm_main, g_main, pB_main);
}
private void CleanPicture(Bitmap b, Graphics g, PictureBox p) //清理函数
{
g.Clear(Color.White);
p.Image = b;
}
//Bitmap bm_colorWheel = new Bitmap(16, 16); //色盘bitmap
Bitmap bm_colorWheel;
Graphics g_bm_color;
//Graphics g_pB_color; 新版imageV2显示要用的变量
Bitmap bm_colorPictureBoxView; //新版imageV3显示要用的变量
Point p_pB_c; //鼠标落点
bool is_pen_down_pB_c = false; //判断画笔是否落下
bool is_colorPixel_draw = false; //判断是否已经画完一个矩形
//bool is_first_point_pB_c = true; //记录第一个点 即落笔位置
Color selectColor;
//Brush brush_colorWheel = new SolidBrush(Color.Black); //新版imageV2显示要用的变量
private void b_colorSelect_Click(object sender, EventArgs e) //选择颜色按钮
{
DialogResult dialogResult = colorDialog1.ShowDialog();
if(dialogResult == DialogResult.OK)
{
selectColor = colorDialog1.Color;
pen1.Color = selectColor;
pB_penColor.BackColor = selectColor;
}
}
private void b_colorSelect2_Click(object sender, EventArgs e) //控制台选择颜色按钮
{
DialogResult dialogResult = colorDialog1.ShowDialog();
if (dialogResult == DialogResult.OK)
{
selectColor = colorDialog1.Color;
pen1.Color = selectColor;
pB_penColor.BackColor = selectColor;
}
}
private void pB_color_Resize(object sender, EventArgs e) //初始化
{
//初始化为pictureBox大小
//bm_colorWheel = new Bitmap(pB_color.Width, pB_color.Height);
bm_colorWheel = new Bitmap(8, 8);
g_bm_color = Graphics.FromImage(bm_colorWheel); //bitmap上的画布初始化
g_bm_color.Clear(Color.White);
//新版imageV2显示要用的变量
//g_pB_color = pB_color.CreateGraphics(); //pictureBox控件上的画布初始化
//label2_debug.Text = g_pB_color.DpiX + ", " + g_pB_color.DpiY; //debug
//新版imageV3显示要用的变量
bm_colorPictureBoxView = new Bitmap(pB_color.Width, pB_color.Height);
}
private void pB_color_MouseDown(object sender, MouseEventArgs e)
{
if(mouseState == MouseState.pen)
{
is_pen_down_pB_c = true;
if (is_pen_down_pB_c == true && is_colorPixel_draw == false)
{
//矩形绘制(已弃用)
//g_color.FillRectangle
// (new SolidBrush(pen1.Color), p_pB_c.X, p_pB_c.Y, 1, 1);
//p_pB_c = new Point(e.X, e.Y);
p_pB_c = new Point(e.X * bm_colorWheel.Width / pB_color.Width, e.Y * bm_colorWheel.Height / pB_color.Height);
//图片缩放则画图方式也要缩放
//g_color.DrawRectangle
// (pen1, p_pB_c.X * (bm_colorWheel.Width / pB_color.Width),
// p_pB_c.Y * (bm_colorWheel.Height / pB_color.Height), 2, 2);
//pB_color.Image = bm_colorWheel; //新版更新imageV3
//g_bm_color.DrawRectangle(pen1, p_pB_c.X, p_pB_c.Y, 1, 1); //先在bitmap上绘制 更新imageV0
bm_colorWheel.SetPixel(p_pB_c.X, p_pB_c.Y, pen1.Color); //新版更新imageV4
//pB_color.Image = bm_colorWheel; //更新imageV0
//DrawImage(bm_colorWheel, pB_color.CreateGraphics(), pB_color); //新版更新imageV1
//DrawImageV2(bm_colorWheel, g_pB_color, pB_color, brush_colorWheel); //新版更新imageV2
DrawImageV3(bm_colorWheel, bm_colorPictureBoxView); //新版更新imageV3
pB_color.Image = bm_colorPictureBoxView; //新版更新imageV3
is_colorPixel_draw = true;
//label2_debug.Text = e.X + ", " + e.Y; //debug
}
}
/* 原取色功能v0.1废弃
if (mouseState == MouseState.colorPicker)
{
Point p = this.PointToScreen(e.Location);
Color pickedColor = GetPixelColor(p);
pen1.Color = pickedColor; // 将颜色值用于你想要的操作,例如显示在标签上或者将其应用到其他控件上
pB_penColor.BackColor = pickedColor;
this.Cursor = Cursors.Default; // 恢复鼠标指针为默认状态
this.mouseState = MouseState.pen; //笔的状态恢复
//this.MouseDown -= Form1_MouseDown; // 移除鼠标按下事件处理程序
//this.MouseDown -= pB_main_MouseDown;
//this.MouseDown -= pB_color_MouseDown;
}
*/
if (mouseState == MouseState.colorPicker)
{
Point p = new Point(e.X * bm_colorWheel.Width / pB_color.Width, e.Y * bm_colorWheel.Height / pB_color.Height);
Color pickedColor = this.bm_colorWheel.GetPixel(p.X, p.Y);
pen1.Color = pickedColor; // 将颜色值用于你想要的操作,例如显示在标签上或者将其应用到其他控件上
pB_penColor.BackColor = pickedColor;
this.Cursor = Cursors.Default; // 恢复鼠标指针为默认状态
this.mouseState = MouseState.pen; //笔的状态恢复
}
}
private void pB_color_MouseUp(object sender, MouseEventArgs e)
{
is_pen_down_pB_c = false;
is_colorPixel_draw = false;
}
private void pB_color_MouseMove(object sender, MouseEventArgs e)
{
/*
if(is_pen_down_pB_c == true && is_colorPixel_draw == false)
{
//矩形绘制(已弃用)
//g_color.FillRectangle
// (new SolidBrush(pen1.Color), p_pB_c.X, p_pB_c.Y, 1, 1);
//p_pB_c = new Point(e.X, e.Y);
p_pB_c = new Point(e.X * bm_colorWheel.Width / pB_color.Width, e.Y * bm_colorWheel.Height / pB_color.Height);
//图片缩放则画图方式也要缩放
//g_color.DrawRectangle
// (pen1, p_pB_c.X * (bm_colorWheel.Width / pB_color.Width),
// p_pB_c.Y * (bm_colorWheel.Height / pB_color.Height), 2, 2);
g_color.DrawRectangle(pen1, p_pB_c.X, p_pB_c.Y , 1, 1);
//pB_color.Image = bm_colorWheel; //更新imageV0
//DrawImage(bm_colorWheel, pB_color.CreateGraphics(), pB_color); //新版更新imageV1
DrawImageV2(bm_colorWheel, pB_color.CreateGraphics(), pB_color, brush_colorWheel); //新版更新imageV2
is_colorPixel_draw = true;
}
*/
if(mouseState == MouseState.colorPicker) //取色时,即时显示颜色
{
//Point p = this.PointToScreen(e.Location);
Point p = new Point(e.X * bm_colorWheel.Width / pB_color.Width, e.Y * bm_colorWheel.Height / pB_color.Height);
//pB_penColor.BackColor = GetPixelColor(p); //已废弃
pB_penColor.BackColor = this.bm_colorWheel.GetPixel(p.X, p.Y);
}
}
//取色功能
//事件功能的+-是怎么工作的?
private void b_colorPick_Click(object sender, EventArgs e) //取色按钮
{
this.Cursor = Cursors.Cross; // 将鼠标指针设置为十字光标,表示取色状态
this.mouseState = MouseState.colorPicker; // 切换笔的状态
//this.MouseDown += Form1_MouseDown; // 添加鼠标按下事件处理程序
//this.MouseDown += pB_main_MouseDown;
//this.MouseDown += pB_color_MouseDown;
}
//文件保存
private void save_ToolStripMenuItem_Click(object sender, EventArgs e) //点击上方菜单 文件->保存
{
//saveFileDialog1.ShowDialog(); //第一次弹出保存对话框
//saveFileDialog1.
//this.saveFileDialog1.Filter = "Jpg 图片|*.jpg|Bmp 图片|*.bmp|Gif 图片|*.gif|Png 图片|*.png|Wmf 图片|*.wmf";
//this.saveFileDialog1.FileName = "test";
//this.saveFileDialog1.AddExtension = true;
//this.saveFileDialog1.DefaultExt = "jpg"; //默认保存文件格式
if(saveFileDialog1.ShowDialog() == DialogResult.OK) //点击保存 //第二次弹出保存对话框
{
//bm_main.Save(saveFileDialog1.FileName, System.Drawing.Imaging.ImageFormat.Jpeg);
bm_main.Save(saveFileDialog1.FileName);
}
} //连续保存两次?
private void DrawImage(Bitmap bitmap, Graphics pictureBoxGraphics, PictureBox pictureBox) //绘制图像
{
pictureBoxGraphics.DrawImage(bitmap, 0, 0, pictureBox.Width, pictureBox.Height);
}
private void DrawImageV2(Bitmap bitmap, Graphics pictureBoxGraphics, PictureBox pictureBox, Brush brush)
//待改进功能:当 pictureBox.Width / bitmap.Width 不能整除时,如何处理偏移
{
Point drawingPonit = new Point();
Color drawingColor = new Color();
for(int bitmapY = 0; bitmapY < bitmap.Height; bitmapY++) {
for(int bitmapX = 0; bitmapX < bitmap.Width; bitmapX++) {
//drawingPonit.X = bitmapX * (pictureBox.Width / bitmap.Width); //确定绘画开始位置
//drawingPonit.Y = bitmapY * (pictureBox.Height / bitmap.Height);
drawingPonit.X = (int)((double)bitmapX * (double)(pictureBox.Width / bitmap.Width)); //确定绘画开始位置
drawingPonit.Y = (int)((double)bitmapY * (double)(pictureBox.Height / bitmap.Height));
drawingColor = bitmap.GetPixel(bitmapX, bitmapY); //确定绘画颜色
brush = new SolidBrush(drawingColor);
pictureBoxGraphics.FillRectangle
(
brush,
drawingPonit.X,
drawingPonit.Y,
//(int)Math.Round((double)(pictureBox.Width / bitmap.Width)),
//(int)Math.Round((double)(pictureBox.Height / bitmap.Height))
(int)((bitmapX + 1) * (double)(pictureBox.Width / bitmap.Width)) - drawingPonit.X,
(int)((bitmapY + 1) * (double)(pictureBox.Height / bitmap.Height)) - drawingPonit.Y
);
}
}
}
private void DrawImageV3(Bitmap bm_input, Bitmap bm_output)
{
Point point_input = new Point();
Color color_input;
for (int bm_output_Y = 0; bm_output_Y < bm_output.Height; bm_output_Y++)
for (int bm_output_X = 0; bm_output_X < bm_output.Width; bm_output_X++)
{
//求bm_output像素点对应的bm_input像素点 注意如何避免除法舍弃小数
point_input.X = (int)(((float)bm_output_X / bm_output.Width) * bm_input.Width);
point_input.Y = (int)(((float)bm_output_Y / bm_output.Height) * bm_input.Height);
color_input = bm_input.GetPixel(point_input.X, point_input.Y);
//绘制
bm_output.SetPixel(bm_output_X, bm_output_Y, color_input);
}
}
//画笔粗细更改功能
//拖动条更改画笔粗细
private void trackBar_penSize_ValueChanged(object sender, EventArgs e)
{
pen1.Width = trackBar_penSize.Value; //更改pen1粗细
textBox_penSize.Text = trackBar_penSize.Value.ToString(); //更改textBox显示值
}
//textBox输入功能
private void textBox_penSize_KeyPress(object sender, KeyPressEventArgs e) //按键事件
{
if (!char.IsControl(e.KeyChar) && !char.IsDigit(e.KeyChar)) // 判断按键不是控制键且不是数字
{
e.Handled = true; // 取消该按键的处理
}
}
private void textBox_penSize_KeyDown(object sender, KeyEventArgs e) //检测回车并响应更新
{
if(e.KeyCode == Keys.Enter) //Enter键按下
{
if (textBox_penSize.Text.Length > 0) //字符串有内容时
{
int penSize = int.Parse(textBox_penSize.Text); //int.Parse 函数功能:str转int
if (penSize < 1)
{
penSize = 1;
textBox_penSize.Text = "1";
}
else if (penSize > 20)
{
penSize = 20;
textBox_penSize.Text = "20";
}
pen1.Width = penSize; //设置笔
trackBar_penSize.Value = penSize; //设置滑条
//textBox_penSize.Text = ToString();
this.ActiveControl = null; //取消焦点(?)
}
}
}
//橡皮按钮
private void b_eraser_Click(object sender, EventArgs e)
{
pen1.Color = Color.White;
pB_penColor.BackColor = Color.White;
pen1.Width = 20;
trackBar_penSize.Value = 20;
textBox_penSize.Text = "20";
}
/*
private void textBox_penSize_TextChanged(object sender, EventArgs e) //文本更新事件
{
//int penSize;
//bool success = int.TryParse(textBox_penSize.Text, out penSize);
if (textBox_penSize.Text.Length > 0) //字符串有内容时
{
int penSize = int.Parse(textBox_penSize.Text); //int.Parse 函数功能:str转int
if (penSize < 1)
{
penSize = 1;
}
else if (penSize > 10)
{
penSize = 10;
}
pen1.Width = penSize;
trackBar_penSize.Value = penSize;
}
}
*/
}
}
/* 参考代码 第一版保存
private void button2_Click(object sender, EventArgs e) //保存文件按钮
{
savePath = textBox1.Text;
if (Directory.Exists(savePath))
{
bitmap.Save(savePath + "\\test.jpg");
textBox1.Text = (savePath + " 保存成功!文件名为test.jpg");
}
else
{
textBox1.Text = wrongPathMessage;
}
}
*/
/*
private void Form1_MouseDown(object sender, MouseEventArgs e) //form窗体取色
{
/*
if(mouseState == MouseState.colorPicker)
{
//Color pickedColor = GetPixelColor(e.Location); // 获取鼠标点击位置的颜色
Point p = this.PointToScreen(e.Location);
Color pickedColor = GetPixelColor(p);
pen1.Color = pickedColor; // 将颜色值用于你想要的操作,例如显示在标签上或者将其应用到其他控件上
pB_penColor.BackColor = pickedColor;
this.Cursor = Cursors.Default; // 恢复鼠标指针为默认状态
this.mouseState = MouseState.pen; //笔的状态恢复
//this.MouseDown -= Form1_MouseDown; // 移除鼠标按下事件处理程序
//this.MouseDown -= pB_main_MouseDown;
//this.MouseDown -= pB_color_MouseDown;
}
}
*/
/*
private Color GetPixelColor(Point location) //取色函数 //已弃用
{
using (Bitmap bmp = new Bitmap(1, 1))
{
using (Graphics g = Graphics.FromImage(bmp))
{
g.CopyFromScreen(location, new Point(0, 0), new Size(1, 1)); //取色不稳定
}
return bmp.GetPixel(0, 0);
}
}
*/
//取色功能
//事件功能的+-是怎么工作的?
/*
private void b_colorPick_Click(object sender, EventArgs e) //取色按钮
{
this.Cursor = Cursors.Cross; // 将鼠标指针设置为十字光标,表示取色状态
this.MouseDown += Form1_MouseDown; // 添加鼠标按下事件处理程序
}
private void Form1_MouseDown(object sender, MouseEventArgs e)
{
//Color pickedColor = GetPixelColor(e.Location); // 获取鼠标点击位置的颜色
Point p = this.PointToScreen(e.Location);
Color pickedColor = GetPixelColor(p);
pen1.Color = pickedColor; // 将颜色值用于你想要的操作,例如显示在标签上或者将其应用到其他控件上
pB_penColor.BackColor = pickedColor;
this.Cursor = Cursors.Default; // 恢复鼠标指针为默认状态
this.MouseDown -= Form1_MouseDown; // 移除鼠标按下事件处理程序
}
private Color GetPixelColor(Point location) //取色函数
{
using (Bitmap bmp = new Bitmap(1, 1))
{
using (Graphics g = Graphics.FromImage(bmp))
{
g.CopyFromScreen(location, new Point(0, 0), new Size(1, 1));
}
return bmp.GetPixel(0, 0);
}
}
*/