Win32实现阴影窗口

25 篇文章 1 订阅
8 篇文章 0 订阅
#include <windows.h>
#include <math.h>

#pragma comment(lib,"Msimg32.lib")

LRESULT CALLBACK WindowProc(HWND hwnd,
	UINT uMsg,
	WPARAM wParam,
	LPARAM lParam
	);

LRESULT CALLBACK ForegroundWndProc(HWND hwnd,
	UINT uMsg,
	WPARAM wParam,
	LPARAM lParam
	);

void pre_multiply(void* pdata, int w, int h)
{
	unsigned char* pBmpData = (unsigned char*)pdata;
	int perLineByts = 4 * w;
	for (int y = 0; y < h; y++)
	{
		for (int x = 0; x < perLineByts; x += 4)
		{
			//即内存高地址存放数据的高位
			double a = pBmpData[x + y * perLineByts + 3] / 255.0;
			pBmpData[x + y * perLineByts] *= a;//B
			pBmpData[x + y * perLineByts + 1] *= a;//G
			pBmpData[x + y * perLineByts + 2] *= a;//R
		}
	}
}

void shadow(HWND hwnd,int w,int h)
{
#define ShadowWidth 20
#define MaxOpaque	80

	BITMAPINFO bmi;
	ZeroMemory(&bmi, sizeof(BITMAPINFO));

	// setup bitmap info 
	// set the bitmap width and height to 60% of the width and height of each of the three horizontal areas. Later on, the blending will occur in the center of each of the three areas.
	bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
	bmi.bmiHeader.biWidth = w;
	bmi.bmiHeader.biHeight = h;
	bmi.bmiHeader.biPlanes = 1;
	bmi.bmiHeader.biBitCount = 32;         // four 8-bit components
	bmi.bmiHeader.biCompression = BI_RGB;
	bmi.bmiHeader.biSizeImage = bmi.bmiHeader.biWidth * bmi.bmiHeader.biHeight * 4;

	// create our DIB section and select the bitmap into the dc


	VOID *pvBits;
	HDC hdc = GetDC(hwnd);
	HDC hdcMem = CreateCompatibleDC(hdc);
	HBITMAP hBmp = CreateDIBSection(hdcMem, &bmi, DIB_RGB_COLORS, &pvBits, NULL, 0x0);
	ReleaseDC(hwnd, hdc);
	SelectObject(hdcMem, hBmp);

	unsigned char grayLevel = 0;
	int spaceWidth = bmi.bmiHeader.biWidth - 2 * ShadowWidth;
	for (int y = 0; y < bmi.bmiHeader.biHeight; y++)
	{
		for (int x = 0; x < bmi.bmiHeader.biWidth; x++)
		{
			if (x < ShadowWidth && y >= ShadowWidth && y <= bmi.bmiHeader.biHeight - ShadowWidth)
			{
				unsigned char alpha;
				//alpha = 50 * (double)x / bmi.bmiHeader.biWidth;//线性渐变
				alpha = x*x * MaxOpaque / (ShadowWidth*ShadowWidth);//二次函数
				((UINT32*)pvBits)[x + y * bmi.bmiHeader.biWidth] = (alpha << 24) | (grayLevel << 16) | (grayLevel << 8) | grayLevel;
			}
			else if (x>bmi.bmiHeader.biWidth - ShadowWidth && y >= ShadowWidth && y <= bmi.bmiHeader.biHeight - ShadowWidth)
			{
				unsigned char alpha;
				//alpha = 50 * (double)x / bmi.bmiHeader.biWidth;//线性渐变
				alpha = (bmi.bmiHeader.biWidth - x)*(bmi.bmiHeader.biWidth - x) * MaxOpaque / (ShadowWidth*ShadowWidth);//二次函数
				((UINT32*)pvBits)[x + y * bmi.bmiHeader.biWidth] = (alpha << 24) | (grayLevel << 16) | (grayLevel << 8) | grayLevel;
			}
			else if (x >= ShadowWidth && x <= bmi.bmiHeader.biWidth - ShadowWidth && y<ShadowWidth)
			{
				unsigned char alpha;
				//alpha = 50 * (double)x / bmi.bmiHeader.biWidth;//线性渐变
				alpha = y*y * MaxOpaque / (ShadowWidth*ShadowWidth);//二次函数
				((UINT32*)pvBits)[x + y * bmi.bmiHeader.biWidth] = (alpha << 24) | (grayLevel << 16) | (grayLevel << 8) | grayLevel;
			}
			else if (x >= ShadowWidth && x <= bmi.bmiHeader.biWidth - ShadowWidth && y > bmi.bmiHeader.biHeight - ShadowWidth)
			{
				unsigned char alpha;
				//alpha = 50 * (double)x / bmi.bmiHeader.biWidth;//线性渐变
				alpha = (bmi.bmiHeader.biHeight - y)*(bmi.bmiHeader.biHeight - y) * MaxOpaque / (ShadowWidth*ShadowWidth);//二次函数
				((UINT32*)pvBits)[x + y * bmi.bmiHeader.biWidth] = (alpha << 24) | (grayLevel << 16) | (grayLevel << 8) | grayLevel;
			}

			//四个角落
			else if (x < ShadowWidth && y < ShadowWidth)
			{
				int r = sqrt((double)(x - ShadowWidth)*(x - ShadowWidth) + (y - ShadowWidth)*(y - ShadowWidth));
				if (r>ShadowWidth)
					((UINT32*)pvBits)[x + y * bmi.bmiHeader.biWidth] = 0x00ffffff;//ARGB,A=0表示透明,A=255表示不透明
				else
				{
					unsigned char alpha;
					//alpha = 50 * (double)x / bmi.bmiHeader.biWidth;//线性渐变
					alpha = (ShadowWidth - r)*(ShadowWidth - r) * MaxOpaque / (ShadowWidth*ShadowWidth);//二次函数
					((UINT32*)pvBits)[x + y * bmi.bmiHeader.biWidth] = (alpha << 24) | (grayLevel << 16) | (grayLevel << 8) | grayLevel;
				}
			}
			else if (x > bmi.bmiHeader.biWidth - ShadowWidth && y < ShadowWidth)
			{
				int r = sqrt((double)(x - bmi.bmiHeader.biWidth + ShadowWidth)*(x - bmi.bmiHeader.biWidth + ShadowWidth) + (y - ShadowWidth)*(y - ShadowWidth));
				if (r>ShadowWidth)
					((UINT32*)pvBits)[x + y * bmi.bmiHeader.biWidth] = 0x00ffffff;//ARGB,A=0表示透明,A=255表示不透明
				else
				{
					unsigned char alpha;
					//alpha = 50 * (double)x / bmi.bmiHeader.biWidth;//线性渐变
					alpha = (ShadowWidth - r)*(ShadowWidth - r) * MaxOpaque / (ShadowWidth*ShadowWidth);//二次函数
					((UINT32*)pvBits)[x + y * bmi.bmiHeader.biWidth] = (alpha << 24) | (grayLevel << 16) | (grayLevel << 8) | grayLevel;
				}
			}
			else if (x > bmi.bmiHeader.biWidth - ShadowWidth && y >bmi.bmiHeader.biHeight - ShadowWidth)
			{
				int r = sqrt((double)(x - bmi.bmiHeader.biWidth + ShadowWidth)*(x - bmi.bmiHeader.biWidth + ShadowWidth) +
					(y - bmi.bmiHeader.biHeight + ShadowWidth)*(y - bmi.bmiHeader.biHeight + ShadowWidth));
				if (r > ShadowWidth)
					((UINT32*)pvBits)[x + y * bmi.bmiHeader.biWidth] = 0x00ffffff;//ARGB,A=0表示透明,A=255表示不透明
				else
				{
					unsigned char alpha;
					//alpha = 50 * (double)x / bmi.bmiHeader.biWidth;//线性渐变
					alpha = (ShadowWidth - r)*(ShadowWidth - r) * MaxOpaque / (ShadowWidth*ShadowWidth);//二次函数
					((UINT32*)pvBits)[x + y * bmi.bmiHeader.biWidth] = (alpha << 24) | (grayLevel << 16) | (grayLevel << 8) | grayLevel;
				}
			}
			else if (x < ShadowWidth && y > bmi.bmiHeader.biHeight - ShadowWidth)
			{
				int r = sqrt((double)(x - ShadowWidth)*(x - ShadowWidth) +
					(y - bmi.bmiHeader.biHeight + ShadowWidth)*(y - bmi.bmiHeader.biHeight + ShadowWidth));
				if (r > ShadowWidth)
					((UINT32*)pvBits)[x + y * bmi.bmiHeader.biWidth] = 0x00ffffff;//ARGB,A=0表示透明,A=255表示不透明
				else
				{
					unsigned char alpha;
					//alpha = 50 * (double)x / bmi.bmiHeader.biWidth;//线性渐变
					alpha = (ShadowWidth - r)*(ShadowWidth - r) * MaxOpaque / (ShadowWidth*ShadowWidth);//二次函数
					((UINT32*)pvBits)[x + y * bmi.bmiHeader.biWidth] = (alpha << 24) | (grayLevel << 16) | (grayLevel << 8) | grayLevel;
				}
			}
			//中间的矩形区域
			else if (x >= ShadowWidth && x <= bmi.bmiHeader.biWidth - ShadowWidth && y >= ShadowWidth && y <= bmi.bmiHeader.biHeight - ShadowWidth)
				((UINT32*)pvBits)[x + y * bmi.bmiHeader.biWidth] = 0xffffffff;//ARGB,A=0表示透明,A=255表示不透明

			

			//unsigned char alpha;
			//alpha = 50 * (double)x / bmi.bmiHeader.biWidth;//线性渐变
			//alpha = x*x * 50 / (bmi.bmiHeader.biWidth*bmi.bmiHeader.biWidth);//二次函数
			//alpha = 255;
			//((UINT32*)pvBits)[x + y * bmi.bmiHeader.biWidth] = (alpha << 24) | (grayLevel << 16) | (grayLevel << 8) | grayLevel;
			// 0x0A000000;//ARGB,A=0表示透明,A=255表示不透明
		}
	}

	pre_multiply(pvBits, bmi.bmiHeader.biWidth, bmi.bmiHeader.biHeight);

	/*
	操作系统执行AlphaBlend的公式如下:
	Dst.Red = Src.Red + (1 - Src.Alpha/255) * Dst.Red
	Dst.Green = Src.Green + (1 - Src.Alpha/255) * Dst.Green
	Dst.Blue = Src.Blue + (1 - Src.Alpha/255) * Dst.Blue
	*/

	HDC hdcScreen = GetDC(NULL);
	POINT dstPt = { 0, 0 };
	POINT srcPt = { 0, 0 };
	SIZE size = { bmi.bmiHeader.biWidth, bmi.bmiHeader.biHeight };
	BLENDFUNCTION bf;
	bf.BlendOp = AC_SRC_OVER;
	bf.BlendFlags = 0;
	bf.AlphaFormat = AC_SRC_ALPHA;  // use source alpha 
	bf.SourceConstantAlpha = 0xff;  // opaque (disable constant alpha)
	BOOL b = UpdateLayeredWindow(hwnd, hdcScreen, &dstPt, &size, hdcMem, &srcPt, 0, &bf, ULW_ALPHA);
	ReleaseDC(NULL, hdcScreen);

	DeleteObject(hdcMem);
	DeleteObject(hBmp);
}

