采用的是双缓冲绘图,想实现在黑色背景下,屏幕上画扇形坐标轴(更新时坐标轴不变),同时可以显示动态的彩色圆。我试了些方法,无论用什么画刷,画出来的都是白色,而且是闪烁的。学得不通,代码贴上来了,请大侠们帮帮忙。在有背景的情况下画图,是不是只能改背景位图的RGB值,才能显示想要的图?有没有办法可以将要显示的图直接覆盖背景,无显示部分就还是保留背景色。
下面是我的代码:
void CPlotDlg::Draw()//绘图
{
pDC=m_edit.GetDC();
m_edit.GetClientRect(&rect); CBitmap memBitmap;
CBitmap* pOldBmp = NULL;
memDC.CreateCompatibleDC(pDC); memBitmap.CreateCompatibleBitmap(pDC,rect.right,rect.bottom);
pOldBmp = memDC.SelectObject(&memBitmap); memDC.BitBlt(rect.left,rect.top,rect.right,rect.bottom,pDC,0,0,SRCCOPY);
reDraw(&memDC);
// reDraw 函数包括的语句
// mDC->SetPixelV(rect.left+nCoordinate,rect.bottom-i*2,plot[i]); 改变屏幕像素
// mDC->SetPixelV(rect.left+nCoordinate,rect.bottom-i*2-1,plot[i]); pDC->BitBlt(rect.left,rect.top,rect.right,rect.bottom,&memDC,0,0,SRCCOPY);
memDC.SelectObject(pOldBmp);
memDC.DeleteDC();
memBitmap.DeleteObject();
ReleaseDC(pDC);
ReleaseDC(&memDC);
}OnPaint()函数里面有创建背景位图
下面是我的代码:
void CPlotDlg::Draw()//绘图
{
pDC=m_edit.GetDC();
m_edit.GetClientRect(&rect); CBitmap memBitmap;
CBitmap* pOldBmp = NULL;
memDC.CreateCompatibleDC(pDC); memBitmap.CreateCompatibleBitmap(pDC,rect.right,rect.bottom);
pOldBmp = memDC.SelectObject(&memBitmap); memDC.BitBlt(rect.left,rect.top,rect.right,rect.bottom,pDC,0,0,SRCCOPY);
reDraw(&memDC);
// reDraw 函数包括的语句
// mDC->SetPixelV(rect.left+nCoordinate,rect.bottom-i*2,plot[i]); 改变屏幕像素
// mDC->SetPixelV(rect.left+nCoordinate,rect.bottom-i*2-1,plot[i]); pDC->BitBlt(rect.left,rect.top,rect.right,rect.bottom,&memDC,0,0,SRCCOPY);
memDC.SelectObject(pOldBmp);
memDC.DeleteDC();
memBitmap.DeleteObject();
ReleaseDC(pDC);
ReleaseDC(&memDC);
}OnPaint()函数里面有创建背景位图
memDC.BitBlt(rect.left,rect.top,rect.right,rect.bottom,pDC,0,0,SRCCOPY);
这里的pDC改成你的背景位图DC。
就是再创建一个内存DC,专门存放背景。
这里的pDC改成你的背景位图DC。
就是再创建一个内存DC,专门存放背景。不好意思哦,看了一些双缓冲的资料,还是不是很懂。你能说得再详细点吗?有背景色的情况下,跟无背景下绘图有什么不一样啊?
HDC hdcMem = CreateCompatibleDC(hdc);
//创建一个bmp内存空间
HBITMAP hBmp = CreateCompatibleBitmap(hdc,SCREEN_WIDTH,SCREEN_HEIGHT);
//将bmp内存空间分配给内存DC
HGDIOBJ hOldSel = SelectObject(hdcMem,hBmp);
//这是使用者需要绘制的画面,全部往内存DC绘制
// 绘制代码....................... 如:
Rectangle(hdcMem,0,0,SCREEN_WIDTH,SCREEN_HEIGHT);
//将内存DC的内容复制到屏幕显示DC中,完成显示
BitBlt(hdc,0,0,SCREEN_WIDTH,SCREEN_HEIGHT,hdcMem,0,0,SRCCOPY);
//清除资源
SelectObject(hdcMem,hOldSel);
DeleteDC(hdcMem);
另外,重载OnEraseBkgnd(CDC* pDC),在该函数中不要绘制背景,中直接返回TRUE。
另一类DC是内存DC,它没有跟任何设备向关联,仅仅是为了画图方便,而用它来在内存里模拟真实的设备。由于它没有对应任何真实的设备,因此它没有什么固定的属性。为了保证能模拟某个特定设备,内存DC在生成的时候必须指定它模拟哪个设备,因此它必须用CreateCompatibleDC来生成,其参数就是待模拟的设备DC。由于内存DC没有任何固定属性,因此将一个内存DC作为参数送入CreateCompatibleDC来生成另一个内存DC是不行的。
生成了内存DC之后,我们实际上仅仅拥有了一个黑板框。与设备DC不同,作为真实设备的“黑板”总是存在的,但内存DC的黑板则不然,它必须靠我们专门地在内存里制作一个出来才行。能够作为内存DC的黑板的东西就是Bitmap(你所谓的CBitmap仅仅是MFC对HBITMAP的封装,因此下面只谈HBITMAP)。由于没有了设备的物理限制,这个黑板你愿意做多大都行。为了能够更好地模拟真实的设备,这块黑板的生成,最好使用CreateCompatibleBitmap,并将需要模拟的设备DC传入其中。同样,不应该把一个内存DC作为参数送入CreateCompatibleBitmap,否则你会得到某些意料之外的结果。
生成了黑板之后,还需要把黑板“安装”进黑板框,才能进行画图。“安装”的方法就是使用SelectObject,把你生成的黑板放进你的内存DC。SelectObject返回的结果是从这个DC里被换下来的黑板。第一次安装黑板的时候,被换下来的是一块“NULL 黑板”。之后,你可以按照你的意愿随时给黑板框更换黑板。顺便说一句,由于设备DC所关联的是真实的设备黑板,因此对一个设备DC进行安装黑板(把一个Bitmap送入SelectObject)的操作是无效的。
装好黑板之后,就可以在黑板上画图了。如果装进黑板框的是“NULL 黑板”,那么你的一切绘图操作也都会成功,但没有任何效果(想象一下拿着粉笔在空气里画图)。当你画了一些图形之后,你可以把另一块黑板换上去,再去画另一些图形。当然,黑板被换下来之后,其内容不会发生任何变化。如果你愿意的话,你可以生成N块黑板,不断地换进同一个黑板框,画上各种不同的图形,然后再换下来。
最后,如果你已经画完了,你可以通过DeleteDC销毁那个内存DC(黑板框)。尽管销毁黑板框的操作并不会损坏当前安装在其中的黑板,但仍然建议在销毁DC之前,用最初换下来的那块“NULL 黑板”把你自己的黑板换下来。至于你自己的黑板,你可以在你不需要它的时候,用DeleteObject来销毁。不过要注意,不要试图在这块黑板还装在某个黑板框里的时候去销毁它。剩下的问题就很简单了。什么叫双缓冲呢?
1、做个内存里的黑板框。
2、做个黑板装进去。
3、在黑板上面画图。
4、把画好的图贴到真实的设备黑板上。
5、把新做的黑板换下来销毁。
6、把黑板框销毁。这个流程可以很容易地改成:
1、预先画好固定的图形:
1.1、做个内存里的黑板框。
1.2、做个黑板装进去。
1.3、在黑板上面画图。
1.4、把新做的黑板换下来,但不要销毁(如果你自己做的黑板你都没有弄个变量存起来,那我就无话可说了)。
1.5、把黑板框销毁。
2、当需要往屏幕上画的时候(例如响应WM_PAINT消息):
2.1、做个内存里的黑板框。
2.2、把你上次存起来的黑板装进去。
2.3、把黑板上的内存贴到真实的设备黑板上。
2.4、把黑板换下来。
2.5、把黑板框销毁。
3、作为一个良好习惯,当你的程序退出时,记得把你存起来的黑板销毁。如果你愿意的话,上述流程还可以进一步变化,例如你把好几种不同固定图形预先画在几块黑板上,按需要选用,或者你同时制作两个黑板框,把一块新做的黑板装进黑板框1,然后把预先做好的黑板1至黑板N轮流装进黑板框2,并往黑板框1中的新黑板上贴,最后再把最终做好的新黑板中的内容贴到真实的设备黑板上,诸如此类。
楼主,你傻了么?这个需要双缓冲所,直接一个Pen就OK了,要想局部刷新就InvalidateRect()双缓冲用来做什么?一般都用来贴图片,靠,画的东西跟贴的不一样!
pDC->MoveTo(200,200);
pDC->AngleArc(200, 200, 10, 180,-90);
pDC->LineTo(200,200);结果画出来,LineTo画的直线出现锯齿状,怎么解决这个问题呀?
Reserved.SmoothingModeDefault
Specifies that smoothing is not applied.SmoothingModeHighSpeed
Specifies that smoothing is not applied.SmoothingModeHighQuality
Specifies that smoothing is applied using an 8 X 4 box filter.SmoothingModeNone
Specifies that smoothing is not applied.SmoothingModeAntiAlias8x4
Specifies that smoothing is applied using an 8 X 4 box filter.SmoothingModeAntiAlias
Specifies that smoothing is applied using an 8 X 4 box filter.SmoothingModeAntiAlias8x8
Specifies that smoothing is applied using an 8 X 8 box filter.
{
memDC.BitBlt(rect.left,rect.top,rect.right,rect.bottom,pDC,0,0,SRCCOPY);
}
else
{
memDC.FillSolidRect(PlotRect.left,PlotRect.top,PlotRect.right,PlotRect.bottom,RGB(0,0,0)); //刷新为黑色背景
//画扇形代码
CPoint Radus1,Radus2,Radus3;
CString str;
CPen* pPenBlue = new CPen;
// 绿色画笔
pPenBlue->CreatePen(PS_SOLID,1,RGB(0,255,0));
// 选中当前绿色画笔,并保存以前的画笔
CGdiObject* pOldPen=memDC.SelectObject(pPenBlue);
memDC.MoveTo(rect.left+360,rect.top+514);
memDC.AngleArc(rect.left+360,rect.top+514,300,45,90);
Radus1=memDC.GetCurrentPosition();
str="9.3m";
memDC.SetTextColor(RGB(255,0,0));
memDC.TextOut(Radus1.x-35,Radus1.y,str);
memDC.AngleArc(rect.left+360,rect.top+514,0,0,0);
memDC.MoveTo(rect.left+360,rect.top+514);
memDC.AngleArc(rect.left+360,rect.top+514,400,45,90);
Radus2=memDC.GetCurrentPosition();
str="12.2m";
memDC.TextOut(Radus2.x-35,Radus2.y,str);
memDC.AngleArc(rect.left+360,rect.top+514,0,0,0);
memDC.MoveTo(rect.left+360,rect.top+514);
memDC.AngleArc(rect.left+360,rect.top+514,500,45,90);
Radus3=memDC.GetCurrentPosition();
str="15.1m";
memDC.TextOut(Radus3.x-5,Radus3.y+5,str);
memDC.AngleArc(rect.left+360,rect.top+514,0,0,0);
memDC.SelectObject(pOldPen); }
这是我写的扇形代码。AngleArc画的线段不会出现锯齿现象,我就用了两次。可我运行一段时间后,就出现异常。我把画扇形的代码注释起来,else中只保留memDC.FillSolidRect这句,程序能正常运行下去。是我这段代码写错了吗?请高手指点下,谢谢拉