C#中用“橡皮条”法绘图和重绘

lengyuewuhen 2004-11-02 10:53:09
C#中用“橡皮条”法绘图和重绘

前些日子在论坛上发了个帖子,100分寻求“橡皮条”法绘图的代码。效果不是很好,于是自己参照网友给的代码重新写了一个,解决了绘图与重绘的问题。由于只写了部分,所以功能有限,同时可能算法不是很好,希望大家指点!!窗体中仅包含一个pictrueBox1,先将代码付诸于下:
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.Drawing.Drawing2D;

namespace GDI_练习
{
/// <summary>
/// Form1 的摘要说明。
/// </summary>
public class Form1 : System.Windows.Forms.Form
{
public System.Windows.Forms.PictureBox pictureBox1;
private Point p1 = Point.Empty, p2 = Point.Empty;
private bool isMouseDown = false, isMouseUp = false;

ArrayList addArray = new ArrayList();
public struct SharpType
{
public string type;
public Point p1, p2;
public Color foreColor, backColor;
public Brush brush;
public SharpType( string type, Point p1, Point p2, Color foreColor, Color backColor, Brush brush )
{
this.type = type;
this.p1 = p1;
this.p2 = p2;
this.foreColor = foreColor;
this.backColor = backColor;
this.brush = brush;
}

}

/// <summary>
/// 必需的设计器变量。
/// </summary>
private System.ComponentModel.Container components = null;

public Form1()
{
//
// Windows 窗体设计器支持所必需的
//
InitializeComponent();

//
// TODO: 在 InitializeComponent 调用后添加任何构造函数代码
//
}

/// <summary>
/// 清理所有正在使用的资源。
/// </summary>
protected override void Dispose( bool disposing )
{
if( disposing )
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}

#region Windows 窗体设计器生成的代码
/// <summary>
/// 设计器支持所需的方法 - 不要使用代码编辑器修改
/// 此方法的内容。
/// </summary>
private void InitializeComponent()
{
this.pictureBox1 = new System.Windows.Forms.PictureBox();
this.SuspendLayout();
//
// pictureBox1
//
this.pictureBox1.BackColor = System.Drawing.Color.White;
this.pictureBox1.Dock = System.Windows.Forms.DockStyle.Fill;
this.pictureBox1.Location = new System.Drawing.Point(0, 0);
this.pictureBox1.Name = "pictureBox1";
this.pictureBox1.Size = new System.Drawing.Size(432, 397);
this.pictureBox1.TabIndex = 0;
this.pictureBox1.TabStop = false;
this.pictureBox1.Paint += new System.Windows.Forms.PaintEventHandler(this.pictureBox1_Paint);
this.pictureBox1.MouseUp += new System.Windows.Forms.MouseEventHandler(this.pictureBox1_MouseUp);
this.pictureBox1.MouseMove += new System.Windows.Forms.MouseEventHandler(this.pictureBox1_MouseMove);
this.pictureBox1.MouseDown += new System.Windows.Forms.MouseEventHandler(this.pictureBox1_MouseDown);
//
// Form1
//
this.AutoScaleBaseSize = new System.Drawing.Size(6, 14);
this.ClientSize = new System.Drawing.Size(432, 397);
this.Controls.Add(this.pictureBox1);
this.Name = "Form1";
this.Text = "Form1";
this.ResumeLayout(false);

}
#endregion

/// <summary>
/// 应用程序的主入口点。
/// </summary>
[STAThread]
static void Main()
{
Application.Run(new Form1());
}

private void pictureBox1_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
{
if( ! isMouseUp )
{
this.isMouseDown = true;
this.p1 = new Point( e.X, e.Y );
}

}

private void pictureBox1_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e)
{
Graphics g = this.pictureBox1.CreateGraphics();
if( isMouseDown && p2 != Point.Empty )
g.DrawEllipse( Pens.White, p1.X, p1.Y, Math.Abs( p1.X - p2.X ), Math.Abs( p1.Y - p2.Y ) );


if( isMouseDown && ! isMouseUp )
{
p2 = new Point( e.X, e.Y );
g.DrawEllipse( Pens.Black, p1.X, p1.Y, Math.Abs( p1.X - p2.X ), Math.Abs( p1.Y - p2.Y ) );

}
foreach( SharpType type in addArray )
{
g.DrawEllipse( Pens.Black, type.p1.X, type.p1.Y, Math.Abs( type.p1.X - type.p2.X ), Math.Abs( type.p1.Y - type.p2.Y ) );

}
g.Dispose();
}

private void pictureBox1_MouseUp(object sender, System.Windows.Forms.MouseEventArgs e)
{
this.isMouseDown = false;
p2 = new Point( e.X, e.Y );
Graphics g = this.pictureBox1.CreateGraphics();
g.DrawEllipse( Pens.Black, p1.X, p1.Y, Math.Abs( p1.X - p2.X ), Math.Abs( p1.Y - p2.Y ) );
addArray.Add( new SharpType( "a", p1, p2, Color.Black, Color.Empty, Brushes.Black ) );
p1 = Point.Empty;
p2 = Point.Empty;
g.Dispose();

}

private void pictureBox1_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
{
foreach( SharpType type in addArray )
{
e.Graphics.DrawEllipse( Pens.Black, type.p1.X, type.p1.Y, Math.Abs( type.p1.X - type.p2.X ), Math.Abs( type.p1.Y - type.p2.Y ) );

}
}



}
}

