图形处理问题

whutcl8110 2009-11-07 12:50:38
在画图过程中

比如说要删除一条直线
一般采用反色来处理,即SetROP2
但是,如果直线下面还有其它图形,就会把直线与其它图形相交的部分也擦拭掉了。
大家有什么好的处理方法,谢谢!
...全文
120 16 打赏 收藏 转发到动态 举报
写回复
用AI写文章
16 条回复
切换为时间正序
请发表友善的回复…
发表回复
whutcl8110 2009-11-10
  • 打赏
  • 举报
回复
感谢各位,问题解决了!
whutcl8110 2009-11-10
  • 打赏
  • 举报
回复
呵呵,我的想法和你相似
你给的这个链接是一本书图像处理的书,谢谢!我正想找这么一本书。
lambochan 2009-11-09
  • 打赏
  • 举报
回复
额..怎么说呢?..你应该把那幅内存BMP置为类内变量(或者干脆连memdc都内置)..
当画一个图形例如点时,那么就画在这个BMP上..
当画了一百个图形时,根本就不需要重绘那已经画了的100个图形,因为已经都画在了那幅BMP上了,只需刷新帖图,那么实际上OnDraw()就只需要一句:
void CMyView::OnDraw( CDC *pDC )
{
if( m_pMemDC != NULL ){
pDC->BitBlt(xxxxxxxxx, m_pMemDC,XXXXXX);
}
}
ok,然后回到上面的画直线..由于直接画在客户区,根本不接触到BMP上,所以不会对已画的有任何影响,当结束时,才直接画在内存BMP上..然后Invalidate()..

或许偶的表达能力有限,这里有个连接:http://d.download.csdn.net/down/181825/zhaobei1986
里面有周长发的ImageBoard的代码,绝对可以满足你的要求了..
whutcl8110 2009-11-09
  • 打赏
  • 举报
回复
void CMyView::OnMouseMove(UINT nFlags, CPoint point)
{
if( bStartDraw ){ // 如果开始了
// 直接画在客户区
CClientDC dc(this);
int nROP = dc.SetROP2(R2_NOTXORPEN);
dc.MoveTo( ptStart );
dc.LineTo( ptCur ); // 画旧的,等于刷除上一条//这里就会把底层的图形破坏了
ptCur = point; // remark
dc.MoveTo( ptStart );
dc.LineTo( ptCur ); // 画新的。
dc.SetROP2( nROP );
}
CScrollView::OnMouseMove(nFlags, point);
}
void CMyView::OnLButtonDown(UINT nFlags, CPoint point)
{
if( bStartDraw ){
CClientDC dc( this );
int nROP = dc.SetROP2(R2_NOTXORPEN);
dc.MoveTo( ptStart );
dc.LineTo( ptCur ); // 画旧的,等于刷除上一条
dc.SetROP2(nROP);

bStartDraw = FALSE; // 画完
::ReleaseCapture(); // 释放鼠标
ptEnd = point;

// 现在,你已经得到两个点了:起始点和最终点来画一条直线了。
// 可以调用你那堆东西:

Draw(); //其实在这里又重新把以前有的图形重新画了

}
CScrollView::OnLButtonUp(nFlags, point);
}
CScrollView::Draw()
{
CDC* pDC=GetDC();
CRect rect;
GetClientRect(&rect);
CDC memDC;
memDC.CreateCompatibleDC(pDC);
CBitmap memBmp;
memBmp.CreateCompatibleBitmap(pDC,rect.Width(),rect.Height());
memDC.SelectObject(&memBmp);
memDC.FillSolidRect(0,0,rect.Width(),rect.Height(),RGB(255,255,255));

memDC.Rectangle(CRect(50,50,200,200));//矩形

memDC.MoveTo(ptStart);
memDC.LineTo(ptEnd); //直线


pDC->BitBlt(50,50,rect.Width(),rect.Height(),&memDC,0,0,SRCCOPY);//拷贝到客户区
}
我对您思路的理解是:
在动态画出跟随鼠标移动的直线后,重新刷新了底层图形,不然按照以上的代码应该实现不了我要的功能
橡皮筋应该可以画出来,我的苦恼是,在画出橡皮筋的同时,由于使用了SetROP2(R2_NOTXORPEN),使得直线移动过的区域有些点被擦拭掉了。

呵呵!谢谢您的耐心指教!
lambochan 2009-11-09
  • 打赏
  • 举报
回复
其实画橡皮筋很容易的,以直线来举例吧:
首先要有变量记录开始点(CPoint ptStart),然后还有个变量记录当前点(CPoint ptCur),最终点就是鼠标抬起时的那点了(CPoint ptEnd),当然还需要有个变量来控制开始画橡皮筋(BOOL bStartDraw)...最后,要有个BOOL变量来控制画还是不画(DrawXiangPi)。
整个过程就是要得到开始和最终点来画一条直线。

那么当鼠标按下时:

void CMyView::OnLButtonDown(UINT nFlags, CPoint point)
{
if( DrawXiangPi ){ // 如果要画橡皮就开始,否则啥都不做(这个BOOL变量当然是菜单或者命令更改)
ptStart = ptCur = point; // 记录开始点
bStartDraw = TRUE;// 开始画
SetCapture(); // 捕捉鼠标
}
CScrollView::OnLButtonDown(nFlags, point);
}

当鼠标按下移动时就画橡皮:

