关闭

MFC实现不规则形状窗口(CF登陆窗口)

8475人阅读 评论(12) 收藏 举报
分类:

1,目标

实现形状不规则的窗口,例如CF登陆窗口。


可以看到,窗口不是死板的矩形,而是带突出带凹陷的不规则形状。(PS:谢霆锋代言CF,还真是霸气测漏啊……)

2,原理

查询CWnd接口,有一个叫SetWindowRgn的方法,可以设置窗口显示的区域。
函数原型 int SetWindowRgn(HRGN hRgn,BOOL bRedraw);
hRgn代表一个区域,这个HRGN结构有一些生成的方法,其中有通过矩形、多边形、椭圆来创建一个HRGN,更奇妙的是可以2个HRGN相加或相减生成一个新的HRGN。所以需要求出不透明区域的HRGN,思路是用Photoshop制作一张与背景图同样大小的双色图片,其中不透明区域设为一种颜色(如白色),透明区域设为黑色,通过遍历像素将白色区域的HRGN全部加和,后得到显示的区域。(或者求出黑色区域,用总区域减掉它)


3,实现

①得到CF登陆界面的截图,如上图。(为了在PS中选中方便,这里最好把桌面背景换成单色)
②用PS将多余部分改成黑色,注意:代码中是以像素RGB值做判断的,这里一定要和代码中做筛选的RGB值相对应,我在PS中用的(0,0,0)的纯黑色。反选,将显示部分改成其他颜色(由于本示例代码是求出黑色部分做减法,所以要显示的部分只要不是黑色就行)如图:其余部分我改成了绿色。
③新建MFC对话框程序,清空对话框上的控件,把对话框的属性中的边框设为无(有标题栏和边框的话,图片显示位置会不对)。导入登陆界面截图和双色图,ID分别设为IDB_BITMAP_CF,IDB_BITMAP_AREA。注意两张图大小一样(应该直接用前一张图制作双色图)。
④给dlg类添加成员函数SetRegion,实现如下:
void CFDlg::SetRegion(CDC* pDC, UINT BackBitmapID, COLORREF TransColor)
{
	CDC dcMem;
	if(!dcMem.CreateCompatibleDC(pDC))
	{
		MessageBox(_T("创建兼容DC失败!"));
	}

	CBitmap bitmap;
	if(!bitmap.LoadBitmap(BackBitmapID))
	{
		MessageBox(_T("加载位图失败!"));
	}

	if(!dcMem.SelectObject(&bitmap))
	{
		MessageBox(_T("选进设备描述表失败!"));
	}

	BITMAP bitmapinfo;
	bitmap.GetBitmap(&bitmapinfo);
	//把窗口设为图片的大小,去掉这个的话,那么程序分割会不正确
	MoveWindow(0,0,bitmapinfo.bmWidth,bitmapinfo.bmHeight,true); 
	//整体区域
	CRgn rgn;
	CRgn tmpRgn;
	rgn.CreateRectRgn(0,0,bitmapinfo.bmWidth,bitmapinfo.bmHeight);
	//从整体区域中剔除所有黑色像素区域
	for(int i=0;i<bitmapinfo.bmWidth;i++)
	{
		for(int j=0;j<bitmapinfo.bmHeight;j++)
		{
			COLORREF cl=dcMem.GetPixel(i,j);
			if(cl== TransColor)
			{
				tmpRgn.CreateRectRgn(i,j,i+1,j+1);
				rgn.CombineRgn(&rgn,&tmpRgn,RGN_XOR);
				tmpRgn.DeleteObject();
			}
		}
	}
	//设置窗口显示区域
	SetWindowRgn(rgn,true);
}

⑤在dlg类OnInitDialog方法中调用SetRegion.
BOOL CFDlg::OnInitDialog()
{
	CDialog::OnInitDialog();

	SetIcon(m_hIcon, TRUE);			// Set big icon
	SetIcon(m_hIcon, FALSE);		// Set small icon

	//根据双色图片设置窗口形状(非黑色区域有效)
	SetRegion(GetDC(),IDB_BITMAP_AREA,RGB(0,0,0));

	//居中
	CenterWindow();

	//播放背景音乐
	sndPlaySound(TEXT("cf_bgm.wav"),SND_ASYNC);

	return TRUE;  // return TRUE  unless you set the focus to a control
}
其中CenterWindow让窗口居中显示,同时用sndPlaySound函数播放了CF的背景音乐cf_bgm.wav,这是从游戏安装文件夹中找的。我转换过格式并重命名了。要使用这个音乐API,得加入如下lib:
#include "mmsystem.h"
#pragma comment(lib,"winmm.lib")
⑥现在窗口形状达到要求了,但是还没有背景图,在OnPaint中else分支中修改为如下,要去掉CDialog::OnPaint();
void CFDlg::OnPaint()
{
	if (IsIconic())
	{
		CPaintDC dc(this); // device context for painting

		SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);

		// Center icon in client rectangle
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// Draw the icon
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CPaintDC  dc(this);   
		CRect  rect;   
		GetWindowRect(&rect);   
		CDC  dcMem;   
		dcMem.CreateCompatibleDC(&dc);   
		CBitmap  bmpBackground;   
		bmpBackground.LoadBitmap(IDB_BITMAP_CF);  //背景图
		BITMAP  bitmap;   
		bmpBackground.GetBitmap(&bitmap);   
		CBitmap  *pbmpOld=dcMem.SelectObject(&bmpBackground); 
		dc.StretchBlt(0,0,rect.Width(),rect.Height(),&dcMem,0,0,bitmap.bmWidth,bitmap.bmHeight,SRCCOPY);
	}
}

