话不多说,先验货:
(原始状态)
(最大化状态)
(对比图)
为自己鼓掌!!!
哈哈,捣鼓2天终于把这个搞出来了!虽然代码一团糟,但是不难理解!
要实现这个功能需要几个组件:DWM,GDI+
在实现这个代码中我认为最困难的就是chrome边框的阴影部分~
(这里的2个像素的阴影)
和本身客户区边框的1个黑色像素,这1个像素IE11没有处理,而CHROME却没有这个黑边:
最开始使用GDI,但是GDI不带有Alpha通道,导致在画阴影时画出来的是实线,所以换成GDI+,下面是实现效果(没有采用圆角矩形,因为GDI+没有直接绘制圆角矩形的接口):
好了,上代码:
1 # include <windows.h>
2 #include <windowsx.h>
3 # include <stdio.h>
4 # include <stdlib.h>
5 #include "dwmapi.h"
6 #include "resource.h"
7 #include <gdiplus.h>
8 using namespace Gdiplus;
9
10
11 const int TOPEXTENDWIDTH = 44;
12 const int TOPEXTENDWIDTHMAX = 34;
13 const int BOTTOMEXTENDWIDTH = 8;
14 const int LEFTEXTENDWIDTH = 8;
15 const int RIGHTEXTENDWIDTH = 8;
16
17
18 LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM);
19 LRESULT AppWinProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
20 LRESULT CustomCaptionProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, bool* pfCallDWP);
21
22 bool formstateMax=false;
23
24 LRESULT HitTestNCA(HWND hWnd, WPARAM wParam, LPARAM lParam)
25 {
26
27 POINT ptMouse = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)};
28
29 RECT rcWindow;
30 GetWindowRect(hWnd, &rcWindow);
31
32
33 RECT rcFrame = { 0 };
34 AdjustWindowRectEx(&rcFrame, WS_OVERLAPPEDWINDOW & ~WS_CAPTION, FALSE, NULL);
35
36
37 USHORT uRow = 1;
38 USHORT uCol = 1;
39 bool fOnResizeBorder = false;
40
41
42 if (ptMouse.y >= rcWindow.top && ptMouse.y < rcWindow.top + (formstateMax?TOPEXTENDWIDTHMAX:TOPEXTENDWIDTH) )
43 {
44 fOnResizeBorder = (ptMouse.y < (rcWindow.top - rcFrame.top));
45 uRow = 0;
46 }
47 else if (ptMouse.y < rcWindow.bottom && ptMouse.y >= rcWindow.bottom - BOTTOMEXTENDWIDTH)
48 {
49 uRow = 2;
50 }
51
52 if (ptMouse.x >= rcWindow.left && ptMouse.x < rcWindow.left + LEFTEXTENDWIDTH)
53 {
54 uCol = 0;
55 }
56 else if (ptMouse.x < rcWindow.right && ptMouse.x >= rcWindow.right - RIGHTEXTENDWIDTH)
57 {
58 uCol = 2;
59 }
60
61 // Hit test (HTTOPLEFT, ... HTBOTTOMRIGHT)
62 LRESULT hitTests[3][3] =
63 {
64 { HTTOPLEFT, fOnResizeBorder ? HTTOP : HTCAPTION, HTTOPRIGHT },
65 { HTLEFT, HTNOWHERE, HTRIGHT },
66 { HTBOTTOMLEFT, HTBOTTOM, HTBOTTOMRIGHT },
67 };
68
69
70 return hitTests[uRow][uCol];
71 }
72
73 int RECTWIDTH(RECT trec)
74 {
75 int rWidth = 0;
76 rWidth = trec.right - trec.left;
77 return rWidth;
78 }
79
80 int RECTHEIGHT(RECT trec)
81 {
82 int rHeight = 0;
83 rHeight = trec.bottom - trec.top;
84 return rHeight;
85 }
86
87 void ReDrawExtendFrame(HWND hWnd)
88 {
89 MARGINS margins;
90
91 margins.cxLeftWidth = LEFTEXTENDWIDTH;
92 margins.cxRightWidth = RIGHTEXTENDWIDTH;
93 margins.cyBottomHeight = BOTTOMEXTENDWIDTH;
94 if (formstateMax)
95 margins.cyTopHeight = TOPEXTENDWIDTHMAX;
96 else
97 margins.cyTopHeight = TOPEXTENDWIDTH;
98
99 int hr = DwmExtendFrameIntoClientArea(hWnd, &margins);
100
101 if (!SUCCEEDED(hr))
102 {
103
104 }
105 }
106
107 int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,PSTR szCmdLine,int iCmdShow)
108 {
109 static TCHAR szAppName [] = TEXT("Pavkoo SChrome");
110 int address = (int)hInstance;
111 HWND hwnd;
112 MSG msg;
113 WNDCLASS wndclass;
114 GdiplusStartupInput gdiplusStartupInput;
115 ULONG_PTR gdiplusToken;
116 GdiplusStartup(&gdiplusToken,&gdiplusStartupInput,NULL);
117 wndclass.style = CS_HREDRAW|CS_VREDRAW;
118 wndclass.lpfnWndProc = WndProc;
119 wndclass.cbClsExtra = 0 ;
120 wndclass.cbWndExtra = 0 ;
121 wndclass.hInstance = hInstance;
122 wndclass.hIcon = LoadIcon(hInstance,MAKEINTRESOURCE(IDI_ICON1));
123 wndclass.hCursor=LoadCursor(NULL,IDC_ARROW);
124 wndclass.hbrBackground=(HBRUSH)GetStockObject(BLACK_BRUSH);
125 wndclass.lpszMenuName=NULL;
126 wndclass.lpszClassName=szAppName;
127 if(!RegisterClass(&wndclass))
128 {
129 MessageBox(NULL,TEXT("This program requires Windows NT!"),szAppName,MB_ICONERROR);
130 return 0;
131 }
132 hwnd=CreateWindow(szAppName,TEXT("Schrome"),WS_OVERLAPPEDWINDOW,
133 CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,
134 NULL,NULL,hInstance,NULL);
135 ShowWindow(hwnd,iCmdShow);
136 UpdateWindow(hwnd);
137
138 while(GetMessage(&msg,NULL,0,0))
139 {
140 TranslateMessage(&msg);
141 DispatchMessage(&msg);
142 }
143 GdiplusShutdown(gdiplusToken);
144 return msg.wParam;
145 }
146
147
148 LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
149 {
150 bool fCallDWP = true; //是否需要将消息传递给默认的窗口处理程序,如果是重绘窗体框架就不用传递消息了!
151 BOOL fDwmEnabled = FALSE;
152 LRESULT lRet = 0;
153 HRESULT hr = S_OK;
154
155 // 判断Aero Glass是否开启
156 hr = DwmIsCompositionEnabled(&fDwmEnabled);
157 if (SUCCEEDED(hr))
158 {
159 lRet = CustomCaptionProc(hWnd, message, wParam, lParam, &fCallDWP);
160 }
161
162 // 处理其他默认的消息
163 if (fCallDWP)
164 {
165 lRet = AppWinProc(hWnd, message, wParam, lParam);
166 }
167 return lRet;
168 }
169
170 //
171 // 绘制自定义窗体框架的处理程序
172 //
173 LRESULT CustomCaptionProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, bool* pfCallDWP)
174 {
175 LRESULT lRet = 0;
176 HRESULT hr = S_OK;
177 bool fCallDWP = true; // 传递给DefWindowProc
178
179 //是否需要DWM绘制非客户区
180 fCallDWP = !DwmDefWindowProc(hWnd, message, wParam, lParam, &lRet);
181
182 if (message == WM_CREATE)
183 {
184 RECT rcClient;
185 GetWindowRect(hWnd, &rcClient);
186
187 SetWindowPos(hWnd,
188 NULL,
189 rcClient.left, rcClient.top,
190 RECTWIDTH(rcClient), RECTHEIGHT(rcClient),
191 SWP_FRAMECHANGED);//触发一条WM_NCCALCSIZE消息,通吃应用程序框架大小发生改变
192
193 fCallDWP = true;
194 lRet = 0;
195 }
196
197 // 窗口激活
198 if (message == WM_ACTIVATE)
199 {
200 ReDrawExtendFrame(hWnd);
201 fCallDWP = true;
202 lRet = 0;
203 }
204
205 if (message == WM_PAINT)
206 {
207 HDC hdc;
208 PAINTSTRUCT ps;
209 {
210 hdc = BeginPaint(hWnd, &ps);
211
212 //使用gdi+绘制
213 Graphics graphicsInstance(hdc);
214 Rect rect = Rect(ps.rcPaint.left + LEFTEXTENDWIDTH,
215 ps.rcPaint.top + (formstateMax?TOPEXTENDWIDTHMAX:TOPEXTENDWIDTH),
216 ps.rcPaint.right - ps.rcPaint.left - RIGHTEXTENDWIDTH-LEFTEXTENDWIDTH ,
217 ps.rcPaint.bottom -ps.rcPaint.top -BOTTOMEXTENDWIDTH-(formstateMax?TOPEXTENDWIDTHMAX:TOPEXTENDWIDTH));
218 SolidBrush solidBrush(Color(255,255,255,255));
219 rect.Inflate(1,1);
220 graphicsInstance.FillRectangle(&solidBrush,rect);
221 Pen pen(Color(200,100,100,100));
222 graphicsInstance.DrawRectangle(&pen,rect);
223 rect.Inflate(1,1);
224 pen.SetColor(Color(60,100,100,100));
225 graphicsInstance.DrawRectangle(&pen,rect);
226 rect.Inflate(1,1);
227 pen.SetColor(Color(20,100,100,100));
228 graphicsInstance.DrawRectangle(&pen,rect);
229
230
231 //画标签
232 Rect rectTab= Rect(20,rect.Y-TOPEXTENDWIDTHMAX+3+7,190,TOPEXTENDWIDTHMAX-7);
233 solidBrush.SetColor(Color(255,255,255,255));
234 graphicsInstance.FillRectangle(&solidBrush,rectTab);
235 pen.SetColor(Color(200,100,100,100));
236 graphicsInstance.DrawRectangle(&pen,rectTab);
237 pen.SetColor(Color(255,255,255,255));
238 graphicsInstance.DrawLine(&pen,rectTab.X,rectTab.Y+rectTab.Height,rectTab.X+rectTab.Width,rectTab.Y+rectTab.Height);
239
240 Rect * add = rectTab.Clone();
241 add->Offset(add->Width +6,0);
242 add->Width = 30;
243 add->Height = 18;
244 add->Y = add->Y +4;
245 solidBrush.SetColor(Color(100,255,255,255));
246 graphicsInstance.FillRectangle(&solidBrush,*add);
247 pen.SetColor(Color(80,100,100,100));
248 graphicsInstance.DrawRectangle(&pen,*add);
249
250 SolidBrush brush(Color(255, 0, 0, 0));
251 FontFamily fontFamily(L"微软雅黑");
252 Font font(&fontFamily, 12, FontStyleRegular, UnitPixel);
253 PointF pointF(rectTab.X +10,rectTab.Y+6);
254
255 graphicsInstance.DrawString(L"打开新的标签页", -1, &font, pointF, &brush);
256 FontFamily fontFamily2(L"Gautami");
257 Font font2(&fontFamily2,12, FontStyleBold, UnitPixel);
258 PointF pointF2(rectTab.X + rectTab.Width - 10- 10 ,rectTab.Y+4);
259 brush.SetColor(Color(255, 60, 60, 60));
260 graphicsInstance.DrawString(L"x", -1, &font2, pointF2, &brush);
261
262
263 Rect rectAddress = Rect(rect.X+3,rectTab.Y+rectTab.Height,rect.Width-6,TOPEXTENDWIDTHMAX);
264 LinearGradientBrush linGrBrush(
265 Point(rectAddress.X,rectAddress.Y),
266 Point(rectAddress.X, rectAddress.Y+rectAddress.Height-2), //不包含边框
267 Color(255, 255,255, 255),
268 Color(255, 220, 220, 220)
269 );
270 graphicsInstance.FillRectangle(&linGrBrush,rectAddress);
271 pen.SetColor(Color(255,160,160,160));
272 graphicsInstance.DrawLine(&pen,rectAddress.X,rectAddress.Y+rectAddress.Height-2,rectAddress.X +rectAddress.Width,rectAddress.Y+rectAddress.Height-2);
273
274
275 Rect * left= rectAddress.Clone();
276 left->X = left->X +10;
277 left->Y = left->Y + 8;
278 left ->Width = 18;
279 left->Height = 14;
280 Image imageLeft(L"D:\\Code\\WINAPI\\chrome\\alpha\\Windowstyle\\RES\\left.png");
281 graphicsInstance.DrawImage(&imageLeft,left->X,left->Y,left->Width,left->Height);
282
283 Image imageRight(L"D:\\Code\\WINAPI\\chrome\\alpha\\Windowstyle\\RES\\right.png");
284 graphicsInstance.DrawImage(&imageRight,left->X+left->Width+15,left->Y,left->Width,left->Height);
285
286 Image imageRefresh(L"D:\\Code\\WINAPI\\chrome\\alpha\\Windowstyle\\RES\\refresh.png");
287 graphicsInstance.DrawImage(&imageRefresh,left->X+left->Width+15+left->X+left->Width,left->Y,left->Width,left->Height);
288 int leftSparate = left->X+left->Width+15+left->X+left->Width+15 + left->Width;
289 Rect rectSearch = Rect(leftSparate,rectAddress.Y +5,rectAddress.Width-leftSparate,rectAddress.Height -12);
290 solidBrush.SetColor(Color(255,255,255,255));
291 graphicsInstance.FillRectangle(&solidBrush,rectSearch.X,rectSearch.Y,rectSearch.Width,rectSearch.Height);
292 rectSearch.Inflate(1,1);
293 pen.SetColor(Color(200,200,200,200));
294 graphicsInstance.DrawRectangle(&pen,rectSearch);
295 rectSearch.Inflate(-1,-1);
296 pen.SetColor(Color(10,100,100,100));
297 graphicsInstance.DrawRectangle(&pen,rectSearch);
298
299 Image image(L"D:\\Code\\WINAPI\\chrome\\alpha\\Windowstyle\\RES\\center.png");
300 PointF point3(((ps.rcPaint.right-ps.rcPaint.left) - image.GetWidth()) / 2,((ps.rcPaint.bottom-ps.rcPaint.top) - image.GetHeight()) / 2);
301 graphicsInstance.DrawImage(&image,point3.X,point3.Y,image.GetWidth(),image.GetHeight());
302
303 EndPaint(hWnd, &ps);
304 }
305
306 fCallDWP = true;
307 lRet = 0;
308 }
309
310 // 接受非客户区大小发生改变
311 if ((message == WM_NCCALCSIZE) && (wParam == TRUE))
312 {
313 // 计算新的NCCALCSIZE_PARAMS大小
314 NCCALCSIZE_PARAMS *pncsp = reinterpret_cast<NCCALCSIZE_PARAMS*>(lParam);
315
316 pncsp->rgrc[0].left = pncsp->rgrc[0].left + 0;
317 pncsp->rgrc[0].top = pncsp->rgrc[0].top + 0;
318 pncsp->rgrc[0].right = pncsp->rgrc[0].right - 0;
319 pncsp->rgrc[0].bottom = pncsp->rgrc[0].bottom - 0;
320
321 lRet = 0;
322
323 // 这个消息没有必要传递给Defwindowproc
324 fCallDWP = false;
325 }
326
327 // 处理DwmDefWindowProc没有处理到的hit testing消息
328 if ((message == WM_NCHITTEST) && (lRet == 0))
329 {
330 lRet = HitTestNCA(hWnd, wParam, lParam);
331
332 if ((lRet != HTNOWHERE) )
333 {
334 fCallDWP = false;
335 }
336 }
337 *pfCallDWP = fCallDWP;
338
339 return lRet;
340 }
341
342 LRESULT AppWinProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
343 {
344 int wmId, wmEvent;
345 PAINTSTRUCT ps;
346 HDC hdc;
347 HRESULT hr;
348 LRESULT result = 0;
349
350 switch (message)
351 {
352 case WM_CREATE:
353 {}
354 break;
355 case WM_COMMAND:
356 wmId = LOWORD(wParam);
357 wmEvent = HIWORD(wParam);
358 switch (wmId)
359 {
360 default:
361 return DefWindowProc(hWnd, message, wParam, lParam);
362 }
363 break;
364 case WM_PAINT:
365 {
366 hdc = BeginPaint(hWnd, &ps);
367 EndPaint(hWnd, &ps);
368 }
369 break;
370 case WM_SIZE:
371 {
372 if (wParam==SIZE_MAXIMIZED)
373 {
374 formstateMax = true;
375 }
376 else
377 {
378 formstateMax = false;
379 }
380 ReDrawExtendFrame(hWnd);
381 }
382 break;
383 case WM_DESTROY:
384 PostQuitMessage(0);
385 break;
386 default:
387 return DefWindowProc(hWnd, message, wParam, lParam);
388 }
389 return 0;
390 }
参考链接:
http://msdn.microsoft.com/en-us/library/bb688195(VS.85).aspx#appendixc
http://msdn.microsoft.com/en-us/library/ms632606(VS.85).aspx
http://blog.csdn.net/oldmtn/article/details/7258003
http://www.cnblogs.com/kekec/archive/2010/10/08/1845645.html
时间: 2024-10-08 22:52:00