void CMyView::OnMouseMove(UINT nFlags, CPoint point)
{
if( bStartDraw ){ // 如果开始了
// 直接画在客户区
CClientDC dc(this);
int nROP = dc.SetROP2(R2_NOTXORPEN);
dc.MoveTo( ptStart );
dc.LineTo( ptCur ); // 画旧的,等于刷除上一条
ptCur = point; // remark
dc.MoveTo( ptStart );
dc.LineTo( ptCur ); // 画新的。
dc.SetROP2( nROP );
}
CScrollView::OnMouseMove(nFlags, point);
}

最后,当鼠标抬起时,就得到连个点,可以画在底图上了:

void CMyView::OnLButtonDown(UINT nFlags, CPoint point)
{
if( bStartDraw ){
CClientDC dc( this );
int nROP = dc.SetROP2(R2_NOTXORPEN);
dc.MoveTo( ptStart );
dc.LineTo( ptCur ); // 画旧的,等于刷除上一条
dc.SetROP2(nROP);

bStartDraw = FALSE; // 画完
::ReleaseCapture(); // 释放鼠标
ptEnd = point;

// 现在,你已经得到两个点了:起始点和最终点来画一条直线了。
// 可以调用你那堆东西:memdc.MoveTo(ptStart);memdc.LineTo(ptEnd);
dosomethink(here); // 可以把你上面那堆搞成个函数: dosomethink( CPoint ptStart, CPoint ptEnd );

// Invalidate(); // 刷新or not..看你的代码而定了.
}
CScrollView::OnLButtonUp(nFlags, point);
}



以上大概就是画橡皮筋直线的办法.画矩形也是差不多的.
当然,那不是摘录下来的代码,是偶随手写的,有错不出奇..hoho.
gl.
whutcl8110 2009-11-09
  • 打赏
  • 举报
回复
在内存画布上画完图形后,最终还需要拷贝到客户区
如果要动态移动这条直线,我就不知道怎么处理,我知道橡它类似橡皮筋的原理,可是不知道怎么处理。


CRect rect;
GetClientRect(&rect);
CDC memDC;
memDC.CreateCompatibleDC(pDC);
CBitmap memBmp;
memBmp.CreateCompatibleBitmap(pDC,rect.Width(),rect.Height());
memDC.SelectObject(&memBmp);
memDC.FillSolidRect(0,0,rect.Width(),rect.Height(),RGB(255,255,255));

memDC.Rectangle(CRect(50,50,200,200));//矩形

memDC.MoveTo(70,40);
memDC.LineTo(70,250); //直线


pDC->BitBlt(50,50,rect.Width(),rect.Height(),&memDC,0,0,SRCCOPY);//拷贝到客户区
lambochan 2009-11-09
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 whutcl8110 的回复:]
lambochan,你好,你所说的底图和客户区有什么区别?

CClientDC dc( this ); 客户区

底图也是在CDC上画的呀,


CClientDC dc( this );
dc.setrop2(notxorpen);
//刷除上次
dc.moveto..
dc.lineto..

这也会影响到底图的

可能我没有明白你的意思,能不能再给些提示,谢谢!
[/Quote]

汗,我知道了,你并没有画在一幅内存BMP上,而是直接在客户区作图.
那么,当你重绘时,你就需要重绘所有画过的DD,因此非常耗时,而且有可能在刷除时受影响。。。。

那么为何不画在BMP上呢?画在bmp上就没那么多烦恼了。
whutcl8110 2009-11-09
  • 打赏
  • 举报
回复
lambochan,你好,你所说的底图和客户区有什么区别?

CClientDC dc( this ); 客户区

底图也是在CDC上画的呀,


CClientDC dc( this );
dc.setrop2(notxorpen);
//刷除上次
dc.moveto..
dc.lineto..

这也会影响到底图的

可能我没有明白你的意思,能不能再给些提示,谢谢!
whutcl8110 2009-11-08
  • 打赏
  • 举报
回复
自己顶上!
lambochan 2009-11-08
  • 打赏
  • 举报
回复
画在客户区上而不是画在底图上,当结束当前画图指令时,才彻底画在底图上并刷新.
例如画橡皮筋直线,根据onmousemove直接:
CClientDC dc( this );
dc.setrop2(notxorpen);
//刷除上次
dc.moveto..
dc.lineto..
//重绘新线
dc.moveto..
dc.lineto..
dc.setrop2(oldrop).
当结束绘图时(onlbuttonup)才直接绘到底图上刷新.
zoulie 2009-11-07
  • 打赏
  • 举报
回复
将画直线的背景色把原来的直线在画一次
whutcl8110 2009-11-07
  • 打赏
  • 举报
回复
自己顶上!
whutcl8110 2009-11-07
  • 打赏
  • 举报
回复
如果是动态拖动这条直线的话,随着鼠标的移动,就需要删除上一个位置的直线,同时刷新下面的图形,有没有更好一点的解决办法?
lghndyz 2009-11-07
  • 打赏
  • 举报
回复
在内存里面画,画好在显示,很快的了!!
whutcl8110 2009-11-07
  • 打赏
  • 举报
回复
刷新是不是把直线下面的图形重新画一下,
如果这样的话,图像比较复杂的话,刷新太慢!
有没有更好的方法
askhe 2009-11-07
  • 打赏
  • 举报
回复
原来直线的位置,重新刷新。

15,978

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 界面
社区管理员
  • 界面
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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