...全文
267 19 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
19 条回复
切换为时间正序
请发表友善的回复…
发表回复
soilwork 2004-11-17
  • 打赏
  • 举报
回复
呵呵
看看这个吧
lengyuewuhen 2004-11-11
  • 打赏
  • 举报
回复
找着了
先试一试
谢谢 iYoung()
iYoung 2004-11-11
  • 打赏
  • 举报
回复
没关系,不懂就从新学。
不想研究 GDI 的话,就 google 一下吧
http://www.google.com/search?hl=zh-CN&newwindow=1&q=GDI+SetROP2&lr=
第一个链接就是讲这个的。
lengyuewuhen 2004-11-11
  • 打赏
  • 举报
回复
你是说,也可以用SetROP2吗?
我不懂GDI啊
iYoung 2004-11-10
  • 打赏
  • 举报
回复
用 P/Invoke,跟传统 GDI 方法差不多,无非就是

GetDC
SetROP2
SelectObject
DeleteObject
ReleaseDC

等。可以用 Reflector 察看 .net framework 的源码。

GDI+ 用来实现 半透明、反锯齿、颜色渐变 等效果很方便,但似乎没有实现 SetROP2 的替代方法。
小蕊_claudia 2004-11-10
  • 打赏
  • 举报
回复
学习~~~
lengyuewuhen 2004-11-10
  • 打赏
  • 举报
回复
iYoung()
回答一下多好啊
soilwork 2004-11-09
  • 打赏
  • 举报
回复
iYoung() 举个例子吧
米有用过GDI不太熟
lengyuewuhen 2004-11-09
  • 打赏
  • 举报
回复
顶一下
Firestone2003 2004-11-08
  • 打赏
  • 举报
回复
dc.SetOP2( R2_NOT )可以使用P/Invoke 调用
lengyuewuhen 2004-11-08
  • 打赏
  • 举报
回复
可不可以举个如何调用的例子
lengyuewuhen 2004-11-07
  • 打赏
  • 举报
回复

C#z中有没有像C++中的dc.SetOP2( R2_NOT )的呀?
烤火的鱼 2004-11-06
  • 打赏
  • 举报
回复
我已经搞定了:
private bool isdown=false;
private Point p1 = Point.Empty;
private Point p2 = Point.Empty;

private void pic_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
{
isdown=true;
pic.Capture = true;
p1 = pic.PointToScreen(new Point(e.X, e.Y));
}

private void pic_MouseUp(object sender, System.Windows.Forms.MouseEventArgs e)
{
isdown=false;
pic.Capture = false;
p2 = Point.Empty;
}

private void pic_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e)
{
if(isdown)
{
Point p = pic.PointToScreen(new Point(e.X, e.Y));
if(p2 != Point.Empty)
{
ControlPaint.DrawReversibleLine(p1, p2, Color.Black);
}
p2 = p;
ControlPaint.DrawReversibleLine(p1, p2, Color.Black);
}
}

烤火的鱼 2004-11-06
  • 打赏
  • 举报
回复
我的e-Mail:gatmail@163.net qq:52664073,如果需要什么资料,可以到我的ftp://202.107.251.26下载,如果要上传,帐号密码都是: wangyou
烤火的鱼 2004-11-06
  • 打赏
  • 举报
回复
你的程序有问题,当鼠标移动时,你采用的方法是用背景色覆盖原来的图形,然后在新的位置画图形,为防止已经画的图形和刚刚画的擦去的图形相交而留下背景色的痕迹,你将原来的图形重新画了一遍,这对单一背景色是看不出来的,如果设置一下该picturebox的image属性为一个照片,该方法的问题就出来了(鼠标移动时会留下白色椭圆),最好的办法是采用异或作图,但我目前也没有找到如何设置xor作图,希望共同研究.
iYoung 2004-11-06
  • 打赏
  • 举报
回复
橡皮筋还是直接用 GDI 画较方便,最终效果用 GDI+ 重画一遍。
ControlPaint 的 DrawReversible... 也是用 P/Invoke 调用传统 GDI 函数绘制的。
lengyuewuhen 2004-11-06
  • 打赏
  • 举报
回复
“会绘制直线了,其他应该迎刃而解了吧,虽然我没有继续研究。”

不是的,你用的ControlPaint,我以前也试过,是一个网友给的
所以我才重写了
烤火的鱼 2004-11-06
  • 打赏
  • 举报
回复
会绘制直线了,其他应该迎刃而解了吧,虽然我没有继续研究。
soilwork 2004-11-06
  • 打赏
  • 举报
回复
用ControlPaint只能绘制矩形或直线啊
如果是其他图形怎么办
比如椭圆?

111,098

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • AIGC Browser
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