定时器控制画线的问题!(附代码)

时间:2021-08-30 02:10:08
本程序是用定时器控制的画线问题,点击按钮后就会画线,可是当有别的窗口掩盖第一条线后,下面的线就消失了!
第二条线倒是没有这种情况。(后来发现可能是因为改变了点pt1,pt2或x1,y1,x2,y2,dx,dy的原因吧,因为当去掉
pt1=CPoint(10,50);
pt2=CPoint(100,20);
PointInit(pt1,pt2);
SetTimer(1,10,NULL);以后第一条线也就没有问题了!)

下面是一部分源代码:
1、主文件的头文件中主要变量的声明:
CPoint pt1;//起点
CPoint pt2;//终点
    
FLOAT dx,dy;//移动点时每次的增量
FLOAT x1,y1,x2,y2;//初始化时的起点终点坐标值
FLOAT x,y;//移动点中间变量

void PointInit(CPoint pStart,CPoint pEnd);//坐标点的初始化
void Draw();//主要画线代码

2、初始化中:
pt1=CPoint(50,50);
pt2=CPoint(129,187);
PointInit(pt1,pt2);

3、OnPaint()中加入Draw():
Draw();//主要的画线程序
 if (IsIconic())
{————}
————

4、定时器主要代码:
void CLineMoveDlg::OnTimer(UINT nIDEvent) 
{
if (nIDEvent==1)
{ x+=dx;
y+=dy;

OnPaint();
}
CDialog::OnTimer(nIDEvent);
}

5、鼠标点击事件代码:(只有一句)
SetTimer(1,10,NULL);

6、坐标点的初始化:
void CLineMoveDlg::PointInit(CPoint pStart,CPoint pEnd)
{

x=x1=pStart.x;
y=y1=pStart.y;
x2=pEnd.x;
y2=pEnd.y;


dx=(x2-x1)/200;
dy=(y2-y1)/200;

}

7、主要画线代码:
void CLineMoveDlg::Draw()
{
    CDC* m_dc = GetDC();
    CPen m_pen(PS_SOLID,5,RGB(50,220,255));
    m_dc->SelectObject(&m_pen);
    m_dc->MoveTo(x1,y1);
    m_dc->LineTo(x,y);
    if (x2>=x1&&y2>=y1)
       {
if (x>=x2&&y>=y2)
    {
               KillTimer(1);
               //去掉下面四句代码后第一条线也就没问题了!
                 pt1=CPoint(10,50);
               pt2=CPoint(100,20);
               PointInit(pt1,pt2);
               SetTimer(1,10,NULL);
    }

}
else if (x2>=x1&&y2<=y1)
{
if (x>=x2&&y<=y2)
{
KillTimer(1);
}

}
else if (x2<=x1&&y2>=y1)
{
if (x<=x2&&y>=y2)
{
KillTimer(1);

}

}
else if (x2<=x1&&y2<=y1)
{
if (x<=x2&&y<=y2)
{
KillTimer(1);
}

}
}

请各位帮忙看看,谢谢!!!

7 个解决方案

#1


void CLineMoveDlg::OnTimer(UINT nIDEvent)  

