MFC中的窗体绘制事件函数:OnCtlColor、OnPaint、OnNcPaint、OnDrawItem、OnEraseBkgnd、OnDraw

文章目录

参考:https://learn.microsoft.com/

CWnd::OnCtlColor

即将绘制子控件时,框架会调用此成员函数。

c 复制代码
afx_msg HBRUSH OnCtlColor(
    CDC* pDC,
    CWnd* pWnd,
    UINT nCtlColor);

参数
pDC

包含指向子窗口的显示上下文的指针。 可能是暂时性指针。

pWnd

包含指向请求颜色的控件的指针。 可能是暂时性指针。

nCtlColor

包含以下用于指定控件类型的值之一:

CTLCOLOR_BTN 按钮控件

CTLCOLOR_DLG 对话框

CTLCOLOR_EDIT 编辑控件

CTLCOLOR_LISTBOX 列表框控件

CTLCOLOR_MSGBOX 消息框

CTLCOLOR_SCROLLBAR 滚动条控件

CTLCOLOR_STATIC 静态控件

返回值

OnCtlColor 必须返回用于绘制控件背景的画笔的句柄。

注解

大多数控件将此消息发送到其父级(通常是一个对话框),以准备 pDC 来使用正确的颜色绘制控件。

若要更改文本颜色,请使用所需的红绿蓝 (RGB) 值调用 SetTextColor 成员函数。

若要更改单行编辑控件的背景色,请在 CTLCOLOR_EDIT 和 CTLCOLOR_MSGBOX 消息代码中设置画笔句柄,并调用 CDC::SetBkColor 函数来响应 CTLCOLOR_EDIT 代码。

不会对下拉组合框的列表框调用 OnCtlColor,因为下拉列表框实际上是组合框的子级,而不是窗口的子级。 若要更改下拉列表框的颜色,请在 nCtlColor 参数中创建一个 CComboBox,并在其中包含一个用于检查 CTLCOLOR_LISTBOX 的 OnCtlColor 重写。 在此处理程序中,必须使用 SetBkColor 成员函数来设置文本的背景色。

备注

框架调用此成员函数来支持你的应用程序处理 Windows 消息。 传递到函数的参数反映了收到消息时框架所接收的参数。 如果调用此函数的基类实现,该实现将使用最初随消息传递的参数,而不是你提供给该函数的参数。 若要将以下方法添加到对话框类,请使用 Visual Studio 属性窗格添加 WM_CTLCOLOR 的消息处理程序。 或者,可以手动将 ON_WM_CTLCOLOR() 条目添加到消息映射。

示例

c 复制代码
// This OnCtlColor handler will change the color of a static control
// with the ID of IDC_MYSTATIC. The code assumes that the CPenWidthsDlg
// class has an initialized and created CBrush member named m_brush.
// The control will be painted with red text and a background
// color of m_brush.
HBRUSH CPenWidthsDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
   // Call the base class implementation first! Otherwise, it may
   // undo what we're trying to accomplish here.
   HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);

   // Are we painting the IDC_MYSTATIC control? We can use
   // CWnd::GetDlgCtrlID() to perform the most efficient test.
   if (pWnd->GetDlgCtrlID() == IDC_MYSTATIC)
   {
      // Set the text color to red
      pDC->SetTextColor(RGB(255, 0, 0));

      // Set the background mode for text to transparent 
      // so background will show thru.
      pDC->SetBkMode(TRANSPARENT);

      // Return handle to our CBrush object
      hbr = m_brush;
   }

   return hbr;
}

CWnd::OnPaint

当 Windows 或应用程序请求重绘应用程序窗口的一部分时,框架会调用此成员函数。

c 复制代码
afx_msg void OnPaint();

注解

在调用 UpdateWindow 或 RedrawWindow 成员函数时发送 WM_PAINT 消息。

