A-A+

VS中不规则窗体的创建

2015年07月05日 C/C++ 阅读 1,532 views 次

1、基本思路

逐个扫描图片的每个像素,如这个像素不属于定义的透明色,则在相应位置创建一个只含一个像素的region,然后将这些小region合并起来组成一个任意形状的region。

2、图片资源处理

将背景图片中不需要显示的部分涂上一种单一的颜色,此颜色不要与需要显示的部分有相同色。本例中将不需要显示的部分涂为白色。将图片资源加入到工程中,并设置其ID。本例中设为IDB_BACKGROUND。

7db1246077bde7bfea02ccbd707ee165

3、主实现程序(来源于网络)

主实现程序如下:

//CDC *pDC, //窗体的DC指针
//CBitmap &cBitmap, //含有窗体形状的位图对象
//COLORREF TransColor //透明色
void SetupRegionCDC(CDC * pDC, CBitmap & cBitmap, COLORREF TransColor)
{
//本函数只调用一次即可
static int nExit=1;
if (nExit>1)
{
return;
}
nExit++;

 CDC memDC;//创建与传入DC兼容的临时DC
memDC.CreateCompatibleDC(pDC);
CBitmap *pOldMemBmp = NULL;//将位图选入临时DC
pOldMemBmp = memDC.SelectObject(&cBitmap);

 static CRgn wndRgn;//创建总的窗体区域,初始region为0
wndRgn.CreateRectRgn(0, 0, 0, 0);

 BITMAP bit;
cBitmap.GetBitmap (&bit);//取得位图参数,这里要用到位图的长和宽

 //逐个扫描图片的每个像素,如这个像素不属于透明色,
//则在相应位置创建一个只含一个像素的region,然后将这些小region
//合并起来组成一个任意形状的region
int y;
CRgn rgnTemp; //保存临时region
for(y = 0; y <= bit.bmHeight ; y++)
{
int iX = 0;
do
{
//在图片的第y行寻找第一个非透明色的点
while (iX <= bit.bmWidth && memDC.GetPixel(iX, y) == TransColor)
iX++;
int iLeftX = iX;//记住这个起始点

    //在图片的第y行寻找第一个透明色的点
while (iX <= bit.bmWidth && memDC.GetPixel(iX, y) != TransColor)
++iX;

    //创建一个包含起点与终点间高为1像素的临时“region”
rgnTemp.CreateRectRgn(iLeftX, y, iX, y + 1);

    //合并到主"region".
wndRgn.CombineRgn(&wndRgn, &rgnTemp, RGN_OR);

    //删除临时"region",否则下次创建时会出错
rgnTemp.DeleteObject();
}
while(iX<= bit.bmWidth); 
}

    this->SetWindowRgn(wndRgn, TRUE);
memDC.DeleteDC();
}

4、处理WM_ERASEBKGND消息

添加WM_ERASEBKGND消息,并在消息中做如下处理:

(1)去除标题和边框

SetWindowLong(m_hWnd, GWL_STYLE,GetWindowLong(m_hWnd, GWL_STYLE) & (~(WS_CAPTION | WS_BORDER)));

(2)窗口贴图

 CDC memDC;
memDC.CreateCompatibleDC(pDC);
BITMAP bmp;
CBitmap bkImg;
bkImg.LoadBitmap(IDB_BACKGROUND);
bkImg.GetBitmap(&bmp);
memDC.SelectObject(&bkImg);

(3)设置窗口大小

 SetWindowPos(NULL, 0, 0, bmp.bmWidth, bmp.bmHeight, SWP_NOMOVE|SWP_NOZORDER);
CRect rect;
GetClientRect(&rect);
pDC->StretchBlt(0, 0,bmp.bmWidth, bmp.bmHeight, &memDC, 0, 0, bmp.bmWidth, bmp.bmHeight,SRCCOPY);
memDC.DeleteDC();

(4)设置窗口透明

 SetWindowLong(AfxGetMainWnd()->m_hWnd,GWL_EXSTYLE,
GetWindowLong(AfxGetMainWnd()->m_hWnd,GWL_EXSTYLE) | 0x80000);
HINSTANCE hInst=LoadLibrary(_T("User32.DLL"));   
if(hInst)   
{   
typedef BOOL     (WINAPI * MYFUNC)(HWND,COLORREF,BYTE,DWORD);   
MYFUNC fun=NULL;

  //取得SetLayeredWindowAttributes函数指针   
fun=(MYFUNC)GetProcAddress(hInst,"SetLayeredWindowAttributes");   
if(fun)   
fun(AfxGetMainWnd()->m_hWnd,RGB(0,0,0),0,1);   
FreeLibrary(hInst);   
}

(5)调用主程序,实现不规则窗体

 static CBitmap m_Bmp;
m_Bmp.LoadBitmap(IDB_BACKGROUND);
static COLORREF cr;
cr=RGB(0,0,0);
SetupRegionCDC(pDC,m_Bmp,cr);
return TRUE;

5、移动窗口时不出现边框

若要移动窗口时不出现边框,需处理WM_NCHITTEST消息。在此消息中做如下处理:

//禁止显示移动矩形窗体框
::SystemParametersInfo(SPI_SETDRAGFULLWINDOWS,TRUE,NULL,0);
CRect rect;
GetClientRect(&rect);
ClientToScreen(&rect);
return rect.PtInRect(point) ? HTCAPTION : CDialog::OnNcHitTest(point);

6、不规则窗口效果

f1b8d231dbaf81470a72a5bb10768db5

个人公众号“数字化设计CAX联盟”,欢迎关注,共同交流
为您推荐:

给我留言

© 坐倚北风 版权所有 严禁镜像复制 苏ICP备15034888号. 基于 Ality 主题定制 AliCMS
联系邮箱:leanwind@163.con,微信公众号:数字化设计CAX联盟

用户登录

分享到: