在网上关于窗口视觉效果,有2个问题被问得最多:
第一个是如何让窗口边框有阴影效果?
第二个是如何让窗口控件有半透明效果?

对于第一个问题,我们的答案是用双层窗口模拟或是用Layered Window。
在XP下可以直接在注册窗口类时用CS_DROPSHADOW风格,系统就会自动让你的窗口附加上阴影效果,实际上系统也是通过双层窗口来实现的;当然我们也可以用自己的窗口来模拟阴影效果,只要让阴影窗口永远跟随我们的目标窗口就可以了。
如果用Layered Window, 我们只要一个窗口,通过让窗口支持Alpha通道,最后UpdateLayeredWindow, 即可实现阴影效果。

对于第二个问题,我们通常的答案是用双层窗体或是DirectUI。
因为Windows绘画是以DC为单位,而主窗口和内部控件是居于不同的DC, 所以他们不能半透明融合在一起。
另外只有Pop up的窗口才能支持Layered Window,所以只有Pop up的窗口才能实现半透明效果,所以我们通常用双层窗口来模拟控件的半透明,也就是说窗口上面的控件其实是通过一个Pop up窗口模拟出来的。所以用这种方式实现控件的半透明效果,性能比较差,也只能实现一些简单的界面。
还有一种控件半透明的方式是用DirectUI,所有的窗口控件都通过在主窗口上绘画模拟出来,实现半透明效果自然也很容易了。

所以既要实现窗口的阴影效果,又要让内部控件半透明,最终极的方式还是用WS_EX_LAYERED风格的DirectUI窗口。

其实另外还有一种既不用DirectUI,也不用双层窗口,也能实现控件半透明的方法。
该方法的关键是控件在Paint自己时,首先向主窗口询问,获取主窗口上控件所在区域的背景图,然后控件先将此背景画到自己的DC上,然后在再画自己,这样可以让控件看起来像是直接画在主窗口上一样。
当然该方法也只能针对一些简单的UI,如果子窗口层次很多,或是控件个数很多,都会有性能影响。

核心代码如下:

HBRUSH AtlGetBackgroundBrush(HWND hWnd, HWND hwndParent)
{
   CWindow wnd = hWnd;
   CWindow wndParent = hwndParent;
   CClientDC dcParent = wndParent;
   CRect rcParent;
   wndParent.GetWindowRect(&rcParent);
   CDC dcCompat1;
   dcCompat1.CreateCompatibleDC(dcParent);
   CBitmap bmpCompat1;
   bmpCompat1.CreateCompatibleBitmap(dcParent, rcParent.Width(), rcParent.Height());
   HBITMAP hOldBmp1 = dcCompat1.SelectBitmap(bmpCompat1);
   wndParent.SendMessage(WM_PRINTCLIENT, (WPARAM) (HDC) dcCompat1, (LPARAM)(PRF_ERASEBKGND | PRF_CLIENT | PRF_NONCLIENT));
   CRect rcWin;
   wnd.GetWindowRect(&rcWin);
   CDC dcCompat2;
   dcCompat2.CreateCompatibleDC();
   CBitmap bmpCompat2;
   bmpCompat2.CreateCompatibleBitmap(dcCompat1, rcWin.Width(), rcWin.Height());
   HBITMAP hOldBmp2 = dcCompat2.SelectBitmap(bmpCompat2);
   CRect rcSnap = rcWin;
   ::MapWindowPoints(NULL, wndParent, (LPPOINT) (LPRECT) &rcSnap, 2);
   dcCompat2.BitBlt(0, 0, rcWin.Width(), rcWin.Height(), dcCompat1, rcSnap.left, rcSnap.top, SRCCOPY);
   HBRUSH hBrush = ::CreatePatternBrush(bmpCompat2);
   dcCompat1.SelectBitmap(hOldBmp1);
   dcCompat2.SelectBitmap(hOldBmp2);
   return hBrush;
}

下面是一个简单的Demo:

Demo源代码: TransparentControl Demo

注:Demo上的文字因为是直接用GDI画的,所以没有支持Alpha通道

http://www.cppblog.com/weiym/archive/2012/08/23/187998.html