这是绘制我们那张背景图,其中边缘外的部分由于窗口大小关系被截掉,所以看不到了。

4,效果


边缘有点毛边,这个得靠PS处理的仔细程度了,我只是用魔棒工具简单的选择了下范围。


5,源码

附本文VC6+vs2008 MFC工程源码下载:




2
0
查看评论

MFC界面编程1:GDI+实现不规则窗体

先来看一下实现的效果,下图中那个娃娃就是我们要实现的不规则窗体啦~ 1. GDI+配置及初始化(VS2013)VS2013上已经有了GDI+支持,不用单独下载安装包了。现在只需项目中引入gdiplus.lib和加入头文件即可。 为了在全工程使用GDI+,在stdafx.h中加入:#include...
  • elaine_bao
  • elaine_bao
  • 2016-06-04 23:04
  • 2216

实现不规则窗体------基于MFC based DLG

实现界面如下所示:(文末有源码下载地址,初写技术博客,写的不好还请大家多多批评指正) 实现过程: 1、首先创建基于DLG的MFC应用程序,命名为:tryBGDlg,并将DLG的属性设置为:Title Bar :False ,其它设置不变 2、制作两幅图像,其中的一幅黑白图像,是...
  • harvic880925
  • harvic880925
  • 2012-09-11 12:10
  • 2467

MFC实现不规则形状窗口

  • 2017-02-20 17:46
  • 1.52MB
  • 下载

MFC实现不规则形状窗口

转载来自:http://blog.csdn.net/dpsying/article/details/17126761 http://www.jb51.net/article/66694.htm void CFDlg::SetRegion(CDC* pDC, U...
  • songyimin1208
  • songyimin1208
  • 2017-03-06 11:47
  • 604

mfc 不规则对话框

BitmapDialog.h :#if !defined(AFX_BITMAPDIALOG_H__A76F9E74_DF43_11D4_AE27_4854E828E6FD__INCLUDED_)#define AFX_BITMAPDIALOG_H__A76F9E74_DF43_11D4_AE27_4...
  • dragoo1
  • dragoo1
  • 2017-01-17 21:31
  • 185

MFC不规则对话框

  • 2011-12-15 14:52
  • 7.88MB
  • 下载

VC++玩转炫酷悬浮窗2---不规则窗体的实现(常规)

目标不规则窗体也称为异型窗体,像迅雷的飞鸟型窗体就是啦。这篇文章就是要实现这样的窗体。计划&方案根据上一篇文章继续扩展。我们有几种方案实现不规则窗体。迅雷就是用一张图片作为窗体的形状,那么图片的类型我们也要考虑进来。现在是png图片的天下,自带背景透明;对于bmp图片,需要程序处理一下。对于...
  • lincyang
  • lincyang
  • 2014-08-22 10:47
  • 4010

VC++玩转炫酷悬浮窗3---GDI+完美实现不规则窗体

目标上一篇不规则窗体虽然实现了,但是图形有锯齿,给人以上世纪的老古董感觉,跟酷炫不搭边。今天就要用高级一些的技术做出完美的光滑的无锯齿的不规则窗体。计划&方案PNG图片本身就是带透明效果的,把此图片作为窗体,用GDI+将其实现。那么什么是GDI+呢?先要说一说GDI, Graphics De...
  • lincyang
  • lincyang
  • 2014-09-05 11:09
  • 7120

MFC 不规则窗口 SetWindowRgn

有时候,我们需要使用到不规则窗口,比如一个圆形的对话框,或者一个三角形的对话框,这个时候,我们就可以通过使用SetWindowRgn来设置对话框的形状。 其实,当我们不设置窗口形状的时候,windows默认设置窗口形状为矩形了。 可以再OnInlitDialog中添加下列代码: CRgn rg...
  • zengweicdut
  • zengweicdut
  • 2013-04-18 17:15
  • 1322

用PNG透明图片和GDI+做不规则透明窗体"异形窗口"

一、准备工作(PNG图片透空窗体) 1、图片资源准备工作。首先在Photoshop中编辑所用图片,将这些图片保存成为带透明通道的.png格式(GDI+调用显示时能够透明调背景)。这样程序中图片资源就准备好了。 2、下面开始做好展开此项工作的基本准备工作。 创建一个对话框应用程序,名称为Gdi+...
  • jackfengwei
  • jackfengwei
  • 2013-08-08 13:22
  • 2377
    个人资料
    • 访问:348063次
    • 积分:3395
    • 等级:
    • 排名:第11751名
    • 原创:79篇
    • 转载:41篇
    • 译文:0篇
    • 评论:47条
    博客专栏
    文章分类
    最新评论