if (nIDEvent==1) 
{ x+=dx; 
y+=dy; 

OnPaint(); 

CDialog::OnTimer(nIDEvent); 

==================
OnPaint不是由你调用的,它是由系统当出现WM_PAINT消息时自己调用的.你在定时器中应该用UpdateWindow来触发消息.

#2


同意楼上老兄 

#3


首先对第一楼的说法进行纠正,WM_PAINT并不是由UpdateWindow来触发的,而是对窗口设置了无效区域后,由Windows在适当的时机来触发WM_PAINT,那么UpdateWindow的作用是什么呢?它的作用是不必等Windows在适当的时机,而告诉Windows立即执行无效区域的绘制。所以如果我们要立即更新绘制,应该先InvalidateRect(m_hWnd,rcInvalidate,FALSE);然后UpdateWindow(m_hWnd);

对于搂主的写法似乎有点欠妥,在OnPaint应该是绘制全部,而不是部分,所以在OnPaint中不要使用GetDC这样的写法,
而是用CPaintDC,对于需要实时更新的部分,例如要在OnTimer中进行立即更新部分图像,应该使用GetDC来进行局部绘制,同时不要触发WM_PAINT来绘制。因为如果你每次都通过触发WM_PAINT来绘制,那么你的效率将是特别低下的。
当窗口被其他窗口覆盖等情况下,Windows会自动触发OnPaint来绘制全部,所以将绘制全部的代码放在OnPaint中是必须的。


===============================================================================
阙海忠 (CTO Skin++ 开发成员  http://www.uipower.com 上海勇进软件有限公司)

#4


楼上的三位兄台,谢谢你们的回答,可是本人刚学VC不久,很多东西还不明白,

各位能说具体一些吗?

TO:wltg2001
再就是已经把OnTimer()中的事件改为了UpdateWindow();连线都画不出来了

TO:fafa_cai
您说的方法怎么用呢?
InvalidateRect(m_hWnd,rcInvalidate,FALSE);中rcInvalidate是怎么来的呢?
谢谢!

#5


上面的说法是对的,一般确实是用InvalidateRect来使客户无效,我上面的回贴是随手写的,InvalidateRect中的rcInvalidate一般可以设为NULL,表示整个客户区都无效.

#6


不明LZ在说什么

#7


呵,各位,终于弄明白了,原来在画完之后还要保存起点和终点,然后在OnPaint()中重绘

谢谢各位了!

#1


void CLineMoveDlg::OnTimer(UINT nIDEvent)  

if (nIDEvent==1) 
{ x+=dx; 
y+=dy; 

OnPaint(); 

CDialog::OnTimer(nIDEvent); 

==================
OnPaint不是由你调用的,它是由系统当出现WM_PAINT消息时自己调用的.你在定时器中应该用UpdateWindow来触发消息.

#2


同意楼上老兄 

#3


首先对第一楼的说法进行纠正,WM_PAINT并不是由UpdateWindow来触发的,而是对窗口设置了无效区域后,由Windows在适当的时机来触发WM_PAINT,那么UpdateWindow的作用是什么呢?它的作用是不必等Windows在适当的时机,而告诉Windows立即执行无效区域的绘制。所以如果我们要立即更新绘制,应该先InvalidateRect(m_hWnd,rcInvalidate,FALSE);然后UpdateWindow(m_hWnd);

对于搂主的写法似乎有点欠妥,在OnPaint应该是绘制全部,而不是部分,所以在OnPaint中不要使用GetDC这样的写法,
而是用CPaintDC,对于需要实时更新的部分,例如要在OnTimer中进行立即更新部分图像,应该使用GetDC来进行局部绘制,同时不要触发WM_PAINT来绘制。因为如果你每次都通过触发WM_PAINT来绘制,那么你的效率将是特别低下的。
当窗口被其他窗口覆盖等情况下,Windows会自动触发OnPaint来绘制全部,所以将绘制全部的代码放在OnPaint中是必须的。


===============================================================================
阙海忠 (CTO Skin++ 开发成员  http://www.uipower.com 上海勇进软件有限公司)

#4


楼上的三位兄台,谢谢你们的回答,可是本人刚学VC不久,很多东西还不明白,

各位能说具体一些吗?

TO:wltg2001
再就是已经把OnTimer()中的事件改为了UpdateWindow();连线都画不出来了

TO:fafa_cai
您说的方法怎么用呢?
InvalidateRect(m_hWnd,rcInvalidate,FALSE);中rcInvalidate是怎么来的呢?
谢谢!

#5


上面的说法是对的,一般确实是用InvalidateRect来使客户无效,我上面的回贴是随手写的,InvalidateRect中的rcInvalidate一般可以设为NULL,表示整个客户区都无效.

#6


不明LZ在说什么

#7


呵,各位,终于弄明白了,原来在画完之后还要保存起点和终点,然后在OnPaint()中重绘

谢谢各位了!