 悬赏园豆:50
                [已解决问题] 
            
                    解决于 2016-04-16 13:53
                悬赏园豆:50
                [已解决问题] 
            
                    解决于 2016-04-16 13:53 
                 
        要实现的效果:鼠标点击winform上任意两点构成直线,点击第一个按钮,出现一个圆沿直线做往返运动,点击第二个按钮,同时出现三条直线,每条直线上有三个圆沿直线做往返运动。这个效果已实现,三个圆之间无闪屏
问题:解决三个圆之间的闪屏
界面:两个button,三个timer
代码:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing.Drawing2D;
namespace PictureSport
{
 public partial class Test_DongYuan : Form
 {
 public Test_DongYuan()
 {
 //this.DoubleBuffered = true;
InitializeComponent();
 }
public Graphics g;//封装一个gdi+绘图图面
 private Bitmap bmp;
 
 public Point p1;//默认第一条线点的起始坐标
 public Point p2;//默认第一条线点的结束坐标
public Point p3;
 public Point p4;
 public Point p5;
 public Point p6;
private int n = 0; //运动点离起点的距离
 private bool bDirect = true;//true为从起点向终点运行,false从终点向起点运行
 Point pt = new Point(0, 0); //当前点
public int i = 1;//记录循环次数
public int m;//总距离
private void Test_DongYuan_Load(object sender, EventArgs e)
 {
 //1、在内存中建立一块“虚拟画布”
 
 bmp = new Bitmap(this.Width, this.Height);//创建和窗体大小的画布
 //2、获取这块内存画布的Graphics引用 
 
 g = Graphics.FromImage(bmp); ;//获取画布
 timer1.Enabled = false;//一开始不画圆
 timer2.Enabled = false;
 timer3.Enabled = false;
 }
private void Test_DongYuan_MouseClick(object sender, MouseEventArgs e)
 {
 if (i == 1)
 {
 p1 = new Point();
 p1.X = e.Location.X;
 p1.Y = e.Location.Y;
 i++;
}
 else
 {
if (i == 2)
 {
 p2 = new Point();
 p2.X = e.Location.X;
 p2.Y = e.Location.Y;
g.DrawLine(Pens.Black, p1, p2);
 g.DrawImage(bmp, new Point(0, 0));
 this.BackgroundImage = bmp;//位图是虚拟的,所以直线只存在在位图上,只在位图上显示,要想真实显示出来就得以位图填充背景
 g.Dispose();
}
}
}
 private void timer1_Tick(object sender, EventArgs e)
 {
button1_Click(sender, e);
}
 private void timer2_Tick(object sender, EventArgs e)
 {
 //第一条直线上的直线
p3.X = p1.X;
 p3.Y = p1.Y - 50;
 p4.X = p2.X;
 p4.Y = p2.Y - 50;
//第一条直线下的直线
 p5.X = p1.X;
 p5.Y = p1.Y + 50;
 p6.X = p2.X;
 p6.Y = p2.Y + 50;
 bmp = new Bitmap(this.Width, this.Height);//创建和窗体大小的画布
 g = Graphics.FromImage(bmp); ;//获取画布
 g.DrawLine(Pens.Black, p1, p2);
 g.DrawLine(Pens.Black, p3, p4);
 g.DrawLine(Pens.Black, p5, p6);
 DongYuan(p3, p4);
 g.DrawImage(bmp, new Point(0, 0));
this.BackgroundImage = bmp;//位图是虚拟的,所以直线只存在在位图上,只在位图上显示,要想真实显示出来就得以位图填充背景
 g.Dispose();
}
private void timer3_Tick(object sender, EventArgs e)
 {
//第一条直线上的直线
p3.X = p1.X;
 p3.Y = p1.Y - 50;
 p4.X = p2.X;
 p4.Y = p2.Y - 50;
//第一条直线下的直线
 p5.X = p1.X;
 p5.Y = p1.Y + 50;
 p6.X = p2.X;
 p6.Y = p2.Y + 50;
bmp = new Bitmap(this.Width, this.Height);//创建和窗体大小的画布
 g = Graphics.FromImage(bmp); ;//获取画布
 g.DrawLine(Pens.Black, p1, p2);
 g.DrawLine(Pens.Black, p3, p4);
 g.DrawLine(Pens.Black, p5, p6);
 DongYuan(p5, p6);
 g.DrawImage(bmp, new Point(0, 0));
 this.BackgroundImage = bmp;//位图是虚拟的,所以直线只存在在位图上,只在位图上显示,要想真实显示出来就得以位图填充背景
 g.Dispose();
}
/// <summary>
 /// 动圆
 /// </summary>
 /// <param name="sender"></param>
 /// <param name="e"></param>
 private void button1_Click(object sender, EventArgs e)
 {
 
 
 DongYuan(p1,p2);
 timer1.Enabled = true;
}
 /// <summary>
 /// 动圆方法
 /// </summary>
 /// <param name="sender"></param>
 /// <param name="e"></param>
 public void DongYuan(Point p_first,Point p_last)
 {
 //Math.Pow() Pow返回指定数字的指定次幂 pow(X,y)就是计算X的Y次方
 m = (int)Math.Pow(Math.Pow((p_last.X - p_first.X), 2) + Math.Pow((p_last.Y - p_first.Y), 2), 0.5);//总距离
 if (n == m)//运动点离起点的距离=总距离
 bDirect = false;//false从终点向起点运行
 if (n == 0)//运动点离起点的距离=0
 bDirect = true;//true为从起点向终点运行
 if (bDirect)//从起点向终点运行
 n++;//运动点离起点的距离不断自加
 else
 n--;//运动点离起点的距离不断自-
//Pen p11 = new Pen(Color.Black);
 Pen p_double = new Pen(Color.Red);
 Graphics g = this.CreateGraphics();
if (pt.X != 0 && pt.Y != 0) //清除上次的运动点
 {
 //减去圆半径
 g.DrawEllipse(new Pen(this.BackColor), pt.X - 15, pt.Y - 15, 30, 30); //清除上次的运动点
 }
g.DrawLine(Pens.Black,p_first, p_last);//画起点到终点的线
 g.DrawImage(bmp, new Point(0, 0));
 this.BackgroundImage = bmp;//位图是虚拟的,所以直线只存在在位图上,只在位图上显示,要想真实显示出来就得以位图填充背景
 
 //总距离不为0
 if (m != 0)
 {
 pt.X = ((p_last.X - p_first.X) * n) / m + p_first.X;
 pt.Y = ((p_last.Y - p_first.Y)) * n / m + p_first.Y;
 g.DrawEllipse(p_double, pt.X - 15, pt.Y - 15, 30, 30); //画运动的点
 g.Dispose();//释放资源
}
 
 }
 /// <summary>
 /// 分批
 /// </summary>
 /// <param name="sender"></param>
 /// <param name="e"></param>
 private void button2_Click(object sender, EventArgs e)
 {
 timer2.Enabled = true;
 timer3.Enabled = true;
 //第一条直线上的直线
 
 p3.X = p1.X;
 p3.Y = p1.Y - 50;
 p4.X = p2.X;
 p4.Y = p2.Y - 50;
//第一条直线下的直线
 p5.X = p1.X;
 p5.Y = p1.Y + 50;
 p6.X = p2.X;
 p6.Y = p2.Y + 50;
bmp = new Bitmap(this.Width, this.Height);//创建和窗体大小的画布
 g = Graphics.FromImage(bmp); ;//获取画布
 g.DrawLine(Pens.Black,p1,p2);
 g.DrawLine(Pens.Black, p3, p4);
 g.DrawLine(Pens.Black, p5, p6);
 g.DrawImage(bmp, new Point(0, 0));
 this.BackgroundImage = bmp;//位图是虚拟的,所以直线只存在在位图上,只在位图上显示,要想真实显示出来就得以位图填充背景
 button1_Click(sender, e);
 }
 }
}
留个邮箱或QQ,我把代码发你?
邮箱:2220552727@qq.com
@随风起舞: 发你邮件了,没做往返功能,只是为了演示不闪烁。
@Firen: 已经收到了案例,完美解决问题了。
我现在有点怕用gdi+做动画了,你还是用wpf做吧,保证不闪
不会用wpf
@随风起舞: 事实上,用gdi+画这个根本没压力,是你方法没用对
@上帝之城: 如果你会的话,求教
@随风起舞: 用gdi+,就要学习局部绘图技术,你每次都完整的绘制了一帧,不卡才怪。
@上帝之城: 那应该怎么修改代码?
你需要使用双缓冲,才能解决闪屏问题
双缓冲用过了好几种,都没有效果
@随风起舞: 你的代码里确实用到了双缓冲,要不你把整个项目发给我,有空我帮你调调?
@刘宏玺: 好的
@刘宏玺: 我发份压缩包到你的邮箱吧,有空麻烦帮我看一下