Win7风格DWM界面的一些高级应用 .

    DWM的高级使用

本介绍下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);

    }

}

原文地址:https://www.cnblogs.com/jinsedemaitian/p/5589112.html