• 理解operator HBRUSH( ) const的实现原理


    问题引出


    在MFC中有个WM_CTLCOLOR消息,它的消息响应函数是CWnd类的OnCtlColor,其函数声明和注释如下:

    afx_msg HBRUSH OnCtlColor( CDC* pDC, CWnd* pWnd, UINT nCtlColor );
    
    返回值:OnCtlColor必须返回一个刷子句柄,该刷子将被用于画出控件的背景。
    参数:
    pDC       包含了子窗口的显示设备环境的指针。可能是临时的。  
    PWnd      包含了要求颜色的控件的指针。可能是临时的。  
    NCtlColor 包含了下列值,指定了控件的类型: 
    · CTLCOLOR_BTN        按钮控件  
    · CTLCOLOR_DLG        对话框  
    · CTLCOLOR_EDIT       编辑控件  
    · CTLCOLOR_LISTBOX    列表框控件  
    · CTLCOLOR_MSGBOX     消息框  
    · CTLCOLOR_SCROLLBAR  滚动条控件  
    · CTLCOLOR_STATIC     静态控件 

    
    

    该函数的返回值将被用来绘制控件的背景。当一个子控件将要被绘制时,它都要向的的父窗口(通常是一个对话框)发生一个WM_CTLCOLOR消息来准备一个DC,以便使用正确的颜色来绘制该控件。OnCtlColor默认的函数实现如下:

    HBRUSH CDrawMainDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
    {
        HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);
        
        //如果默认的不是所需画笔,则返回另一个画笔
        //CBrush 对象
        return m_brush;
    }
    我们注意到,OnCtlColor函数要求返回HBRUSH类型的句柄,而默认的函数返回的却是CBrush类型的画刷对象。这其中的原因就是CBrush类重载了HBRUSH操作符。HBRUSH操作符重载声明如下:

    operator HBRUSH( ) const;
    调用成功时该操作符返回一个指向Windows GDI对象的句柄,该句柄表示一个CBrush对象,否则返回NULL。

    现在的问题就是请说明如何将CBrush对象转换为一个HBRUSH句柄,在回答这个问题之前我们先了解下GDI对象,重载,强制类型转换这个三个知识点。


    补充知识


    GDI对象

           微软提供了各种Windows图形设备接口(GDI)对象,如位图(CBitmap)、区域(CRgn)、画刷(CBrush)、画笔(CPen)、调色板(CPalette)、字体(CFont)的等类型,这些类类型对象可以用于相关图形的绘制工作,它们都有相同的父类CGdiObject,m_hObject是CGdiObject的数据成员,包含附加给对象的HBITMAP,HPALETTE,HRGN,HBRUSH,HPEN或HFONT的句柄。也就是说CPen、CBrush等对象都各自包含了相对应的句柄。


    强制类型转换

         当操作数的类型不同,经常需要将操作数转化为所需要的类型,这个过程即为强制类型转换。强制类型转换具有两种形式:显式强制转换和隐式强制类型转换

    显式强制转换

          形如“TYPE b = (TYPE) a”的表达式都是显示强制类型转换,这种转换有明显的转换过程,即括号和类型组合(TYPE)。

    隐式类型转换

         这类型转换发生在赋值表达式有返回值的函数调用表达式中。在赋值表达式中,如果赋值符左右两侧的操作数类型不同,则将赋值符右边操作数强制转换为赋值符左侧的类型数值后,赋值给赋值符左侧的变量。在函数调用时,如果return后面表达式的类型与函数返回值类型不同,则在返回值时将return后面表达式的数值强制转换为函数返回值类型后,再将值返回。


    操作符重载

    操作符重载包含两个要素:operator 和被重载的字符,CBrush类被重载的字符就是"HBRUSH",当在CBrush类中,当遇到HBRUSH类型转换时,被转换的CBrush对象会调用operator HBRUSH()运算符重载函数,在其中的GDI类型中也都有相对应的运算符重载接口,它们的原理也都是一样的。


    HBRUSH运算符重载实现


    OnCtlColor函数中我们直接返回了CBrush类的对象,由于该函数要求返回的是HBRUSH句柄,两者类型不一致,发生隐式类型转换,即存在这个的过程“HBRUSH hTemp = (HBRUSH)m_brush”->m_brush.operatro HBRUSH()。m_brush对象调用了运算符重载函数,在该函数中返回了对应的句柄,函数大致实现如下:

    HBRUSH operator HBRUSH()
    {
       return this.m_hObject;//指向CBrush对象的句柄
    }

  • 相关阅读:
    告别ThinkPHP6的异常页面, 让我们来拥抱whoops吧
    ThinkPHP6 上传图片代码demo
    【ThinkPHP6:从TP3升级到放弃】1. 前言及准备工作
    PHP数字金额转换大写金额
    提高PHP开发效率, PhpStorm必装的几款插件
    5分钟弄懂Docker!
    GitHub 上排名前 100 的 IOS 开源库简介
    GitHub 上排名前 100 的 Android 开源库简介
    android线程消息传递机制——Looper,Handler,Message
    Android Activity:四种启动模式,Intent Flags和任务栈
  • 原文地址:https://www.cnblogs.com/jinxiang1224/p/8468354.html
Copyright © 2020-2023  润新知