现在的位置: 首页 > 综合 > 正文

VC++调用UpdateLayeredWindow实现半透明窗体【转】

2013年09月30日 ⁄ 综合 ⁄ 共 2779字 ⁄ 字号 评论关闭

半年没碰MFC了 , 感觉是那么的陌生 , 忘记了绝大部分函数了....‍你说我现在都有点学这忘哪,以后能跟的上技术的发展嘛?

      注意:由于代码有点长,直接放在这里显得冗长,所以,如果需要源码的朋友请发邮件或留言,代码只是互相学习之用,由于本人水平有限,如果您觉得不好,望理解,且不要有攻击性的言行,谢谢!)

        首先看看我做的效果,有点像Vista的效果,而且解决了控件不能显示的问题,注意上层是一个子窗体,用来承载窗体控件:

     


         最近看了桌面天气秀这款小软件,其界面精致漂亮,而且可以透明显示,还有个特别有趣的功能就是能让窗体固定在桌面上并且鼠标可以“穿透”而窗体不受任何影响,这就是带着些许神秘的“有影无形”的功能。

         事实上要实现这种“有影无形”的功能,很简单,我相信聪明的您一定很快会想到怎么做。几句代码就可以搞定,给你点提示,只有在2000以上的Win操作系统才支持(当然如果你有足够的时间可以完全可以在98上实现)。那么今天我们主要讨论一下窗体的半透明显示,其实,如果仅仅要实现窗体的半透明显示,很简单,UpdateLayeredWindow调用就可以了,网上去搜一下几乎都是贴的这个函数怎么怎么实现窗体的半透明,在往下就没了,比如此函数有个缺陷,就是经过此函数处理过的窗体,其上面的控件都透明了。诸如此类的问题至少到现在我在网上没找到一个让人感觉满意的解决方案。

       记得在一个所谓专业的C#网站上看到一篇题为“XP下透明窗体的完美实现”,当时看了还真高兴一阵子,可是把代码下下来一看,又是被忽悠了,里面就调用了UpdateLayeredWindow函数实现透明然后加个旋转显示,这样子就算完美了,我晕!这个函数查查资料谁不会。看来还是自己动手,不知道有心的朋友注意到没有,在桌面天气秀里,打开设置,然后快速拖动,会看到上面的窗体明显脱离,这就是多层窗口留下的尾巴。下面的透明窗体是背景,上面的窗体承载控件。在拖动下层窗体的时候让上层窗体跟着一起动。对于小软件来说,效果还可以。事实上,今天我实现的也和这个思路差不多,不过我这个上下两层窗体是父子关系,它们各施其职,但是又没有拖动时留下的尾巴(窗口移动的处理),我把这些功能都封装在一起了,只需要简单地把你要在透明窗体上显示的窗体传过去以及透明处理的图片就OK了。限于篇幅下面给绘制函数以及调用示例:


bool DrawAlpha(Image* pBgImg, HWND hWnd)
{
   if (!::IsWindow(hWnd)) return false;

   CWndDecorate wndDecor(hWnd);
   //wndDecor.SetAlpha((255 * 20) / 100);
   //wndDecor.ShowOnDesk();

   RECT rcWnd;
   ::GetWindowRect(hWnd, &rcWnd);
   int nWid = rcWnd.right - rcWnd.left;
   int nHei = rcWnd.bottom - rcWnd.top;

   HDC hdcTemp = ::GetWindowDC(hWnd);
   HDC hdcMemory = ::CreateCompatibleDC(hdcTemp);
   HBITMAP hBitMap = CreateCompatibleBitmap(hdcTemp, nWid, nHei);
   SelectObject(hdcMemory, hBitMap);

   HDC hdcScreen = ::GetWindowDC(hWnd);
   POINT ptWinPos = {rcWnd.left, rcWnd.top};

   Graphics graph(hdcMemory);
   Point points[] = {Point(0, 0),Point(nWid, 0),Point(0, nHei)};
   graph.DrawImage(pBgImg, points,3);

   SIZE sizeWindow={nWid, nHei};
   POINT ptSrc={0,0};

   DWORD dwExStyle = ::GetWindowLong(hWnd, GWL_EXSTYLE);
   if ((dwExStyle & 0x80000!= 0x80000)
   {
    ::SetWindowLong(hWnd, GWL_EXSTYLE, dwExStyle ^ 0x80000);
   }

   CString strTitle;
   m_alWnd.GetWindowText(strTitle);

   Gdiplus::Font   font(L"宋体",12,FontStyleBold,UnitPixel);
   StringFormat   strFormat;
   SolidBrush   brush(Color(0xff,0,0,0));

   graph.DrawString(strTitle, -1, &font, PointF(32,30),&strFormat, &brush);

   ::UpdateLayeredWindow(hWnd, hdcScreen, &ptWinPos, &sizeWindow, hdcMemory, &ptSrc, 0, &m_alBlend, ULW_ALPHA);

   graph.ReleaseHDC(hdcMemory);
   ::ReleaseDC(hWnd,hdcScreen);
   hdcScreen = NULL;
   ::ReleaseDC(hWnd,hdcTemp);
   hdcTemp = NULL;
   DeleteObject(hBitMap);
   DeleteDC(hdcMemory);
   hdcMemory = NULL;

   return true;
}

调用示例:

CWndAlpha<CMainDlg> wndAl;

wndAl.InitAlpha(L"C:\\bg.png", NULL, rcMargin, true);
m_pMainWnd = wndAl.GetMainWnd();
wndAl.DoModal();

很简单吧,就这么几行代码就可以实现背景透明而且又可以随意编辑你自己的子控件了。下面是我生成的示例图,大家欣赏一下了,欢迎留言讨论,如果有需要的请留言!谢谢!

原文转载自:http://rohna.w.blog.163.com/blog/static/145741652009023534832/

抱歉!评论已关闭.