C++ 在透明窗口中绘制半透明矩形
我在stackoverflow中发现了这段代码,它使用位图在透明窗口上绘制了一个矩形。但不知何故,我无法改变矩形的透明度。更准确地说,我可以,但它会变得更暗。就像位图本身有黑色背景一样。如何使矩形透明C++ 在透明窗口中绘制半透明矩形,c++,winapi,gdi,C++,Winapi,Gdi,我在stackoverflow中发现了这段代码,它使用位图在透明窗口上绘制了一个矩形。但不知何故,我无法改变矩形的透明度。更准确地说,我可以,但它会变得更暗。就像位图本身有黑色背景一样。如何使矩形透明 void paintRect(HDC hdc, RECT dim, COLORREF penCol, COLORREF brushCol, int opacity) { HDC tempHDC = CreateCompatibleDC(hdc);
void paintRect(HDC hdc, RECT dim, COLORREF penCol, COLORREF brushCol, int opacity)
{
HDC tempHDC = CreateCompatibleDC(hdc);
BITMAPINFO bitmapInfo;
ZeroMemory(&bitmapInfo, sizeof(BITMAPINFO));
bitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bitmapInfo.bmiHeader.biWidth = dim.right - dim.left;
bitmapInfo.bmiHeader.biHeight = dim.bottom - dim.top;
bitmapInfo.bmiHeader.biPlanes = 1;
bitmapInfo.bmiHeader.biBitCount = 32;
bitmapInfo.bmiHeader.biCompression = BI_RGB;
bitmapInfo.bmiHeader.biSizeImage = (dim.right - dim.left) * (dim.bottom - dim.top) * 4;
HBITMAP hBitmap = CreateDIBSection(tempHDC, &bitmapInfo, DIB_RGB_COLORS, NULL, NULL, 0x0);
SelectObject(tempHDC, hBitmap);
SetDCPenColor(tempHDC, RGB(0, 0, 255));
SetDCBrushColor(tempHDC, RGB(0, 0, 255));
FillRect(tempHDC, &dim, CreateSolidBrush(RGB(0, 0, 255)));
BLENDFUNCTION blend = { AC_SRC_OVER, 0, 255, 0 };
AlphaBlend(hdc, dim.left, dim.top, dim.right, dim.bottom, tempHDC, dim.left, dim.top, dim.right, dim.bottom, blend);
}
完整代码
#include <Windows.h>
int wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int nCmdShow);
LRESULT CALLBACK windowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
int APIENTRY wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int nCmdShow)
{
WNDCLASS windowClass {};
windowClass.lpfnWndProc = windowProc;
windowClass.hInstance = hInstance;
windowClass.lpszClassName = L"Keystrokes";
windowClass.style = CS_NOCLOSE;
windowClass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
windowClass.hCursor = LoadCursor(NULL, IDC_ARROW);
if (!RegisterClass(&windowClass))
{
return 0;
}
HWND hwnd = CreateWindowEx(WS_EX_LAYERED | WS_EX_TOPMOST | WS_EX_TOOLWINDOW, L"Keystrokes", L"Keystrokes", WS_POPUP, 0, 0, 148, 140, 0, 0, hInstance, 0);
if (!hwnd)
{
return 0;
}
SetLayeredWindowAttributes(hwnd, RGB(0, 0, 0), 0, LWA_COLORKEY);
ShowWindow(hwnd, nCmdShow);
MSG msg {};
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
void paintRect(HDC hdc, RECT dim, COLORREF penCol, COLORREF brushCol, int opacity)
{
HDC tempHDC = CreateCompatibleDC(hdc);
BITMAPINFO bitmapInfo;
ZeroMemory(&bitmapInfo, sizeof(BITMAPINFO));
bitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bitmapInfo.bmiHeader.biWidth = dim.right - dim.left;
bitmapInfo.bmiHeader.biHeight = dim.bottom - dim.top;
bitmapInfo.bmiHeader.biPlanes = 1;
bitmapInfo.bmiHeader.biBitCount = 32;
bitmapInfo.bmiHeader.biCompression = BI_RGB;
bitmapInfo.bmiHeader.biSizeImage = (dim.right - dim.left) * (dim.bottom - dim.top) * 4;
HBITMAP hBitmap = CreateDIBSection(tempHDC, &bitmapInfo, DIB_RGB_COLORS, NULL, NULL, 0x0);
SelectObject(tempHDC, hBitmap);
SetDCPenColor(tempHDC, RGB(0, 0, 255));
SetDCBrushColor(tempHDC, RGB(0, 0, 255));
FillRect(tempHDC, &dim, CreateSolidBrush(RGB(0, 0, 255)));
BLENDFUNCTION blend = { AC_SRC_OVER, 0, 255, 0 };
AlphaBlend(hdc, dim.left, dim.top, dim.right, dim.bottom, tempHDC, dim.left, dim.top, dim.right, dim.bottom, blend);
}
LRESULT CALLBACK windowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_LBUTTONDOWN:
{
SendMessage(hwnd, WM_NCLBUTTONDOWN, HTCAPTION, 0);
}
break;
case WM_MBUTTONDOWN:
{
PostQuitMessage(0);
}
break;
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hDC = BeginPaint(hwnd, &ps);
paintRect(hDC, { 0, 0, 48, 48 }, RGB(255, 0, 0), RGB(255, 255, 255), 255);
EndPaint(hwnd, &ps);
}
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
#包括
int wWinMain(HINSTANCE HINSTANCE、HINSTANCE hPrevInstance、PWSTR pCmdLine、int nCmdShow);
LRESULT回调windowProc(HWND-HWND、UINT-uMsg、WPARAM-WPARAM、LPARAM-LPARAM);
int APICENT wWinMain(HINSTANCE HINSTANCE、HINSTANCE hPrevInstance、PWSTR pCmdLine、int nCmdShow)
{
WNDCLASS windowClass{};
windowClass.lpfnWndProc=windowProc;
windowClass.hInstance=hInstance;
windowClass.lpszClassName=L“击键”;
windowClass.style=CS\u NOCLOSE;
windowClass.hbrBackground=(HBRUSH)GetStockObject(黑色画笔);
windowClass.hCursor=LoadCursor(空,IDC_箭头);
if(!RegisterClass(&windowClass))
{
返回0;
}
HWND HWND=CreateWindowEx(WS|u EX|u分层的| WS|u EX|u最顶层的| WS|u EX|u工具窗口,L“击键”,L“击键”,WS|u弹出窗口,0,0,148,140,0,0,hInstance,0);
如果(!hwnd)
{
返回0;
}
SetLayeredWindowAttributes(hwnd、RGB(0、0、0)、0、LWA_颜色键);
显示窗口(hwnd、nCmdShow);
MSG{};
while(GetMessage(&msg,NULL,0,0))
{
翻译信息(&msg);
发送消息(&msg);
}
返回0;
}
void paintRect(HDC HDC、RECT dim、COLORREF penCol、COLORREF brushCol、int不透明)
{
HDC tempHDC=CreateCompatibleDC(HDC);
BITMAPINFO BITMAPINFO;
零内存(&bitmapInfo,sizeof(bitmapInfo));
bitmapInfo.bmiHeader.biSize=sizeof(bitmapInfo头文件);
bitmapInfo.bmiHeader.biWidth=dim.right-dim.left;
bitmapInfo.bmiHeader.biHeight=dim.bottom-dim.top;
bitmapInfo.bmiHeader.biPlanes=1;
bitmapInfo.bmiHeader.biBitCount=32;
bitmapInfo.bmiHeader.biCompression=BI_RGB;
bitmapInfo.bmiHeader.biSizeImage=(dim.right-dim.left)*(dim.bottom-dim.top)*4;
HBITMAP HBITMAP=CreateDIBSection(tempHDC,&bitmapInfo,DIB_RGB_颜色,NULL,NULL,0x0);
选择对象(tempHDC、hBitmap);
SetDCPenColor(tempHDC,RGB(0,0255));
SetDCBrushColor(tempHDC,RGB(0,0255));
FillRect(tempHDC,&dim,CreateSolidBrush(RGB(0,0255));
BLENDFUNCTION blend={AC_SRC_OVER,0,255,0};
AlphaBlend(hdc、dim.left、dim.top、dim.right、dim.bottom、tempHDC、dim.left、dim.top、dim.right、dim.bottom、blend);
}
LRESULT回调windowProc(HWND HWND、UINT uMsg、WPARAM WPARAM、LPARAM LPARAM)
{
开关(uMsg)
{
案例WM_LBUTTONDOWN:
{
发送消息(hwnd、WM_nclubuttondown、HTCAPTION、0);
}
打破
案例WM_mbutdown:
{
PostQuitMessage(0);
}
打破
案例WM_油漆:
{
PAINTSTRUCT-ps;
HDC HDC=开始喷漆(hwnd和ps);
paintRect(hDC,{0,0,48,48},RGB(255,0,0),RGB(255,255,255),255);
端漆(hwnd和ps);
}
}
返回DefWindowProc(hwnd、uMsg、wParam、lParam);
}
“就像位图本身有黑色背景一样。”
因为您的背景设置为:
windowClass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
当然,您可以将其设置为NULL\u BRUSH
,使其看起来透明:
windowClass.hbrBackground = (HBRUSH)GetStockObject(NULL_BRUSH);
但当您移动它时,您会发现这并不是要使窗口透明,而是要停止绘制背景:
正如@Ben所回答的:
您没有使窗口透明,只是停止绘制背景。你所看到的背景就是第一次绘制窗口时在窗口下面发生的事情
你需要参考
不能直接在窗口上添加矩形,应使用分层窗口,然后添加所需内容
以下是您可以参考的示例:
#include <Windows.h>
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
int WINAPI WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPSTR szCmdLine, _In_ int iCmdShow)
{
static TCHAR szAppName[] = TEXT("test window");
HWND hwnd;
MSG msg;
WNDCLASS wndclass;
wndclass.style = CS_HREDRAW | CS_VREDRAW;
wndclass.lpfnWndProc = WndProc;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hInstance = hInstance;
wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wndclass.lpszMenuName = NULL;
wndclass.lpszClassName = szAppName;
if (!RegisterClass(&wndclass))
{
MessageBox(NULL, TEXT("This program requires Windows NT!"), szAppName, MB_ICONERROR);
}
hwnd = CreateWindowEx(WS_EX_LAYERED | WS_EX_TOPMOST | WS_EX_TOOLWINDOW, szAppName,
TEXT("the hello program"),
WS_POPUP,
CW_USEDEFAULT,
CW_USEDEFAULT,
148,
148,
NULL,
NULL,
hInstance,
NULL);
SetLayeredWindowAttributes(hwnd, 0, 1, LWA_ALPHA);
ShowWindow(hwnd, iCmdShow);
UpdateWindow(hwnd);
while (GetMessageW(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessageW(&msg);
}
return msg.wParam;
}
VOID FadeRect(RECT* prc, HDC hdc)
{
BOOL fFade = FALSE;
static HWND hwnd;
SIZE size;
POINT ptSrc = { 0, 0 };
BLENDFUNCTION blend;
SystemParametersInfo(SPI_GETSELECTIONFADE, 0, &fFade, 0);
if (!fFade)
return;
if (!hwnd) hwnd = CreateWindowEx(WS_EX_LAYERED |
WS_EX_TRANSPARENT |
WS_EX_TOPMOST | WS_EX_TOOLWINDOW,
L"static", L"static", WS_POPUP | WS_VISIBLE, prc->left,
prc->top, prc->right, prc->bottom, NULL, (HMENU)0, NULL, NULL);
else MoveWindow(hwnd, prc->left, prc->top, prc->right, prc->bottom, TRUE);
RECT rect{ prc->left,prc->top,prc->right,prc->bottom };
size.cx = prc->right - prc->left;
size.cy = prc->bottom - prc->top;
blend.BlendOp = AC_SRC_OVER;
blend.BlendFlags = 0;
blend.AlphaFormat = 0;
blend.SourceConstantAlpha = 150;
UpdateLayeredWindow(hwnd, NULL, NULL, &size, hdc, &ptSrc, 0,
&blend, ULW_ALPHA);
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_LBUTTONDOWN:
{
SendMessage(hwnd, WM_NCLBUTTONDOWN, HTCAPTION, 0);
InvalidateRect(hwnd, NULL, TRUE);
}
break;
case WM_MBUTTONDOWN:
{
PostQuitMessage(0);
}
break;
case WM_PAINT:
{
PAINTSTRUCT ps;
RECT rect;
GetClientRect(hwnd, &rect);
MapWindowPoints(hwnd, GetParent(hwnd), (LPPOINT)&rect, 2);
HDC hDC = BeginPaint(hwnd, &ps);
RECT rc{ rect.left,rect.top,rect.left + 48,rect.top + 48 };
FadeRect(&rc, hDC);
EndPaint(hwnd, &ps);
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
}
return DefWindowProc(hwnd, message, wParam, lParam);
}
#包括
LRESULT回调WndProc(HWND、UINT、WPARAM、LPARAM);
int WINAPI WinMain(_In_uuhinstance HINSTANCE,_In_uopt_uuuhinstance hPrevInstance,_In_uustrszcmdline,u In_uuint iCmdShow)
{
静态TCHAR szAppName[]=文本(“测试窗口”);
HWND-HWND;
味精;
WNDCLASS WNDCLASS;
wndclass.style=CS_HREDRAW | CS_VREDRAW;
wndclass.lpfnWndProc=WndProc;
wndclass.cbClsExtra=0;
wndclass.cbWndExtra=0;
wndclass.hInstance=hInstance;
wndclass.hIcon=LoadIcon(空,IDI_应用程序);
wndclass.hCursor=LoadCursor(空,IDC_箭头);
wndclass.hbrBackground=(HBRUSH)GetStockObject(白色画笔);
wndclass.lpszMenuName=NULL;
wndclass.lpszClassName=szAppName;
if(!RegisterClass(&wndclass))
{
MessageBox(NULL,文本(“此程序需要Windows NT!”),szAppName,MB_ICONERROR);
}
hwnd=CreateWindowEx(WS_EX_分层的| WS_EX_顶层的| WS_EX_工具窗口,szAppName,
文本(“hello程序”),
WS_弹出窗口,
CW_使用默认值,
CW_使用默认值,
148,
148,
无效的
无效的
hInstance,
无效);
SetLayeredWindowAttributes(hwnd、0、1、LWA_ALPHA);
显示窗口(hwnd、iCmdShow);
更新窗口(hwnd);
while(GetMessageW(&msg,NULL,0,0))
{
翻译信息(&msg);
DispatchMessageW(&msg);
}
返回msg.wParam;
}
无效安装(矩形*prc、HDC、HDC)
{
BOOL-fFade=假;
静态HWND-HWND;
大小;
点ptSrc={0,0};
混合功能混合;
系统参数信息(SPI_GETSELECTIONFADE,0和fFade,0);
如果(!fFade)
返回;
如果(!hwnd)hwnd=CreateWindowEx(WS_EX_LAYERED |
WS_exu|u TRANSPARENT|
WS_EX_TOPMOST | WS_EX_TOOLWINDOW,
L“静态”,L“静态”,WS|u弹出窗口| WS|u可见,prc->左侧,
prc->top,prc->right,prc->bottom,空,(HMENU)0,空,空);
else移动窗口(hwnd,prc->左,prc->顶,prc->右,prc->底,真);
RECT RECT{prc->左,prc->上,prc->右,p