用MFC和Gdi+实现桌面雪花特效

1.最简窗口的建立

2.添加Gdi+支持

这两个我的博客前文都有自己找

在CMainframe类外添加结构如下

struct Snow
{
	
	int x;
	int y;
	int speed;
};

3.在CMainFrame类中添加私有成员

Image* img[2];//两种雪花
	Snow snow[5];//5朵雪花
	RectF rc{ 0,0,1920,1080 };//窗口大小:我的电脑分辨率是1920x1080所以最后两个数设为1920和1080

并在构造函数中初始化

CMainFrame::CMainFrame()
{
	// TODO: 在此添加成员初始化代码
	Create(NULL
		, _T("学习笔记")//窗口标题
		, NULL//窗口风格,我们不在这里设置
		, CRect(0, 0, rc.Width,rc.Height)//窗口大小
		);
	srand(1980);//随机数初始化


	//雪花初始化
	img[0] = Image::FromFile(_T("res/1.jpg"));//图片放在res文件内
	img[1] = Image::FromFile(_T("res/2.jpg"));//图片放在res文件内
	//雪花位置初始化
	for (int i = 0; i < 5; i++)
	{
		
		snow[i].x = rand() % 1920;
		snow[i].y = rand() % 1080;
		snow[i].speed = rand() % 3;
	}
	
}

添加雪花的动作消息DownSnow()

void CMainFrame::DownSnow()
{
	for (int i = 0; i < 5;i++)
	{
		
			snow[i].x += snow[i].speed;
			snow[i].y++;
		
		 if (snow[i].x > rc.Width)
		
			snow[i].x = 0;
			
		
		 if (snow[i].y>1080)
		
		
			snow[i].y = 0;
		
	}

	OnPaint();
	
}

4.在CMainFrame类中添加OnPaint()和WM_TIMER消息函数

void CMainFrame::OnTimer(UINT_PTR nIDEvent)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值
	DownSnow();
	CFrameWnd::OnTimer(nIDEvent);
}

在OnCreate()中设置定时器,此时窗口已创建

SetTimer(0, 10, NULL);
先来看一看DrawImage的一个版本
DrawImage(IN Image* image,
			IN const RectF& destRect,//图片显示位置和大小
			IN REAL srcx,//要显示图片的那一部分(像素),x坐标
			IN REAL srcy,//要显示图片的那一部分(像素),y坐标
			IN REAL srcwidth,//要显示图片的那一部分(像素),长度
			IN REAL srcheight,//要显示图片的那一部分(像素),宽度
			IN Unit srcUnit,//UnitPixel
			IN const ImageAttributes* imageAttributes = NULL,//包含如何操纵位图和图元文件的颜色
			IN DrawImageAbort callback = NULL,
			IN VOID* callbackData = NULL)
再来解释一下一会儿要用到的窗口异形函数
AFX_INLINE BOOL CWnd::UpdateLayeredWindow(CDC* pDCDst, //窗口DC
			POINT *pptDst,//指定分层窗口的屏幕位置
			SIZE *psize,//指定窗口的大小,如果不改变窗口大小,可以为NULL
			CDC* pDCSrc,//缓存DC
			POINT *pptSrc,//内存缓存的左上角坐标(可用于裁剪缓存DC)
			COLORREF crKey,//指向一个COLORREF值(当合成分层窗口时使用指定颜色键值)。要生成COLORREF,使用RGB宏;
			BLENDFUNCTION *pblend,//指向一个BLENDFUNCTION结构(当合成分层窗口时使用指定透明度值)。
			DWORD dwFlags)//ULW_ALPHA 使用pblend为混合功能,如果显示模式为256色或更少,这个值和ULW_OPAQUE效果相同;ULW_COLORKEY 使用crKey值为颜色的透明度;ULW_OPAQUE 绘制一个不透明分层窗口
绘图函数OnPaint()如下
void CMainFrame::OnPaint()
{
	
	CDC* pDC = this->GetDC();//获取窗口DC
	CDC m_dcMemory;//缓冲DC
	CBitmap bmp;//缓冲位图
	bmp.CreateCompatibleBitmap(pDC, rc.Width,rc.Height);//创建位图
	m_dcMemory.CreateCompatibleDC(pDC);//缓冲DC初始化
	CBitmap* pOldBitmap = m_dcMemory.SelectObject(&bmp);//将位图和缓存DC关联
									   //gdi+绘图
	Graphics gh(m_dcMemory.GetSafeHdc());


	ImageAttributes imgAttributes;
	imgAttributes.SetColorKey(Color(255, 255, 254), Color(255, 255, 255));//设置透明颜色的范围


	//绘图代码
	{
		for (int i = 0; i < 5; i++)
		{
			
			
			gh.DrawImage(img[i%2], RectF(snow[i].x, snow[1].y, 100, 100), 0, 0, 1000, 1000, UnitPixel, &imgAttributes);
			
			
				
		}
	}
	
	BLENDFUNCTION _Blend;
	_Blend.BlendOp = 0;
	_Blend.BlendFlags = 0;
	_Blend.SourceConstantAlpha = 255;//范围为0~255,255为全透明
	_Blend.AlphaFormat = 1;


	UpdateLayeredWindow(pDC, &CPoint(0, 0), &CSize(rc.Width, rc.Height),&m_dcMemory, &CPoint(0, 0), 0, &_Blend, ULW_ALPHA);
	pDC->DeleteDC();
}

5,最后一步 改变窗口风格

在PreCreateWindow()函数中

BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
{
	if( !CFrameWnd::PreCreateWindow(cs) )
		return FALSE;
	// TODO: 在此处通过修改
	//  CREATESTRUCT cs 来修改窗口类或样式

	cs.style &= WS_POPUP//三中最基本的窗口之一,重叠(Overlapped),子窗口(child),弹出(popup)
		| WS_VISIBLE
		| WS_SYSMENU
		| WS_MAXIMIZE;
		

	cs.dwExStyle = WS_EX_TOOLWINDOW //不在任务栏显示,不显示在Alt+Tab的切换列表中,不显示在任务管理器中
		| WS_EX_TOPMOST //顶层
		| WS_EX_LAYERED//透明异形
		| WS_EX_TRANSPARENT;//消息穿透
	cs.lpszClass = AfxRegisterWndClass(0);
	return TRUE;
}

大功告成

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值