HWND hFgWnd;
HWND hBkWnd;

int WINAPI WinMain(HINSTANCE hInstance,
	HINSTANCE hPrevInstance,
	LPSTR lpCmdLine,
	int nCmdShow
	)
{
	WNDCLASSA wls;
	wls.cbClsExtra = 0;
	wls.cbWndExtra = 0;
	wls.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
	wls.hCursor = LoadCursorA(NULL, IDC_ARROW);
	wls.hIcon = LoadIconA(NULL, IDI_APPLICATION);
	wls.hInstance = hInstance;
	wls.lpfnWndProc = WindowProc;
	wls.lpszClassName = "Win32Template";
	wls.lpszMenuName = NULL;
	wls.style = CS_HREDRAW | CS_VREDRAW;
	RegisterClassA(&wls);

	wls.hIcon = NULL;// LoadIconA(NULL, IDI_APPLICATION);
	wls.lpfnWndProc = ForegroundWndProc;
	wls.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
	wls.lpszClassName = "ForegroundWnd";
	RegisterClassA(&wls);

	int width = 500;
	int height = 400;
	hBkWnd = CreateWindowExA(WS_EX_LAYERED, "Win32Template", "Win32Template", WS_POPUP | WS_MINIMIZEBOX,
		0, 0, width, height
		, NULL, NULL, hInstance, NULL);

	hFgWnd = CreateWindowA("ForegroundWnd", NULL, WS_POPUP | WS_VISIBLE, ShadowWidth, ShadowWidth,
		width - 2 * ShadowWidth, height - 2 * ShadowWidth, hBkWnd, NULL, hInstance, NULL);
	
	shadow(hBkWnd, width, height);


	ShowWindow(hBkWnd, nCmdShow);
	//UpdateWindow(hwnd);

	MSG msg;
	while (GetMessageA(&msg, NULL, 0, 0))
	{
		TranslateMessage(&msg);
		DispatchMessageA(&msg);
	}

	return 0;
}

