话不多说,先验货:
(原始状态)
(最大化状态)
(对比图)
为自己鼓掌!!!
哈哈,捣鼓2天终于把这个搞出来了!虽然代码一团糟,但是不难理解!
要实现这个功能需要几个组件:DWM,GDI+
在实现这个代码中我认为最困难的就是chrome边框的阴影部分~
(这里的2个像素的阴影)
和本身客户区边框的1个黑色像素,这1个像素IE11没有处理,而CHROME却没有这个黑边:
最开始使用GDI,但是GDI不带有Alpha通道,导致在画阴影时画出来的是实线,所以换成GDI+,下面是实现效果(没有采用圆角矩形,因为GDI+没有直接绘制圆角矩形的接口):
好了,上代码:
# include <windows.h>
#include <windowsx.h>
# include <stdio.h>
# include <stdlib.h>
#include "dwmapi.h"
#include "resource.h"
#include <gdiplus.h>
using namespace Gdiplus; const int TOPEXTENDWIDTH = ;
const int TOPEXTENDWIDTHMAX = ;
const int BOTTOMEXTENDWIDTH = ;
const int LEFTEXTENDWIDTH = ;
const int RIGHTEXTENDWIDTH = ; LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM);
LRESULT AppWinProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
LRESULT CustomCaptionProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, bool* pfCallDWP); bool formstateMax=false; LRESULT HitTestNCA(HWND hWnd, WPARAM wParam, LPARAM lParam)
{ POINT ptMouse = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)}; RECT rcWindow;
GetWindowRect(hWnd, &rcWindow); RECT rcFrame = { };
AdjustWindowRectEx(&rcFrame, WS_OVERLAPPEDWINDOW & ~WS_CAPTION, FALSE, NULL); USHORT uRow = ;
USHORT uCol = ;
bool fOnResizeBorder = false; if (ptMouse.y >= rcWindow.top && ptMouse.y < rcWindow.top + (formstateMax?TOPEXTENDWIDTHMAX:TOPEXTENDWIDTH) )
{
fOnResizeBorder = (ptMouse.y < (rcWindow.top - rcFrame.top));
uRow = ;
}
else if (ptMouse.y < rcWindow.bottom && ptMouse.y >= rcWindow.bottom - BOTTOMEXTENDWIDTH)
{
uRow = ;
} if (ptMouse.x >= rcWindow.left && ptMouse.x < rcWindow.left + LEFTEXTENDWIDTH)
{
uCol = ;
}
else if (ptMouse.x < rcWindow.right && ptMouse.x >= rcWindow.right - RIGHTEXTENDWIDTH)
{
uCol = ;
} // Hit test (HTTOPLEFT, ... HTBOTTOMRIGHT)
LRESULT hitTests[][] =
{
{ HTTOPLEFT, fOnResizeBorder ? HTTOP : HTCAPTION, HTTOPRIGHT },
{ HTLEFT, HTNOWHERE, HTRIGHT },
{ HTBOTTOMLEFT, HTBOTTOM, HTBOTTOMRIGHT },
}; return hitTests[uRow][uCol];
} int RECTWIDTH(RECT trec)
{
int rWidth = ;
rWidth = trec.right - trec.left;
return rWidth;
} int RECTHEIGHT(RECT trec)
{
int rHeight = ;
rHeight = trec.bottom - trec.top;
return rHeight;
} void ReDrawExtendFrame(HWND hWnd)
{
MARGINS margins; margins.cxLeftWidth = LEFTEXTENDWIDTH;
margins.cxRightWidth = RIGHTEXTENDWIDTH;
margins.cyBottomHeight = BOTTOMEXTENDWIDTH;
if (formstateMax)
margins.cyTopHeight = TOPEXTENDWIDTHMAX;
else
margins.cyTopHeight = TOPEXTENDWIDTH; int hr = DwmExtendFrameIntoClientArea(hWnd, &margins); if (!SUCCEEDED(hr))
{ }
} int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,PSTR szCmdLine,int iCmdShow)
{
static TCHAR szAppName [] = TEXT("Pavkoo SChrome");
int address = (int)hInstance;
HWND hwnd;
MSG msg;
WNDCLASS wndclass;
GdiplusStartupInput gdiplusStartupInput;
ULONG_PTR gdiplusToken;
GdiplusStartup(&gdiplusToken,&gdiplusStartupInput,NULL);
wndclass.style = CS_HREDRAW|CS_VREDRAW;
wndclass.lpfnWndProc = WndProc;
wndclass.cbClsExtra = ;
wndclass.cbWndExtra = ;
wndclass.hInstance = hInstance;
wndclass.hIcon = LoadIcon(hInstance,MAKEINTRESOURCE(IDI_ICON1));
wndclass.hCursor=LoadCursor(NULL,IDC_ARROW);
wndclass.hbrBackground=(HBRUSH)GetStockObject(BLACK_BRUSH);
wndclass.lpszMenuName=NULL;
wndclass.lpszClassName=szAppName;
if(!RegisterClass(&wndclass))
{
MessageBox(NULL,TEXT("This program requires Windows NT!"),szAppName,MB_ICONERROR);
return ;
}
hwnd=CreateWindow(szAppName,TEXT("Schrome"),WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,
NULL,NULL,hInstance,NULL);
ShowWindow(hwnd,iCmdShow);
UpdateWindow(hwnd); while(GetMessage(&msg,NULL,,))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
GdiplusShutdown(gdiplusToken);
return msg.wParam;
} LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
bool fCallDWP = true; //是否需要将消息传递给默认的窗口处理程序,如果是重绘窗体框架就不用传递消息了!
BOOL fDwmEnabled = FALSE;
LRESULT lRet = ;
HRESULT hr = S_OK; // 判断Aero Glass是否开启
hr = DwmIsCompositionEnabled(&fDwmEnabled);
if (SUCCEEDED(hr))
{
lRet = CustomCaptionProc(hWnd, message, wParam, lParam, &fCallDWP);
} // 处理其他默认的消息
if (fCallDWP)
{
lRet = AppWinProc(hWnd, message, wParam, lParam);
}
return lRet;
} //
// 绘制自定义窗体框架的处理程序
//
LRESULT CustomCaptionProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, bool* pfCallDWP)
{
LRESULT lRet = ;
HRESULT hr = S_OK;
bool fCallDWP = true; // 传递给DefWindowProc //是否需要DWM绘制非客户区
fCallDWP = !DwmDefWindowProc(hWnd, message, wParam, lParam, &lRet); if (message == WM_CREATE)
{
RECT rcClient;
GetWindowRect(hWnd, &rcClient); SetWindowPos(hWnd,
NULL,
rcClient.left, rcClient.top,
RECTWIDTH(rcClient), RECTHEIGHT(rcClient),
SWP_FRAMECHANGED);//触发一条WM_NCCALCSIZE消息,通吃应用程序框架大小发生改变 fCallDWP = true;
lRet = ;
} // 窗口激活
if (message == WM_ACTIVATE)
{
ReDrawExtendFrame(hWnd);
fCallDWP = true;
lRet = ;
} if (message == WM_PAINT)
{
HDC hdc;
PAINTSTRUCT ps;
{
hdc = BeginPaint(hWnd, &ps); //使用gdi+绘制
Graphics graphicsInstance(hdc);
Rect rect = Rect(ps.rcPaint.left + LEFTEXTENDWIDTH,
ps.rcPaint.top + (formstateMax?TOPEXTENDWIDTHMAX:TOPEXTENDWIDTH),
ps.rcPaint.right - ps.rcPaint.left - RIGHTEXTENDWIDTH-LEFTEXTENDWIDTH ,
ps.rcPaint.bottom -ps.rcPaint.top -BOTTOMEXTENDWIDTH-(formstateMax?TOPEXTENDWIDTHMAX:TOPEXTENDWIDTH));
SolidBrush solidBrush(Color(,,,));
rect.Inflate(,);
graphicsInstance.FillRectangle(&solidBrush,rect);
Pen pen(Color(,,,));
graphicsInstance.DrawRectangle(&pen,rect);
rect.Inflate(,);
pen.SetColor(Color(,,,));
graphicsInstance.DrawRectangle(&pen,rect);
rect.Inflate(,);
pen.SetColor(Color(,,,));
graphicsInstance.DrawRectangle(&pen,rect); //画标签
Rect rectTab= Rect(,rect.Y-TOPEXTENDWIDTHMAX++,,TOPEXTENDWIDTHMAX-);
solidBrush.SetColor(Color(,,,));
graphicsInstance.FillRectangle(&solidBrush,rectTab);
pen.SetColor(Color(,,,));
graphicsInstance.DrawRectangle(&pen,rectTab);
pen.SetColor(Color(,,,));
graphicsInstance.DrawLine(&pen,rectTab.X,rectTab.Y+rectTab.Height,rectTab.X+rectTab.Width,rectTab.Y+rectTab.Height); Rect * add = rectTab.Clone();
add->Offset(add->Width +,);
add->Width = ;
add->Height = ;
add->Y = add->Y +;
solidBrush.SetColor(Color(,,,));
graphicsInstance.FillRectangle(&solidBrush,*add);
pen.SetColor(Color(,,,));
graphicsInstance.DrawRectangle(&pen,*add); SolidBrush brush(Color(, , , ));
FontFamily fontFamily(L"微软雅黑");
Font font(&fontFamily, , FontStyleRegular, UnitPixel);
PointF pointF(rectTab.X +,rectTab.Y+); graphicsInstance.DrawString(L"打开新的标签页", -, &font, pointF, &brush);
FontFamily fontFamily2(L"Gautami");
Font font2(&fontFamily2,, FontStyleBold, UnitPixel);
PointF pointF2(rectTab.X + rectTab.Width - - ,rectTab.Y+);
brush.SetColor(Color(, , , ));
graphicsInstance.DrawString(L"x", -, &font2, pointF2, &brush); Rect rectAddress = Rect(rect.X+,rectTab.Y+rectTab.Height,rect.Width-,TOPEXTENDWIDTHMAX);
LinearGradientBrush linGrBrush(
Point(rectAddress.X,rectAddress.Y),
Point(rectAddress.X, rectAddress.Y+rectAddress.Height-), //不包含边框
Color(, ,, ),
Color(, , , )
);
graphicsInstance.FillRectangle(&linGrBrush,rectAddress);
pen.SetColor(Color(,,,));
graphicsInstance.DrawLine(&pen,rectAddress.X,rectAddress.Y+rectAddress.Height-,rectAddress.X +rectAddress.Width,rectAddress.Y+rectAddress.Height-); Rect * left= rectAddress.Clone();
left->X = left->X +;
left->Y = left->Y + ;
left ->Width = ;
left->Height = ;
Image imageLeft(L"D:\\Code\\WINAPI\\chrome\\alpha\\Windowstyle\\RES\\left.png");
graphicsInstance.DrawImage(&imageLeft,left->X,left->Y,left->Width,left->Height); Image imageRight(L"D:\\Code\\WINAPI\\chrome\\alpha\\Windowstyle\\RES\\right.png");
graphicsInstance.DrawImage(&imageRight,left->X+left->Width+,left->Y,left->Width,left->Height); Image imageRefresh(L"D:\\Code\\WINAPI\\chrome\\alpha\\Windowstyle\\RES\\refresh.png");
graphicsInstance.DrawImage(&imageRefresh,left->X+left->Width++left->X+left->Width,left->Y,left->Width,left->Height);
int leftSparate = left->X+left->Width++left->X+left->Width+ + left->Width;
Rect rectSearch = Rect(leftSparate,rectAddress.Y +,rectAddress.Width-leftSparate,rectAddress.Height -);
solidBrush.SetColor(Color(,,,));
graphicsInstance.FillRectangle(&solidBrush,rectSearch.X,rectSearch.Y,rectSearch.Width,rectSearch.Height);
rectSearch.Inflate(,);
pen.SetColor(Color(,,,));
graphicsInstance.DrawRectangle(&pen,rectSearch);
rectSearch.Inflate(-,-);
pen.SetColor(Color(,,,));
graphicsInstance.DrawRectangle(&pen,rectSearch); Image image(L"D:\\Code\\WINAPI\\chrome\\alpha\\Windowstyle\\RES\\center.png");
PointF point3(((ps.rcPaint.right-ps.rcPaint.left) - image.GetWidth()) / ,((ps.rcPaint.bottom-ps.rcPaint.top) - image.GetHeight()) / );
graphicsInstance.DrawImage(&image,point3.X,point3.Y,image.GetWidth(),image.GetHeight()); EndPaint(hWnd, &ps);
} fCallDWP = true;
lRet = ;
} // 接受非客户区大小发生改变
if ((message == WM_NCCALCSIZE) && (wParam == TRUE))
{
// 计算新的NCCALCSIZE_PARAMS大小
NCCALCSIZE_PARAMS *pncsp = reinterpret_cast<NCCALCSIZE_PARAMS*>(lParam); pncsp->rgrc[].left = pncsp->rgrc[].left + ;
pncsp->rgrc[].top = pncsp->rgrc[].top + ;
pncsp->rgrc[].right = pncsp->rgrc[].right - ;
pncsp->rgrc[].bottom = pncsp->rgrc[].bottom - ; lRet = ; // 这个消息没有必要传递给Defwindowproc
fCallDWP = false;
} // 处理DwmDefWindowProc没有处理到的hit testing消息
if ((message == WM_NCHITTEST) && (lRet == ))
{
lRet = HitTestNCA(hWnd, wParam, lParam); if ((lRet != HTNOWHERE) )
{
fCallDWP = false;
}
}
*pfCallDWP = fCallDWP; return lRet;
} LRESULT AppWinProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
PAINTSTRUCT ps;
HDC hdc;
HRESULT hr;
LRESULT result = ; switch (message)
{
case WM_CREATE:
{}
break;
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
switch (wmId)
{
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
break;
case WM_PAINT:
{
hdc = BeginPaint(hWnd, &ps);
EndPaint(hWnd, &ps);
}
break;
case WM_SIZE:
{
if (wParam==SIZE_MAXIMIZED)
{
formstateMax = true;
}
else
{
formstateMax = false;
}
ReDrawExtendFrame(hWnd);
}
break;
case WM_DESTROY:
PostQuitMessage();
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return ;
}
参考链接:
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.****.net/oldmtn/article/details/7258003
http://www.cnblogs.com/kekec/archive/2010/10/08/1845645.html