由于在设置了 RDW_INTERNALPAINT 标志的情况下调用了 RedrawWindow 成员函数,窗口可能会收到内部绘制消息。 在这种情况下,窗口可能不包含更新区域。 应用程序应调用 GetUpdateRect 成员函数来确定窗口是否包含更新区域。 如果 GetUpdateRect 返回 0,则应用程序不应调用 BeginPaint 和 EndPaint 成员函数。

应用程序需负责通过在其内部数据结构中查找每个 WM_PAINT 消息来检查任何必要的内部重绘或更新,因为 WM_PAINT 消息可能是由无效区域以及在设置了 RDW_INTERNALPAINT 标志的情况下调用 RedrawWindow 成员函数而导致的。

Windows 仅发送内部 WM_PAINT 消息一次。 在 UpdateWindow 成员函数将内部 WM_PAINT 消息发送到某个窗口后,在该窗口失效或者在设置了 RDW_INTERNALPAINT 标志的情况下再次调用 RedrawWindow 成员函数之前,不会发送或发布更多的 WM_PAINT 消息。

CWnd::OnNcPaint

需要绘制非工作区时,框架会调用此成员函数。

c 复制代码
afx_msg void OnNcPaint();

注解

默认实现绘制窗口框架。

应用程序可以重写此调用并绘制其自身的自定义窗口框架。 剪切区域始终是矩形,即使框架的形状已更改。

CWnd::OnDrawItem

当控件或菜单的视觉方面发生更改时,框架将对所有者绘制按钮控件、组合框控件、列表框控件或菜单的所有者调用此成员函数。

c 复制代码
afx_msg void OnDrawItem(
    int nIDCtl,
    LPDRAWITEMSTRUCT lpDrawItemStruct);

参数
nIDCtl

包含发送了 WM_DRAWITEM 消息的控件的标识符。 如果菜单发送了消息,则 nIDCtl 包含 0。

lpDrawItemStruct

指定指向 DRAWITEMSTRUCT 数据结构的长指针,该结构包含有关要绘制的项和所需绘制类型的信息。
注解

DRAWITEMSTRUCT 结构的 itemAction 成员定义要执行的绘制操作。 此成员中的数据允许控件所有者确定所需的绘制操作。

在处理此消息后返回之前,应用程序应确保 DRAWITEMSTRUCT 结构的 hDC 成员所标识的设备上下文已还原到默认状态。

如果 hwndItem 成员属于 CButton、CMenu、CListBox 或 CComboBox 对象,则调用相应类的 DrawItem 虚拟函数。 重写相应控件类的 DrawItem 成员函数可绘制项。

备注

框架调用此成员函数来支持你的应用程序处理 Windows 消息。 传递到函数的参数反映了收到消息时框架所接收的参数。 如果调用此函数的基类实现,该实现将使用最初随消息传递的参数,而不是你提供给该函数的参数。

CWnd::OnEraseBkgnd

当 CWnd 对象背景需要擦除时(例如,调整大小时),框架会调用此成员函数。

c 复制代码
afx_msg BOOL OnEraseBkgnd(CDC* pDC);

参数
pDC

指定设备上下文对象。

返回值

如果擦除背景,则返回非零值;否则返回 0。

注解

调用它来准备一个用于绘制的失效区域。

默认实现使用窗口类结构的 hbrBackground 成员指定的窗口类背景画笔来擦除背景。

如果 hbrBackground 成员为 NULL,则 OnEraseBkgnd 的重写版本应擦除背景色。 该版本还应通过首先对画笔调用 UnrealizeObject,然后选择画笔,将所需画笔的原点与 CWnd 坐标对齐。

如果重写的 OnEraseBkgnd 处理消息并擦除背景,则它应返回非零值以响应 WM_ERASEBKGND;这表示不需要进一步擦除。 如果它返回 0,则窗口将仍旧标记为需要擦除。 (通常,这意味着 PAINTSTRUCT 结构的 fErase 成员将是 TRUE。)

Windows 假设使用 MM_TEXT 映射模式来计算背景。 如果设备上下文使用任何其他映射模式,则擦除的区域可能不在工作区的可见部分内。

备注