LRESULT CALLBACK WindowProc(HWND hwnd,
	UINT uMsg,
	WPARAM wParam,
	LPARAM lParam
	)
{
	PAINTSTRUCT ps;
	HDC hdc;
	RECT* rc;

	switch (uMsg)
	{
	case WM_CREATE:
		return 0;
	case WM_MOVING:
		rc = (RECT*)lParam;
		MoveWindow(hFgWnd, rc->left + ShadowWidth, rc->top + ShadowWidth, rc->right - rc->left - 2 * ShadowWidth, rc->bottom - rc->top - 2 * ShadowWidth, TRUE);
		//SetWindowPos(hFgWnd, hBgWnd, rc->left, rc->top, rc->right - rc->left, rc->bottom - rc->top, SWP_SHOWWINDOW);
		return TRUE;
	case WM_LBUTTONDOWN:
		SendMessage(hwnd, WM_NCLBUTTONDOWN, HTCAPTION, 0);
		return 0;
		/*case WM_PAINT:
			hdc = BeginPaint(hwnd, &ps);
			DrawAlphaBlend(hwnd, hdc);
			EndPaint(hwnd, &ps);
			return 0;*/
	case WM_CLOSE:
		DestroyWindow(hwnd);
		return 0;
	case WM_DESTROY:
		PostQuitMessage(0);
		return 0;
	default:
		break;
	}
	return DefWindowProcA(hwnd, uMsg, wParam, lParam);
}

