这个VC绘图函数错在哪?

烤火的鱼 2000-02-23 07:26:00
我编写了一个小程序,其中有一段代码是模拟按钮,经简化后如下:

//模拟按钮
void uButton(CDC *pDC,CRect rect)
{
CPen *pNewPen,*pOldPen;

CBrush *pNewBrush=new CBrush;
pNewBrush->CreateSolidBrush(RGB(192,192,192));
pDC->FillRect(rect,pNewBrush);
delete pNewBrush;

pNewPen=new CPen;
pNewPen->CreatePen(PS_SOLID,1,RGB(255,255,255));
pOldPen=pDC->SelectObject(pNewPen);
pDC->MoveTo(rect.left,rect.top );
pDC->LineTo(rect.right-1,rect.top);
pDC->MoveTo(rect.left,rect.top );
pDC->LineTo(rect.left,rect.bottom-1);
delete pNewPen;

//以下代码与上面相同,只是颜色和坐标变了
pNewPen=new CPen;
pNewPen->CreatePen(PS_SOLID,1,RGB(0,0,0));
pDC->SelectObject(pNewPen);
pDC->MoveTo(rect.right,rect.top);
pDC->LineTo(rect.right,rect.bottom);
pDC->MoveTo(rect.left,rect.bottom);
pDC->LineTo(rect.right,rect.bottom);
delete pNewPen;

pNewPen=new CPen;
pNewPen->CreatePen(PS_SOLID,1,RGB(128,128,128));
pDC->SelectObject(pNewPen);
pDC->MoveTo(rect.right-1,rect.top+1);
pDC->LineTo(rect.right-1,rect.bottom-1);
pDC->MoveTo(rect.left+1,rect.bottom-1);
pDC->LineTo(rect.right-1,rect.bottom-1);
delete pNewPen;
pDC->SelectObject(pOldPen);
}

为了测试,我在OnKeyDown()事件中写了如下代码:
{

CDC *pDC=GetDC();
CRect rect;

rect.left=0;
rect.right=100;
rect.top=0;
rect.bottom=70;
uButton(pDC,rect);
//ReleaseDC(pDC);
}

如果你大量调用uButton()函数,如按住回车键不动,过一会儿,图案就变了,再过一会儿就死机了,我实在不知程序错在哪儿,望各为大虾吝指教。
...全文
249 11 打赏 收藏 转发到动态 举报
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
gege 2000-02-27
  • 打赏
  • 举报
回复
何处可下载Bounds Checker?
zdg 2000-02-27
  • 打赏
  • 举报
回复
http://www.midatech.com/csdn/tools/
zdg 2000-02-24
  • 打赏
  • 举报
回复
ad的方法是对的, 操作pen尤其要注意释放...
我建议安装Bounds Checker, 这种Error很容易查出...
kxy 2000-02-24
  • 打赏
  • 举报
回复
我前面的帖子错了,sorry
ad 2000-02-24
  • 打赏
  • 举报
回复
netware做得很对, LJN在瞎说。
不过,netware的代码还可作如下优化:

void uButton(CDC *pDC,CRect rect)
{
CPen *pNewPen[3],*pOldPen;

CBrush *pNewBrush=new CBrush;
pNewBrush->CreateSolidBrush(RGB(192,192,192));
pDC->FillRect(rect,pNewBrush);
delete pNewBrush;

pNewPen[0]=new CPen;
pNewPen[0]->CreatePen(PS_SOLID,1,RGB(255,255,255));
pOldPen=pDC->SelectObject(pNewPen[0]);
pDC->MoveTo(rect.left,rect.top );
pDC->LineTo(rect.right-1,rect.top);
pDC->MoveTo(rect.left,rect.top );
pDC->LineTo(rect.left,rect.bottom-1);

//以下代码与上面相同,只是颜色和坐标变了
pNewPen[1]=new CPen;
pNewPen[1]->CreatePen(PS_SOLID,1,RGB(0,0,0));
pDC->SelectObject(pNewPen[1]);
pDC->MoveTo(rect.right,rect.top);
pDC->LineTo(rect.right,rect.bottom);
pDC->MoveTo(rect.left,rect.bottom);
pDC->LineTo(rect.right,rect.bottom);

pNewPen[2]=new CPen;
pNewPen[2]->CreatePen(PS_SOLID,1,RGB(128,128,128));
pDC->SelectObject(pNewPen[2]);
pDC->MoveTo(rect.right-1,rect.top+1);
pDC->LineTo(rect.right-1,rect.bottom-1);
pDC->MoveTo(rect.left+1,rect.bottom-1);
pDC->LineTo(rect.right-1,rect.bottom-1);

pDC->SelectObject(pOldPen);
for(int i=0;i<3;i++) delete pNewPen[i];
}

