在皮肤界面中,最难的恐怕就是自画窗口标题了,网上虽然有各种各样的解决方法,但是都不是很完美,而商业皮肤界面程序包是需要花钱买的。
其中最主要的问题有:
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
}
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。