您的位置:首页 > 其它

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

2012-05-21 18:49 176 查看
                  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);
    }
}
 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息