框架调用此成员函数来支持你的应用程序处理 Windows 消息。 传递到函数的参数反映了收到消息时框架所接收的参数。 如果调用此函数的基类实现,该实现将使用最初随消息传递的参数,而不是你提供给该函数的参数。

CWnd::InvalidateRect

通过将给定矩形添加到 CWnd 更新区域,使给定矩形中的工作区失效。

c 复制代码
void InvalidateRect(
    LPCRECT lpRect,
    BOOL bErase = TRUE);

参数
lpRect

指向包含要添加到更新区域的矩形(以客户端坐标表示)的 CRect 对象或 RECT 结构。 如果 lpRect 为 NULL,则将整个工作区添加到该区域。

bErase

指定是否要擦除更新区域中的背景。

注解

在发送下一条 WM_PAINT 消息时,会将失效矩形连同更新区域中的所有其他区域一起标记为可绘制。 失效区域在更新区域中累积到在下一次发生 WM_PAINT 调用时处理该区域,或者该区域被 ValidateRect 或 ValidateRgn 成员函数验证为止。

bErase 参数指定在处理更新区域时是否要擦除更新区域中的背景。 如果 bErase 为 TRUE,则在调用 BeginPaint 成员函数时擦除背景;如果 bErase 为 FALSE,则背景将保持不变。 对于更新区域的任何部分,如果 bErase 为 TRUE,则会擦除整个区域(而不仅仅是给定部分)中的背景。

每当 CWnd 更新区域不为空并且该窗口的应用程序队列中没有其他消息时,Windows 就会发送一条 WM_PAINT 消息。

类似的函数

MFC中的CWnd::Invalidate、CWnd::InvalidateRgn

c 复制代码
void Invalidate(BOOL bErase = TRUE);
void InvalidateRect(LPCRECT lpRect, BOOL bErase = TRUE);

WIN32API中的InvalidateRect

c 复制代码
BOOL InvalidateRect(
  [in] HWND       hWnd,
  [in] const RECT *lpRect,
  [in] BOOL       bErase
);

CView::OnDraw

由框架调用以呈现文档的图像。

c 复制代码
virtual void OnDraw(CDC* pDC) = 0;

参数
pDC

指向用于呈现文档图像的设备上下文。

注解

框架调用此函数以执行屏幕显示、打印和打印预览,并在每种情况下传递不同的设备上下文。 没有默认实现。

必须重写此函数才能显示文档的视图。 可以使用 pDC 参数所指向的 CDC 对象发出图形设备接口 (GDI) 调用。 可以在绘图前在设备上下文中选择 GDI 资源(例如笔或字体),之后将取消选择它们。 通常,绘图代码可以与设备无关;也就是说,不需要有关哪种类型的设备显示图像的信息。

若要优化绘图,请调用设备上下文的 RectVisible 成员函数,以确定是否绘制给定的矩形。 如果需要区分普通屏幕显示和打印,请调用设备上下文的 IsPrinting 成员函数。

相关推荐
奋斗的小花生3 小时前
c++ 多态性
开发语言·c++
闲晨3 小时前
C++ 继承:代码传承的魔法棒,开启奇幻编程之旅
java·c语言·开发语言·c++·经验分享
UestcXiye4 小时前
《TCP/IP网络编程》学习笔记 | Chapter 3:地址族与数据序列
c++·计算机网络·ip·tcp
霁月风5 小时前
设计模式——适配器模式
c++·适配器模式
jrrz08286 小时前
LeetCode 热题100(七)【链表】(1)
数据结构·c++·算法·leetcode·链表
咖啡里的茶i6 小时前
Vehicle友元Date多态Sedan和Truck
c++
海绵波波1076 小时前
Webserver(4.9)本地套接字的通信
c++
@小博的博客6 小时前
C++初阶学习第十弹——深入讲解vector的迭代器失效
数据结构·c++·学习
爱吃喵的鲤鱼7 小时前
linux进程的状态之环境变量
linux·运维·服务器·开发语言·c++
7年老菜鸡8 小时前
策略模式(C++)三分钟读懂
c++·qt·策略模式