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;
}
大功告成