实现形状不规则的窗口,例如CF登陆窗口。
可以看到,窗口不是死板的矩形,而是带突出带凹陷的不规则形状。(PS:谢霆锋代言CF,还真是霸气测漏啊……)
查询CWnd接口,有一个叫SetWindowRgn的方法,可以设置窗口显示的区域。
函数原型 int SetWindowRgn(HRGN hRgn,BOOL bRedraw);
hRgn代表一个区域,这个HRGN结构有一些生成的方法,其中有通过矩形、多边形、椭圆来创建一个HRGN,更奇妙的是可以2个HRGN相加或相减生成一个新的HRGN。所以需要求出不透明区域的HRGN,思路是用Photoshop制作一张与背景图同样大小的双色图片,其中不透明区域设为一种颜色(如白色),透明区域设为黑色,通过遍历像素将白色区域的HRGN全部加和,后得到显示的区域。(或者求出黑色区域,用总区域减掉它)
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); }
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); } }