透明窗体的又一实现
作者:段会锋
下载源代码
前面拜读过本站无数高手的许多好文章,受益非浅,首先向各位大侠致敬!今天编程偶有小得,不敢独享,特拿出来与各位共享,希望对某些朋友有些许帮助。
透明窗体的问题相信大家已经很熟悉了,前面的几期在线杂志也有几篇详尽的教程,总结一下就是通过SetWindowRgn这个函数来实现,具体的裁切框用CRgn来生成,比较简单的 象圆,椭圆,圆角窗口等CRgn类都提供了相应的生成方法,我们如果想根据自己的图片来生成裁切框前面的朋友提到的方法是首先生成一个矩形裁切框,然后扫描图片,根据象素点的颜色与掩码颜色的匹配与否,对裁切框进行删减(生成一个新的,然后XOR),对于这种方法我就不详细描述了,有需要的朋友请查阅以前的文章,我首先说一下我遇到的不足之处:
如果我的窗体支持Resize,那么我调整大小的过程中,要不停的计算裁切框(要逐点扫描象素,并对裁切框进行操作),计算量相当大,特别当窗体比较大的时候更是如此,会造成窗体的闪烁。
我查阅相关资料得到另一种实现方法,简单实用,那就是利用 SetLayeredWindowAttributes 这个函数,相信许多朋友都见过Microsoft对他的描述但用过的并不多,要用它,要安装最新的SDK,否则会出现没有定义的错误。小弟懒得下载,下面的介绍采用了一般API调用的格式。如果你已经有最新的SDK,那你的程序可以变得更加简练!
首先介绍一下这个函数:
BOOL SetLayeredWindowAttributes(HWND hwnd, // 应用目标窗口的句柄COLORREF crKey, // 掩码的颜色,可以用RGB(r,g,b)来指定BYTE bAlpha, // 掩码颜色部分的Alpha值,0是全透明,255是完全不透明DWORD dwFlags // 透明方式);要说名的是这个函数只在Windows2000及以上版本才支持。MSDN对要求的描述如下
<Requirements>Windows NT/2000/XP: Included in Windows 2000 and later.Windows 95/98/Me: Unsupported.Header: Declared in Winuser.h; include Windows.h.Library: Use User32.lib.还有就是这个函数对于有标题框的窗体支持不好,就是它裁切的只是客户区域,好在我们要制作透明窗体的场合一般用不到标题框下面就说名例程的制作过程。(我旨在说明这种透明窗体的思路及函数的用法,所以代码非常简单,并且没有必要的错误验证机制,希望大家谅解)建立一张用于在窗体上绘制的背景图片,把要裁切的部分用一种颜色标记出来,我们叫它MaskColor,我的图片如下:
我的MaskColor = 0xFF00,也就是 RGB(0,255,0).建立一个基于对话框的工程,修改对话框资源的属性,主要修改两个地方。一是指定没有TitleBar,二是指定BorderStyle为None.这样才能保证出来的窗体符合你的要求把图片加入资源,付ID = IDB_BACKGROUND下面就开始写代码了,呵呵,看下面的代码这么长。是不是头有点大呀,别急,这些多半都是工程向导自动生成的,我加的都已经注解上了,并用黄色表示没有几行的。要不然我怎么敢向各位吹嘘这个实现方法简单呢。a.首先我们给窗体添加两个成员变量:
CBitmap * m_oldBitmap; //指向内存DC原来的 Bitmap CDC m_DC; //用于存放背景图片的内存DCb.在窗体的OnInitDialog()函数中做一番初始化:
BOOL CTransWindowDlg::OnInitDialog(){CDialog::OnInitDialog();// 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动// 执行此操作SetIcon(m_hIcon, TRUE); // 设置大图标SetIcon(m_hIcon, FALSE); // 设置小图标/////////////////////////////////////////段会锋添加的代码//实现背景图以及窗口透明//调用背景图片CBitmap bitmap;BITMAP bitInfo;bitmap.LoadBitmap(IDB_BACKGROUND);//得到图片大小并调整窗口大小适应图片bitmap.GetBitmap(&bitInfo);CRect rect;GetWindowRect(&rect);rect.right = rect.left + bitInfo.bmWidth;rect.bottom = rect.top + bitInfo.bmHeight;MoveWindow(rect);//创建并保存DCm_DC.CreateCompatibleDC(GetDC());m_oldBitmap = m_DC.SelectObject(&bitmap);//设置窗口掩码颜色和模式//首先获得掩码颜色COLORREF maskColor = m_DC.GetPixel(0,0);#define LWA_COLORKEY 0x00000001#define WS_EX_LAYERED 0x00080000typedef BOOL (WINAPI *lpfnSetLayeredWindowAttributes)(HWND hWnd, COLORREF crKey, BYTE bAlpha, DWORD dwFlags);lpfnSetLayeredWindowAttributes SetLayeredWindowAttributes;HMODULE hUser32 = GetModuleHandle("user32.dll");SetLayeredWindowAttributes = (lpf