还可以进一步优化,既然几段代码都差不多,可以集中到一个循环里做,使源码大大减少(执行效率未必提高)。
xingxian 2000-02-24
  • 打赏
  • 举报
回复
kxy is a new comer,but pretend to be a expert.haha!
LJN 2000-02-24
  • 打赏
  • 举报
回复
看看以下两行有什么不同,就能解决了。

pOldPen=pDC->SelectObject(pNewPen);
pOldPen=pDC->SelectObject(&pNewPen);
geofee 2000-02-24
  • 打赏
  • 举报
回复
用pointer多见外!
CPen pen(...);
// use pen code
CPen *o = SelectObject(&pen)
// Draw code
SelectObject(o) // Important!!!

pen.DeleteObject(); // for use again!
pen.CreatePen(...)
// use pen code
o = SelectObject(&pen)
// Draw code
SelectObject(o) // Important!!!

// again and again!!


bclzi 2000-02-24
  • 打赏
  • 举报
回复
first a pointer
then new an object space
last creat the object
netmare 2000-02-23
  • 打赏
  • 举报
回复
An application should not delete a pen when the pen is selected in a device context,and u should release dc every time,so fix the program like this:

void uButton(CDC *pDC,CRect rect)
{
CPen *pNewPen,*pOldPen;

CBrush *pNewBrush=new CBrush;
pNewBrush->CreateSolidBrush(RGB(192,192,192));
pDC->FillRect(rect,pNewBrush);
delete pNewBrush;

pNewPen=new CPen;
pNewPen->CreatePen(PS_SOLID,1,RGB(255,255,255));
pOldPen=pDC->SelectObject(pNewPen);
pDC->MoveTo(rect.left,rect.top );
pDC->LineTo(rect.right-1,rect.top);
pDC->MoveTo(rect.left,rect.top );
pDC->LineTo(rect.left,rect.bottom-1);
pDC->SelectObject(pOldPen);
delete pNewPen;

//以下代码与上面相同,只是颜色和坐标变了
pNewPen=new CPen;
pNewPen->CreatePen(PS_SOLID,1,RGB(0,0,0));
pDC->SelectObject(pNewPen);
pDC->MoveTo(rect.right,rect.top);
pDC->LineTo(rect.right,rect.bottom);
pDC->MoveTo(rect.left,rect.bottom);
pDC->LineTo(rect.right,rect.bottom);
pDC->SelectObject(pOldPen);
delete pNewPen;

pNewPen=new CPen;
pNewPen->CreatePen(PS_SOLID,1,RGB(128,128,128));
pDC->SelectObject(pNewPen);
pDC->MoveTo(rect.right-1,rect.top+1);
pDC->LineTo(rect.right-1,rect.bottom-1);
pDC->MoveTo(rect.left+1,rect.bottom-1);
pDC->LineTo(rect.right-1,rect.bottom-1);
pDC->SelectObject(pOldPen);
delete pNewPen;
//pDC->SelectObject(pOldPen);
}

为了测试,我在OnKeyDown()事件中写了如下代码:
{

CDC *pDC=GetDC();
CRect rect;

rect.left=0;
rect.right=100;
rect.top=0;
rect.bottom=70;
uButton(pDC,rect);
ReleaseDC(pDC);
}

kxy 2000-02-23
  • 打赏
  • 举报
回复
When you no longer need the pen, call the DeleteObject function to delete it.
CreatePen本身创建了一个对象实例,new也创建了
你只释放了一个:)
欢迎去www.midatech.com/kxy下载ChatFtp我一般都在使用这个聊天.

16,470

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Web++
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

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