【编程】界面 - 皮肤界面(自画窗口标题)

    在皮肤界面中,最难的恐怕就是自画窗口标题了,网上虽然有各种各样的解决方法,但是都不是很完美,而商业皮肤界面程序包是需要花钱买的。

其中最主要的问题有:

1、在标题栏或边框移动鼠标时系统会画窗口标题

2、没有任务栏图标。当取消了 SYS_CAPTION Style 后系统不会画窗口标题了,但是同时该窗口也没有任务栏图标。

3、最大化后在标题栏按下鼠标时系统会画窗口标题

4、按下系统按钮再移动鼠标到按钮外后没有正确的重画按钮

    没办法,只有自己摸索了,研究了网络上的一些代码片段和几个比较成功的皮肤界面程序比如 RealPlay, Microsoft Money ,发现它们采用的手法都不尽相同,而网上关于这个问题也没有很完美的解决方案,总是有点小瑕疵。最后,去研究了一下 Windows 2000 的核心代码中关于窗口管理部分,终于算是比较满意的解决了上面的这些问题,但是,我采用的方法和RealPlay, Microsoft Money 都不太一样,RealPlay 好象没有了 NC_* 的消息,而Microsoft Money 则是采用遮盖的方法,而我是采用直接重画的方法,关键是找到重画的关键点。

关键代码:

  1    BEGIN_MSG_MAP(TCaptionBaseT)
  2        MESSAGE_HANDLER(WM_NCHITTEST,            OnNCHitTest)
  3        MESSAGE_HANDLER(WM_NCPAINT,                OnNCPaint)
  4
  5        MESSAGE_HANDLER(WM_NCLBUTTONDOWN,        OnNCLButtonDown)
  6        MESSAGE_HANDLER(WM_NCLBUTTONUP,            OnNCLButtonUp)
  7        MESSAGE_HANDLER(WM_NCMOUSEMOVE,            OnNCMouseMove)
  8        MESSAGE_HANDLER(WM_LBUTTONUP,            OnLButtonUp)
  9
10        MESSAGE_HANDLER(WM_NCACTIVATE,            OnNCActivate)
11
12        MESSAGE_HANDLER(WM_SYSCOMMAND,            OnSysCommand)
13        MESSAGE_HANDLER(WM_INITMENU,            OnInitMenu)
14
15        MESSAGE_HANDLER(WM_SIZE,                OnSizeChanged)
16        MESSAGE_HANDLER(WM_STYLECHANGED ,        OnStyleChanged)
17 MESSAGE_HANDLER(WM_SETTINGCHANGE, OnSettingsChange) 18        MESSAGE_HANDLER(WM_SETTEXT,                OnSetText)
19        MESSAGE_HANDLER(WM_SETICON ,            OnSetIcon)
20
21        MESSAGE_HANDLER(WM_CREATE,                OnCreate)
22        MESSAGE_HANDLER(WM_INITDIALOG,            OnInitDialog)
23    END_MSG_MAP()
24
25    LRESULT OnNCLButtonDown(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
26    {
27        // wParam 由 OnNcHitTest 返回
28        T* pT = static_cast<T*>(this);
29       
30        POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
31        mn_ButtonPress = HTNOWHERE;
32
33        switch( wParam )
34        {
35        case HTMINBUTTON:
36        case HTMAXBUTTON:
37        case HTCLOSE:
38        case HTHELP:
39            mn_ButtonPress  = wParam;
40            mb_OnPressed    = TRUE;
41            bHandled        = TRUE;        // 表示已经处理过了,否则系统会重画按钮且 WM_NC_LBUTTONUP 不会被触发。
42            pT->doReDrawCaption();
43            break;
44        case HTCAPTION:
45            bHandled = FALSE;    // 继续让系统进行缺省处理
46            {
47                DWORD nStyle = pT->GetStyle();
48                if(nStyle & WS_MINIMIZE)
49                {
50                    return 0; // BUG: Prevents move of iconic window, but fixes Windows freeze
51                }

52                else
53                if(nStyle & WS_MAXIMIZE)
54                {
55                    // 在系统最大化的时候需要在鼠标按下时重画标题栏
56                    bHandled = TRUE; // 表示已经处理过了,否则系统会重画按钮。
57                    // 让系统对 HTCAPTION 进行处理
58                    pT->DefWindowProc(uMsg, wParam, lParam);
59                    pT->doReDrawCaption();
60                }

61            }

62            break;
63        default:
64            bHandled = FALSE;    // 继续让系统进行缺省处理
65            break;
66        }

67        return 0;
68    }

69   
70    LRESULT OnNCLButtonUp(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
71    {
72        // wParam 由 OnNcHitTest 返回
73        T* pT = static_cast<T*>(this);
74
75        mb_OnPressed = FALSE;
76
77        if(wParam == mn_ButtonPress)
78        {
79            // 鼠标按下和释放在相同的按钮上
80            POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
81            switch( wParam )
82            {
83            case HTMINBUTTON:
84                pT->PostMessage(WM_SYSCOMMAND, SC_MINIMIZE, MAKELPARAM(pt.x, pt.y));
85                bHandled = TRUE;    // 禁止系统做缺省处理
86                break;
87            case HTMAXBUTTON:
88                mn_ButtonMove = HTNOWHERE;        // 最大画后鼠标位置将改变
89                if(pT->GetStyle() & WS_MAXIMIZE)
90                    pT->PostMessage(WM_SYSCOMMAND, SC_RESTORE,  MAKELPARAM(pt.x, pt.y));
91                else
92                    pT->PostMessage(WM_SYSCOMMAND, SC_MAXIMIZE, MAKELPARAM(pt.x, pt.y));
93                bHandled = TRUE;    // 禁止系统做缺省处理
94                break;
95            case HTCLOSE:
96                pT->PostMessage(WM_CLOSE);
97                bHandled = TRUE;    // 禁止系统做缺省处理
98                break;
99            case HTHELP:
100                pT->PostMessage(WM_HELP);
101                bHandled = TRUE;    // 禁止系统做缺省处理
102                break;
103            case HTSYSMENU:
104            default:
105                bHandled = FALSE;    // 让系统进行缺省处理
106            }

107        }

108        mn_ButtonPress = HTNOWHERE;
109        return 0;
110    }

111
112    LRESULT OnLButtonUp(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
113    {
114        bHandled = FALSE;
115
116        mb_OnPressed    = FALSE;
117        mn_ButtonPress    = HTNOWHERE;
118
119        return 0;
120    }

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值