标题:MFC对话框非客户区完美自绘
只看楼主
我菜119
Rank: 10Rank: 10Rank: 10
等 级:青峰侠
帖 子:938
专家分:1756
注 册:2009-10-17
结帖率:98.26%
已结贴  问题点数:100 回复次数:21 
MFC对话框非客户区完美自绘
声明:这篇帖子我在csdn上发表了,好久没来编程中国了,希望可以把更多的东西分享给大家,同时与大家交流学习!!!

下载地址:
http://download.

贴张效果图:


如果大家觉得效果一般的话,可是参看代码,自己进行改进

我们先从ON_WM_NCHITTEST这个消息入手,其消息映射函数为OnNcHitTest(CPoint point),该消息的作用是:命中测试,即判断鼠标当前位于窗口的什么地方,比如:HTCAPTION(标题栏上),HTMINBUTTON(最小化按钮上)等等,并将测试的结果作为返回值,,在标题栏上的最小化、最大化和关闭“按钮”其实并非真正的按钮,而是我们绘制的位图,使其看起来好像是一个个按钮,于是乎,当我们产生一个WM_LBUTTONDOWN消息,如何知道是否按在了“按钮”呢,这些工作全靠OnNcHitTest函数的返回来进行判断,因此这个消息的处理对我们后续的工作起到至关重要的角色。

我们按照自己的想法,设定了最小化、最大化和关闭“按钮”的位置,程序中我设定它们的位置相对于窗口左上角(0, 0),所以在OnNcHitTest函数中,还需要将这些位置转换为相对于屏幕的坐标,具体的转换,参看BOOL PtInRect(CRect &rtWin, CRect &rtClientBtn, CPoint &pt)函数,

程序代码:
HRESULT CDrawDlg::OnNcHitTest(CPoint point)
{
    CRect rtWin;
    GetWindowRect(&rtWin);

 
    if(PtInRect(rtWin, m_rtCloseBox, point))
    {
        return HTCLOSE;
    }
    if(PtInRect(rtWin, m_rtMaxBox, point))
    {
        return HTMAXBUTTON;
    }
    if(PtInRect(rtWin, m_rtMinBox, point))
    {
        return HTMINBUTTON;
    }
    return CDialog::OnNcHitTest(point);
}


然后再说一下ON_WM_NCRBUTTONDOWN这个消息,其映射函数为OnNcRButtonDown(UINT nHitTest, CPoint point),这个消息将决定即将弹出的系统菜单,如果当前鼠标的位置位于最小化、最大化或是关闭“按钮”上,阻止即将弹出的系统菜单,这样就需要屏蔽掉HTCLOSE、HTMINBUTTON和HTMAXBUTTON情况,很多人看到人想到的是应该是处理ON_WM_NCRBUTTONUP消息,开始的时候我也是这样想的,可是实际上这是徒劳的,仍然会弹出系统菜单,没办法只有处理ON_WM_NCRBUTTONDOWN消息了,
程序代码:
void CDrawDlg::OnNcRButtonDown(UINT nHitTest, CPoint point)
{
    if(HTCLOSE == nHitTest || HTMAXBUTTON == nHitTest || HTMINBUTTON == nHitTest)
    {
        return;
    }
    CDialog::OnNcRButtonDown(nHitTest, point);
}

一个对话框窗口有可能存在几种风格,可能只存在/不存在标题栏,也可能只存在关闭按钮,或是还包含一个最大化按钮,也可能还包含一个最小化按钮,程序中针对这一情况添加了处理函数,GetWindowStyle()用于获取当前窗口的风格,程序启动时在PreSubclassWindow()中调用一次,在OnNcPaint()处理中参考获取到的窗口风格进行绘制,同时,用户还可能在外部调用SetWindowLong()给窗口设置新的风格,针对这一情况,也添加了额外的消息处理:ON_WM_STYLECHANGED,WM_STYLECHANGED是当窗口风格发生改变时发送的消息,在该消息的处理函数中再次调用GetWindowStyle()函数获取到窗口新的风格。


最后说一下一个比较重要的问题,当我们做完上述的工作后,运行程序,会发现会出现默认的关闭/最小化/最大化按钮,这是我们不希望看到的,究其原因,是WM_NCUAHDRAWCAPTION和WM_NCUAHDRAWFRAME这两个该死的消息在作怪,我想把这两个消息详细的讲解一下,可是居然在msdn上没有找到这两个消息,还好,最后在一篇帖子上找到了这样一段话:

原来是windows对绘制处理的一个操作(XP才增加的消息),猜测是一个只有微软内部才知道的BUG处理,其处理方式是通过向标题栏发送以下消息以解决余留问题,但我们重写后未曾予以适当的处理,故出现如题所述的现象


而我们大家所作的就是屏蔽掉这两个消息,不做任何的处理。


欢迎和大家一起交流学习,如果有什么问题,回复在该帖子里就行!
搜索更多相关主题的帖子: 下载地址 效果图 对话框 标题栏 
2013-11-01 16:16
yuccn
Rank: 16Rank: 16Rank: 16Rank: 16
来 自:何方
等 级:版主
威 望:167
帖 子:6809
专家分:42393
注 册:2010-12-16
得分:10 
友谊支持一下

我行我乐
我的博客:
http://blog.yuccn. net
2013-11-01 16:23
wp231957
Rank: 16Rank: 16Rank: 16Rank: 16
来 自:神界
等 级:版主
威 望:422
帖 子:13681
专家分:53296
注 册:2012-10-18
得分:10 
友情标记一下

DO IT YOURSELF !
2013-11-01 16:34
heroinearth
Rank: 10Rank: 10Rank: 10
来 自:云南曲靖
等 级:青峰侠
帖 子:430
专家分:1506
注 册:2011-10-24
得分:10 
友谊支持一下
2013-11-01 18:08
haiboself
Rank: 3Rank: 3
等 级:论坛游侠
帖 子:193
专家分:196
注 册:2013-10-23
得分:10 
跟随各位大神也支持一下!!!
2013-11-01 18:51
pauljames
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
等 级:千里冰封
威 望:9
帖 子:1555
专家分:10000
注 册:2011-5-8
得分:10 
多谢分享

经常不在线不能及时回复短消息,如有c/单片机/运动控制/数据采集等方面的项目难题可加qq1921826084。
2013-11-01 19:20
Susake
Rank: 15Rank: 15Rank: 15Rank: 15Rank: 15
来 自:女儿国的隔壁
等 级:贵宾
威 望:23
帖 子:2288
专家分:6481
注 册:2012-12-14
得分:10 
以下是引用heroinearth在2013-11-1 18:08:38的发言:

友谊支持一下


仰望星空...........不忘初心!
2013-11-02 13:30
ssz8930
Rank: 2
等 级:论坛游民
帖 子:21
专家分:38
注 册:2012-10-30
得分:10 
支持
2013-11-02 16:23
a592963144
Rank: 2
等 级:论坛游民
帖 子:41
专家分:95
注 册:2013-9-27
得分:5 
感觉都很厉害
2013-11-02 17:48
tlliqi
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
等 级:贵宾
威 望:204
帖 子:15453
专家分:65956
注 册:2006-4-27
得分:5 
支持一下!!!
2013-11-02 18:22



参与讨论请移步原网站贴子:https://bbs.bccn.net/thread-422893-1-1.html




关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.015681 second(s), 8 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved