VC创建自定义不规则窗口

最近工作比较闲,可以写点技术文章了。鄙人不才,可能会有所疏漏,只希望可以起到抛砖引入的作用。

前面写过一篇用透明Png图片来创建不规则窗体的文章,本文则主要讲述通过代码来在自定义透明。(有的时候需要在窗口的某些位置打个洞,我以前做过这样的需求,哈哈。)

透明窗口当然需要给窗口加上WS_EX_LAYERED样式,在绘制时调用UpdateLayeredWindow来贴图,源DC中所有像素点中alpha值为0则全透了。(补充下,每个像素点占4个字节,分别是:A (透明度alpha)R G B(三原色),在内存中存储时是反的:B G R A)我们要制定某块区域透明,就需要在贴图前,设置区域内像素的alpha值为0(全透),也可以为其他值(部分透明)……设置前,需要用CreateDIBSection获取DC中背景位图的像素值到指定的buffer中,燃火我们遍历这个buffer就可以设置了。

主要看WM_PAINT消息的处理部分代码:

	case WM_PAINT:
		{
			hdc = BeginPaint(hWnd, &ps);
			// TODO: 在此添加任意绘图代码...
			RECT rcClient;
			GetClientRect(g_hWnd, &rcClient);
			int nWidth=rcClient.right-rcClient.left;
			int nHeight=rcClient.bottom-rcClient.top;
			if ( NULL == g_hMemDC )
			{
				g_hMemDC=CreateCompatibleDC(hdc);
				//g_hBitmap=LoadBitmap(hInst, MAKEINTRESOURCE(IDB_BITMAP1));
				g_hBitmap=CreateCompatibleBitmap(hdc, nWidth, nHeight);
				SelectObject(g_hMemDC, g_hBitmap);
				BITMAPINFO bi;
				ZeroMemory(&bi, sizeof(BITMAPINFO));
				bi.bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
				bi.bmiHeader.biWidth=nWidth;
				bi.bmiHeader.biHeight=nHeight;
				bi.bmiHeader.biPlanes=1;
				bi.bmiHeader.biBitCount=32;
				bi.bmiHeader.biCompression=BI_RGB;
				bi.bmiHeader.biSizeImage=nWidth*nHeight*4;
				BYTE* lpData=NULL;
				HRGN hRgn=CreateRoundRectRgn(0, 0, 100, 100, 100, 100);
				g_hBitmap=CreateDIBSection(g_hMemDC, &bi, DIB_RGB_COLORS, (void**)&lpData, NULL, 0);
				for (int i=0; i<nHeight; ++i)
					for (int j=0; j<nWidth; ++j)
					{
						int nPos=( (nHeight-i-1)*nWidth+j)*4;
						//lpData[nPos+0]=0xff;
						//lpData[nPos+3]=0x00;
						if ( !PtInRegion(hRgn, j, i) )
							lpData[nPos+3]=0x0f;
						else
						{
							lpData[nPos+0]=0xff;
							lpData[nPos+3]=0x00;
						}

					}
				DeleteObject(hRgn);
				SelectObject(g_hMemDC, g_hBitmap);
			}
			POINT pt={300, 300};
			POINT pt1={0, 0};
			SIZE size={300, 300};
			BLENDFUNCTION bf;
			ZeroMemory(&bf, sizeof(bf));
			bf.SourceConstantAlpha=255;
			bf.AlphaFormat=AC_SRC_ALPHA;
			LONG lStyle=GetWindowLong(hWnd, GWL_EXSTYLE);
			SetWindowLong(hWnd, GWL_EXSTYLE, lStyle|WS_EX_LAYERED);
// 			RECT rc={0, 0, 50, 50};
// 			::SetBkColor(g_hMemDC, 0xffffff);
// 			::ExtTextOut(g_hMemDC, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
			UpdateLayeredWindow(hWnd, hdc, &pt, &size, g_hMemDC, &pt1, 0, &bf, ULW_ALPHA);
			EndPaint(hWnd, &ps);
			break;
		}
PtInRegion是来判断这个点是否在你要穿透的区域
这里只是一个很简单的小例,读者可以自行扩展。打算上传代码的,不过CSDN上传的步骤实在是太麻烦了!


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值