本介绍下win7下dwm的一些高级使用,如果还不了解dwm的基础的朋友可以先看下dwm的基础应用,本文主要讨论下如何使用dwm进行自己绘制标题以及如何改变鼠标点击测试,重点是解决gdiplus与透明界面的融合问题。
开发环境为win7和vs2010,编码语音采用c++,win32的sdk平台进行开发。下面先从第一个问题说起,
我们也许自己利用DwmExtendFrameIntoClientArea函数进行了简单的绘制,就像这样
MARGINSmargins={-1};
margins.cxLeftWidth = leftlength; // 8
margins.cxRightWidth = rightlength; // 8
margins.cyBottomHeight = bottomlength; // 20
margins.cyTopHeight = toplength; // 27
DwmExtendFrameIntoClientArea(hWnd,&margins);
然后界面就变成了这样 ,但是当我们用鼠标点击上标题下边自己扩展出的区域时,发现鼠标事件不起作用了,于是想该怎么办呢?然后有人想到改变WM_NCCALCSIZE,这样做是不行的,本人亲自做过实验,会导致一部分界面变成白色,然后程序猿们纠结了,这如何是好,当然笔者也让这个问题困扰了好久,然后看到有位大神的文章解决了这个问题,文章地址(http://msdn.microsoft.com/en-us/library/bb688195(VS.85).aspx)把这个文章阅读一次,然后进过消化总结,大概如下几步,先将原来的WndProc函数分成两份,一份是CustomCaptionProc,另一份是AppWinProc,然后我们在自己定义的回调函数中处理标题绘制和点击测试。
自己定义的回调函数要处理5个消息WM_CREATE,WM_ACTIVATE,WM_PAINT,WM_NCCALCSIZE,WM_NCHITTEST,虽然WM_NCCALSIZE中令非客户增加均为0,但是必须要做,这样才能让系统改变非客户区以实现我们自己去绘制软件界面,然后然后照着大神的代码抄写一遍,自己理解下其中他做了一些什么事情。除了以上要注意的地方,其他都是具体代码实现了,我就不做说明了。OK了鼠标点击问题搞定了,其中比较重要的是要掌握dwmwinproc控制界面的时机,然后调用NCHITTEST去处理界面控制请求,当然还有其他处理方式(把他们全部变成客户区,然后自己绘制界面上的缩小放大关闭框),不过这样的方式付出的代价会变的很大!这样你会发现出现这样的情况:
我们的界面的标题没了,于是我们就该想到自己去绘制一个标题给这个窗口,现在
我们解决自己绘制标题的过程,以下是我自己写的几个绘制标题的方式,其中第三种绘制方式可能让你感觉在什么情况下都能利用,但是你若仔细去看会发现它的处理会导致在启用了DwmEnableBlurBehindWindow的情况下颜色部分失真,也就是变浅!大家可以将我写的三个绘制标题的函数与SetLayeredWindowAttributes和DwmEnableBlurBehindWindow两者进行组合,你会发现很多有趣的现象,这些情况我就不进行介绍了,原理我目前也无法分析清楚,
我们可以利用PaintCustomCaption3方式进行绘制窗口的标题,在使用了SetLayeredWindowAttributes时,我们需要采用PaintCustomCaption3的方式进行窗口的标题的绘制。其他情况先不说了,自己去体验吧!(绘制代码放在最后,需要的可以去看下),然后说明如何解决上次说的控件鼠标局部穿透问题,采用解决方案首先获取原来窗口的风格,然后将窗口的风格中CS_PARENTDC去除这样就可以设置子窗口的形状,然后将其形状改变为我们要绘制的形状,完美解决gdiplus和DWM进行窗口绘制时的问题,不加代码前点击“这是个按钮”周围4个角落时会出现鼠标穿透现象,原因是我先将其进行透明色填充,然后再进行按钮样式的绘制,就会产生鼠标穿透界面到达位于界面后方的现象!(最后把关键部分代码附上!)
DWORD style = GetClassLong(g_hedit, GCL_STYLE);
SetClassLong(g_hedit, GCL_STYLE, style &~CS_PARENTDC);
HRGN hRgn = CreateEllipticRgn(0, 0, 120,30);
SetWindowRgn(g_hedit, hRgn, FALSE);
然后附上3个绘制标题的函数!结合我上传的dwm上次出现穿透现象的程序一起使用!
voidPaintCustomCaption(HWND hWnd, HDC hdc,LPCTSTR strContent,COLORREF color)
{
RECT rcClient;
GetClientRect(hWnd, &rcClient);
HTHEME hTheme =OpenThemeData(::GetDesktopWindow(), L"Window");
if (hTheme)
{
HDC hdcPaint = CreateCompatibleDC(hdc);
if(hdcPaint)
{
intcx = rcClient.right-rcClient.left;
intcy = rcClient.bottom-rcClient.top;
// Definethe BITMAPINFO structure used to draw text.
// Notethat biHeight is negative. This is done because
//DrawThemeTextEx() needs the bitmap to be in top-to-bottom
// order.
BITMAPINFO dib = { 0 };
dib.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
dib.bmiHeader.biWidth = 150;
dib.bmiHeader.biHeight = -30;
dib.bmiHeader.biPlanes = 1;
dib.bmiHeader.biBitCount = 32;
dib.bmiHeader.biCompression = BI_RGB;
HBITMAP hbm = CreateDIBSection(hdc,&dib, DIB_RGB_COLORS, NULL, NULL, 0);
if(hbm)
{
HBITMAP hbmOld =(HBITMAP)SelectObject(hdcPaint, hbm);
HBRUSHThemeBrush=CreateSolidBrush(TRANSPARENT_COLOR);
FillRect(hdcPaint,&rcClient,ThemeBrush);
// Setupthe theme drawing options.
DTTOPTS DttOpts = {sizeof(DTTOPTS)};
DttOpts.dwFlags = DTT_COMPOSITED |DTT_GLOWSIZE|DTT_TEXTCOLOR|DTT_SHADOWTYPE;
DttOpts.iGlowSize = 20;
DttOpts.crText = color;
DttOpts.iTextShadowType = 32;
//Select a font.
LOGFONT lgFont={0};
HFONT hFontOld = NULL;
HFONT hFont = CreateFont(0,0,0,0,400,
FALSE,FALSE,FALSE,DEFAULT_CHARSET,
OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,PROOF_QUALITY,DEFAULT_PITCH,
L"华文行楷");
hFontOld = (HFONT)SelectObject(hdcPaint, hFont);
// Drawthe title.
RECT rcPaint = rcClient;
rcPaint.top += 8;
rcPaint.right -= 0;
rcPaint.left += 8;
rcPaint.bottom = 50;
DrawThemeTextEx(hTheme,
hdcPaint,
0, 0,
strContent,
-1,
DT_LEFT | DT_WORD_ELLIPSIS,
&rcPaint,
&DttOpts);
BLENDFUNCTION ftn = { 0 };
ftn.BlendOp = AC_SRC_OVER; //目前只能设置这个值
ftn.AlphaFormat =AC_SRC_ALPHA; // 也只能设置这个值
ftn.BlendFlags = 0; //必须为0
ftn.SourceConstantAlpha =255; //指定源图片的alpha
// 调用这个函数来进行Alpha混合
AlphaBlend(hdcPaint,0,0,150,30,hdc,0,0,150,30,ftn);
// Blittext to the frame.
BitBlt(hdc, 0, 0, cx, cy,hdcPaint, 0, 0, SRCCOPY);
SelectObject(hdcPaint, hbmOld);
if(hFontOld)
{
SelectObject(hdcPaint,hFontOld);
}
DeleteObject(hbm);
}
DeleteDC(hdcPaint);
}
CloseThemeData(hTheme);
}
}
voidPaintCustomCaption2(HWND hWnd, HDC hdc,LPCTSTR strContent,COLORREF color)
{
HTHEME hTheme =OpenThemeData(::GetDesktopWindow(), L"Window");
HDC hdcPaint = CreateCompatibleDC(hdc);
RECT rcClient;
GetClientRect(hWnd, &rcClient);
int cx =rcClient.right-rcClient.left;
int cy =rcClient.bottom-rcClient.top;
if (hTheme)
{
DTTOPTS DttOpts = {sizeof(DTTOPTS)};
DttOpts.dwFlags = DTT_COMPOSITED | DTT_GLOWSIZE|DTT_TEXTCOLOR|DTT_SHADOWTYPE;
DttOpts.iGlowSize = 1;
DttOpts.crText = color;
DttOpts.iTextShadowType = 2;
// Select afont.
LOGFONT lgFont={0};
HFONT hFontOld = NULL;
HFONT hFont = CreateFont(0,0,0,0,400,
FALSE,FALSE,FALSE,DEFAULT_CHARSET,
OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,PROOF_QUALITY,DEFAULT_PITCH,
L"华文行楷");
hFontOld = (HFONT)SelectObject(hdc,hFont);
// Draw thetitle.
RECT rcPaint = rcClient;
rcPaint.top += 8;
rcPaint.right -= 0;
rcPaint.left += 8;
rcPaint.bottom = 50;
DrawThemeTextEx(hTheme,
hdc,
0, 0,
strContent,
-1,
DT_LEFT | DT_WORD_ELLIPSIS,
&rcPaint,
&DttOpts);
// Blit text tothe frame.
SelectObject(hdc,hFontOld);
}
CloseThemeData(hTheme);
}
voidPaintCustomCaption3(HWND hWnd, HDC hdc,LPCTSTR strContent,COLORREF color)
{
RECT rcClient;
GetClientRect(hWnd, &rcClient);
HTHEME hTheme = OpenThemeData(NULL, L"CompositedWindow::Window");
if (hTheme)
{
HDC hdcPaint = CreateCompatibleDC(hdc);
if(hdcPaint)
{
intcx =rcClient.right-rcClient.left;
intcy =rcClient.bottom-rcClient.top;
// Definethe BITMAPINFO structure used to draw text.
// Notethat biHeight is negative. This is done because
//DrawThemeTextEx() needs the bitmap to be in top-to-bottom
// order.
BITMAPINFO dib = { 0 };
dib.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
dib.bmiHeader.biWidth = cx;
dib.bmiHeader.biHeight = -cy;
dib.bmiHeader.biPlanes = 1;
dib.bmiHeader.biBitCount = BIT_COUNT;
dib.bmiHeader.biCompression = BI_RGB;
HBITMAP hbm = CreateDIBSection(hdc,&dib, DIB_RGB_COLORS, NULL, NULL, 0);
if(hbm)
{
HBITMAP hbmOld =(HBITMAP)SelectObject(hdcPaint, hbm);
// Setupthe theme drawing options.
DTTOPTS DttOpts = {sizeof(DTTOPTS)};
DttOpts.dwFlags = DTT_COMPOSITED |DTT_GLOWSIZE|DTT_TEXTCOLOR|DTT_SHADOWTYPE;
DttOpts.iGlowSize = 20;
DttOpts.crText = color;
DttOpts.iTextShadowType = 2;
//Select a font.
LOGFONT lgFont={0};
HFONT hFontOld = NULL;
HFONT hFont = CreateFont(0,0,0,0,400,
FALSE,FALSE,FALSE,DEFAULT_CHARSET,
OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,PROOF_QUALITY,DEFAULT_PITCH,
L"华文行楷");
hFontOld = (HFONT)SelectObject(hdcPaint, hFont);
// Drawthe title.
RECT rcPaint = rcClient;
rcPaint.top += 8;
rcPaint.right -= 0;
rcPaint.left += 8;
rcPaint.bottom = 50;
DrawThemeTextEx(hTheme,
hdcPaint,
0, 0,
strContent,
-1,
DT_LEFT | DT_WORD_ELLIPSIS,
&rcPaint,
&DttOpts);
// Blittext to the frame.
BitBlt(hdc, 0, 0, cx, cy,hdcPaint, 0, 0, SRCCOPY);
SelectObject(hdcPaint, hbmOld);
if(hFontOld)
{
SelectObject(hdcPaint,hFontOld);
}
DeleteObject(hbm);
}
DeleteDC(hdcPaint);
}
CloseThemeData(hTheme);
}
}