首页 > 代码库 > 模拟Chrome皮肤

模拟Chrome皮肤

话不多说,先验货:

(原始状态)

image

(最大化状态)

image

(对比图)

image

为自己鼓掌!!!

哈哈,捣鼓2天终于把这个搞出来了!虽然代码一团糟,但是不难理解!

要实现这个功能需要几个组件:DWM,GDI+

在实现这个代码中我认为最困难的就是chrome边框的阴影部分~

image

(这里的2个像素的阴影)

和本身客户区边框的1个黑色像素,这1个像素IE11没有处理,而CHROME却没有这个黑边:

image

最开始使用GDI,但是GDI不带有Alpha通道,导致在画阴影时画出来的是实线,所以换成GDI+,下面是实现效果(没有采用圆角矩形,因为GDI+没有直接绘制圆角矩形的接口):

image

 

 

好了,上代码:

  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