#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);
}
Win32实现阴影窗口
最新推荐文章于 2023-08-10 10:19:00 发布