LRESULT CALLBACK ForegroundWndProc(HWND hwnd,
	UINT uMsg,
	WPARAM wParam,
	LPARAM lParam
	)
{
	PAINTSTRUCT ps;
	HDC hdc;
	RECT* rc;
	HWND hBtn;

	switch (uMsg)
	{
	case WM_CREATE:
		hBtn = CreateWindowA("BUTTON", "测试控件", WS_VISIBLE|BS_PUSHBUTTON | WS_CHILD, 100, 100,
			100, 50, hwnd, (HMENU)1234, GetModuleHandleA(NULL), NULL);
		return 0;
	case WM_COMMAND:
		switch (LOWORD(wParam))
		{
		case 1234:
			MessageBoxA(hwnd, "", "", 0);
			return 0;
		default:
			break;
		}
		return 0;
	case WM_MOVING:
		rc = (RECT*)lParam;
		MoveWindow(hBkWnd, rc->left - ShadowWidth, rc->top - ShadowWidth, rc->right - rc->left + 2 * ShadowWidth, rc->bottom - rc->top + 2 * ShadowWidth, TRUE);
		//SetWindowPos(hFgWnd, hBgWnd, rc->left, rc->top, rc->right - rc->left, rc->bottom - rc->top, SWP_SHOWWINDOW);
		return TRUE;
	case WM_LBUTTONDOWN:
		SendMessage(hwnd, WM_NCLBUTTONDOWN, HTCAPTION, 0);
		return 0;
		/*case WM_PAINT:
		hdc = BeginPaint(hwnd, &ps);
		DrawAlphaBlend(hwnd, hdc);
		EndPaint(hwnd, &ps);
		return 0;*/
	case WM_CLOSE:
		DestroyWindow(hwnd);
		return 0;
	case WM_DESTROY:
		PostQuitMessage(0);
		return 0;
	default:
		break;
	}
	return DefWindowProcA(hwnd, uMsg, wParam, lParam);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值