如何让窗口控件半透明(控件在Paint自己时,首先向主窗口询问,获取主窗口上控件所在区域的背景图)的更多相关文章

  1. jquery 获取父窗口的元素、父窗口、子窗口

    一.获取父窗口元素: $("#父窗口元素ID",window.parent.document):对应javascript版本为window.parent.document.getE ...

  2. 获取父窗口元素或者获取iframe中的元素(相同域名下)

    jquery方法 在父窗口中获取iframe中的元素 //方法1 $("#iframe的ID").contents().find("iframe中的元素"); ...

  3. Atitit.获取swing ui 按钮控件的id 与名字 与JPDA 调试体系

    Atitit.获取swing ui 按钮控件的id 与名字 与JPDA 调试体系 1. Swing Inspector是一个Java Swing/AWT用户界面分析和调试工具,功能与firebug类似 ...

  4. C#之菜单控件、主窗体打开子窗体、GroupBox控件使用

    一.背景 一年前有学习过C#,但没有在项目中去实际做APP,重新捡起来应用到项目中.我同事本来做好一个CANOPEN设备管理的界面,由于近期搜索了别人的开发的界面,我觉得有很多东西要重新安排,以及我已 ...

  5. 扩展BindingList,防止增加、删除项时自动更新界面而不出现“跨线程操作界面控件 corss thread operation”异常

    在做界面程序时,常常需要一些数据类,界面元素通过绑定等方式显示出数据,然而由于UI线程不是线程安全的,一般都需要通过Invoke等方式来调用界面控件.但对于数据绑定bindingList而言,没法响应 ...

  6. javascript获取asp.net服务器端控件的值

    代码如下: <%@ Page Language="C#" CodeFile="A.aspx.cs" Inherits="OrderManage_ ...

  7. Winform 获取当前单击的控件名称 和 向窗体添加控件

    Winform如何获取当前单击的控件名称,比如有100个Button 和一个button_Click()的按钮事件 ,分别点击不同按钮后显示所点击的按钮名称?private void button_C ...

  8. 如何获取Iframe的页面控件的值

    有时候我们在页面需要使用iframe的方法来引用另一个页面,虽然个人建议不要使用iframe哈,但是有些时候是没得法了才使用的咯,那么在使用的过程中也会遇到某一些问题,我将自己遇到的问题记录下来方便以 ...

  9. MFC获取光标相对于控件所在行

    获取光标在控件上所在的行数 /*editControl为Edit Control的变量*/ CPoint point = editControl.GetCaretPos(); //获取光标相对于控件的 ...

随机推荐

  1. Python学习之四【变量】

    变量:用于引用(绑定)对象的标识符 语法: >>变量名=对象 (数值,表达式等) 如计算圆的面积 PI=3.14 redius:12.3 area=PI*radius**2(**在pyth ...

  2. HTML中常见的各种位置距离以及dom中的坐标讨论

    最近在学习JavaScript,特意买了一本犀牛角书来看看,尼玛一千多页,看的我头昏脑涨,翻到DOM这章节,突然记起平常在使用DOM时,碰到了好多的这个dom里面的各种宽度,高度,特意在此写一写,写的 ...

  3. c++回调编程本质

    1. boost:bind获得一个函数对象,就像函数指针一样,这个行为可以作为回调 2. bosot:bind的函数对象可以保存别的对象的引用,回调对象的成员函数 3. boost:function是 ...

  4. centos6.3 配置NTP服务

    NTP简介: NTP(Network Time Protocol)是用来使计算机时间同步化的一种协议,它可以使计算机对其服务器或时钟源做同步化,它可以提供高精准度的时间校正.本例讲解如何在CentOS ...

  5. Android客户端与服务端交互之登陆示例

    Android客户端与服务端交互之登陆示例 今天了解了一下android客户端与服务端是怎样交互的,发现其实跟web有点类似吧,然后网上找了大神的登陆示例,是基于IntentService的 1.后台 ...

  6. Web api 文档以及测试工具配置

    第一步: 创建web api 在nuget 上搜索 webapitestclient (包含预发行版) 然后在 /Areas/HelpPage/Views/Help/Api.cshtml 末尾 添加 ...

  7. dede当前位置各种写法

    方法一.Dedecms当前位置{dede:field name='position'/} 方法二.dede:field name='position' runphp='yes'}          $ ...

  8. js异步的理解---千呼万唤始出来啊!

    编译完成后(先分配给变量空间和function(){}命名的函数,var = function(){}这种函数也仅仅只是分配了个空间,还没有赋值个函数给他!),调用了若不是undefined就执行, ...

  9. MemCache缓存和C#自带的Cache缓存

    1.MemCache: //初始化 static SockIOPool _pool; // 创建Memcached private static MemcachedClient Create(stri ...

  10. STL中的set容器

    #include <iostream> #include <set> using namespace std; int main() { set<int> s; s ...