MFC中ONPAINT、ONDRAW、ONERASEBKGND等绘图函数的使用场合和作用、区别是啥啊?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MFC中ONPAINT、ONDRAW、ONERASEBKGND等绘图函数的使用场合和作用、区别是啥啊?相关的知识,希望对你有一定的参考价值。

看不太明白啊,哪位可以解释清楚一点啊

OnPaint是WM_PAINT消息的消息处理函数,在OnPaint中调用OnDraw,一般来说,用户自己的绘图代码应放在OnDraw中。OnPaint()是CWnd的类成员,负责响应WM_PAINT消息。OnDraw()是CVIEW的成员函数,没有响应消息的功能.当视图变得无效时(包括大小的改变,移动,被遮盖等等),Windows发送WM_PAINT消息。该视图的OnPaint 处理函数通过创建CPaintDC类的DC对象来响应该消息并调用视图的OnDraw成员函数.OnPaint最后也要调用OnDraw,因此一般在OnDraw函数中进行绘制。
ONERASEBKGND实现双缓冲绘图,擦除背景的。追问

谢谢大大,屏幕闪烁的话是因为没用ONERASEBKGND吧?双缓冲技术不太明白啊。。

追答

ONERASEBKGND避免闪烁的。首先当然是去掉MFC
提供的背景绘制过程了。实现的方法很多,
* 可以在窗口形成时给窗口的注册类的背景刷付NULL
* 也可以在形成以后修改背景
static CBrush brush(RGB(255,0,0));
SetClassLong(this->m_hWnd,GCL_HBRBACKGROUND,(LONG)(HBRUSH)brush);
* 要简单也可以重载OnEraseBkgnd(CDC* pDC)直接返回TRUE
这样背景没有了,结果图形显示的确不闪了,但是变得一团乱。怎么办?这就要用到双缓存的方法了。双缓冲就是除了在屏幕上有
图形进行显示以外,在内存中也有图形在绘制。我们可以把要显示的图形先在内存中绘制好,然后再一次性的将内存中的图形按照一个点一个点地覆盖到屏幕上去(这个过程非常快,因为是非常规整的内存拷贝)。这样在内存中绘图时,随便用什么反差大的背景色进行清除都不会闪,因为看不见。当贴到屏幕上时,因为内存中最终的图形与屏幕显示图形差别很小(如果没有运动,当然就没有差别),这样看起来就不会闪。

参考技术A 我是在OnEraseBkgnd中做的,下边有段代码,不知道对你能不能有帮助。
BOOL CDeskShortDlg::OnEraseBkgnd(CDC* pDC)

// TODO: Add your message handler code here and/or call default
BITMAP BmpInfo;
CBitmap mpBitmap;
mpBitmap.LoadBitmap(IDB_KEHUDI);
mpBitmap.GetBitmap(&BmpInfo);
CBitmap* pOldBitmap;
CDC pDisplayMemDC;
pDisplayMemDC.CreateCompatibleDC(pDC);
pOldBitmap=(CBitmap*)pDisplayMemDC.SelectObject(&mpBitmap);
CRect hhhh;
GetClientRect(&hhhh);
pDC->StretchBlt(0,0,hhhh.Width(),hhhh.Height(), &pDisplayMemDC, 0,0,BmpInfo.bmWidth, BmpInfo.bmHeight, SRCCOPY);
//pDC->BitBlt(hhhh.left,hhhh.top,BmpInfo.bmWidth, BmpInfo.bmHeight, &pDisplayMemDC,0, 0, SRCCOPY);
pDisplayMemDC.SelectObject(pOldBitmap);
return TRUE;

OnPaint MFC 上未显示矩形

【中文标题】OnPaint MFC 上未显示矩形【英文标题】:Rectangle not showing on OnPaint MFC 【发布时间】:2018-07-30 14:57:02 【问题描述】:

我有一个用 c++ 和 MFC 编写的基于对话框的应用程序。该对话框有一个 CStatic 图片控件。我正在 PictureCtrl 的 OnPaint() 函数中绘制 BITMAP。相关代码如下:

void PictureCtrl::OnPaint()

    CDC* pDC = this->GetDC();
    pDC->SelectStockObject(PS_SOLID);
    pDC->Rectangle(CRect(0, 0, 400, 400));
    ReleaseDC(pDC);

    CStatic::OnPaint();

当应用程序运行时,矩形被绘制在对话框的左上角,而不是图片控件。

其次,如果我最小化和最大化对话窗口,图像会显示出来,但矩形不会。

但是,如果我将鼠标悬停在 Windows 任务栏中,并且工具提示出现在对话框应用程序的图标上,则会显示矩形。

无论用户对窗口做什么(最小化、最大化、移动等),我都希望在图像上显示矩形。

【问题讨论】:

根据文档docs.microsoft.com/en-gb/cpp/mfc/reference/cdc-class#rectangle,这里传递的坐标是逻辑坐标。这里的答案限定了逻辑坐标是:***.com/questions/15862205/… 显示重现此效果所需的整个代码。显示静态控件类的所有代码,以及创建或子类化静态控件的父窗口(或父对话框)中的相关代码。你应该先打电话给CStatic::OnPaint(); 你应该真的使用CPaintDC。其中,它设置正确的剪辑区域,并验证脏区。您需要有充分的理由不使用CPaintDC。从发布的代码来看,您似乎没有这样做。 @BarmakShemirani 调用 CStatic::OnPaint() 完成了这项工作。如果您发布答案,我会接受。谢谢。 我原以为会有不同的问题,例如静态控件最初是在 x/y 坐标 0/0 处创建并在该位置绘制,然后控件移动到不同的位置。 【参考方案1】:

CStatic::OnPaint 处理 BeginPaint/EndPaint(主要 WinAPI 函数)以响应 WM_PAINT 消息。因此应该首先调用它。此外,您可以使用CClientDC 自动清理:

void PictureCtrl::OnPaint()

    CStatic::OnPaint();
    CClientDC dc(this); //<- uses GetDC
    dc.SelectStockObject(BLACK_PEN);
    dc.Rectangle(CRect(0, 0, 400, 400));
 //<- ReleaseDC is automatically called

更好的是,直接使用CPaintDC 来响应WM_PAINT 消息:

void PictureCtrl::OnPaint()

    CPaintDC dc(this); //<- calls `BeginPaint`
    dc.SelectStockObject(BLACK_PEN);
    dc.Rectangle(CRect(0, 0, 400, 400));
 //<- EndPaint is automatically called

不相关,使用BLACK_PEN 作为SelectStockObject 的参数。使用PS_SOLID 作为CPen 的参数:

CPen pen(PS_SOLID, 1, RGB(0,0,0));

【讨论】:

以上是关于MFC中ONPAINT、ONDRAW、ONERASEBKGND等绘图函数的使用场合和作用、区别是啥啊?的主要内容,如果未能解决你的问题,请参考以下文章

关于MFC中的OnPaint和OnDraw

MFC中的Invalidate、OnDraw、OnPaint函数的作用、区别和联系?

MFC中的一般经验之谈----OnInitialUpdate

MFC 中 OnPaint() 函数的使用

MFC中啥时候调用OnDraw()函数?

activex 如何调用OnDraw函数