我正在尝试使用 GDI+ 和 C++ 在屏幕顶部覆盖图像。我已成功将图像绘制到不透明窗口,但我只希望窗口的背景是透明的,而不是整个窗口。
这是我的代码:
#include <windows.h>
#include <gdiplus.h>
LRESULT CALLBACK WindowProcessMessages(HWND hwnd, UINT msg, WPARAM param, LPARAM lparam);
void draw(HDC hdc);
int WINAPI WinMain(HINSTANCE currentInstance, HINSTANCE previousInstance, PSTR cmdLine, INT cmdCount) {
// Initialize GDI+
Gdiplus::GdiplusStartupInput gdiplusStartupInput;
ULONG_PTR gdiplusToken;
Gdiplus::GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, nullptr);
// Register the window class
const char* CLASS_NAME = "myWin32WindowClass";
WNDCLASS wc{};
wc.hInstance = currentInstance;
wc.lpszClassName = CLASS_NAME;
wc.hCursor = LoadCursor(nullptr, IDC_ARROW);
wc.hbrBackground = (HBRUSH)COLOR_WINDOW;
wc.lpfnWndProc = WindowProcessMessages;
RegisterClass(&wc);
// Create the window
//CreateWindow(CLASS_NAME, "Drawing Image",
// WS_POPUP | WS_VISIBLE, // Window style
// CW_USEDEFAULT, CW_USEDEFAULT, // Window initial position
// 800, 600, // Window size
// nullptr, nullptr, nullptr, nullptr);
CreateWindowEx(WS_EX_LAYERED, // Extended window style
CLASS_NAME, "Drawing Image",
WS_POPUP | WS_VISIBLE, // Window style
CW_USEDEFAULT, CW_USEDEFAULT, // Window position
800, 600, // Window size
nullptr, nullptr, currentInstance,
nullptr);
// Window loop
MSG msg{};
while (GetMessage(&msg, nullptr, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
Gdiplus::GdiplusShutdown(gdiplusToken);
return 0;
}
LRESULT CALLBACK WindowProcessMessages(HWND hwnd, UINT msg, WPARAM param, LPARAM lparam) {
HDC hdc;
PAINTSTRUCT ps;
SetLayeredWindowAttributes(hwnd, RGB(0, 0, 0), 255, LWA_COLORKEY | LWA_ALPHA);
switch (msg) {
case WM_PAINT:
SetLayeredWindowAttributes(hwnd, 0, 128, LWA_ALPHA);
hdc = BeginPaint(hwnd, &ps);
draw(hdc);
EndPaint(hwnd, &ps);
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
default:
return DefWindowProc(hwnd, msg, param, lparam);
}
}
void draw(HDC hdc) {
// MessageBox(nullptr, "Draw function called", "Debug", MB_OK);
Gdiplus::Graphics gf(hdc);
Gdiplus::Bitmap bmp(L"image.png");
gf.DrawImage(&bmp, 430, 10);
}
Run Code Online (Sandbox Code Playgroud)
据我所知,SetLayeredWindowAttributes窗口 alpha 的 影响整个窗口。
两年前,我写过一个类似问题的答案。
这也是基于Koro的想法。
我修改了前面的代码示例以显示您想要的窗口效果。(仅用于测试)
#include <ObjIdl.h>
#include <Windows.h>
#include <gdiplus.h>
#include <gdiplusheaders.h>
using namespace Gdiplus;
#pragma comment(lib, "Gdiplus.lib")
#define MAX_WIDTH 800
#define MAX_HEIGHT 600
using namespace std;
void DrawImg(HWND hwnd, HDC hdc);
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam,
LPARAM lParam) {
if (message == WM_DESTROY) {
PostQuitMessage(0);
}
return DefWindowProc(hwnd, message, wParam, lParam);
};
HINSTANCE hinst;
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevinstance, PSTR szCmdLine,
int iCmdShow) {
HWND hWnd;
GdiplusStartupInput gdiplusStartupInput;
ULONG_PTR gdiplusToken;
// Initialize GDI+
GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
hinst = GetModuleHandle(NULL);
// create a window class:
WNDCLASS wc = {};
wc.lpfnWndProc = WndProc;
wc.hInstance = hinst;
wc.lpszClassName = L"win32";
// register class with operating system:
RegisterClass(&wc);
// create and show window:
hWnd = CreateWindowExW(WS_EX_LAYERED | WS_EX_TOPMOST, L"win32", L"WinSoup",
WS_POPUP, 0, 0, 1000, 500, nullptr, nullptr, hInstance,
nullptr);
if (hWnd == NULL) {
return 0;
}
DrawImg(hWnd, GetDC(hWnd));
ShowWindow(hWnd, SW_SHOW);
MSG msg = {};
while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
void DrawImg(HWND hwnd, HDC hdc) {
Bitmap softwareBitmap(MAX_WIDTH, MAX_HEIGHT, PixelFormat32bppARGB);
Graphics g(&softwareBitmap);
g.Clear(Gdiplus::Color(20, 0, 0, 0)); // 20: alpha value
Gdiplus::Bitmap bmp2(L"image.png");
g.DrawImage(&bmp2, 430, 10);
HBITMAP bmp;
softwareBitmap.GetHBITMAP(Color(0, 0, 0, 0), &bmp);
HDC memdc = CreateCompatibleDC(hdc);
HGDIOBJ original = SelectObject(memdc, bmp);
BLENDFUNCTION blend = {0};
blend.BlendOp = AC_SRC_OVER;
blend.SourceConstantAlpha = 255;
blend.AlphaFormat = AC_SRC_ALPHA;
POINT ptLocation = {200, 300};
SIZE szWnd = {MAX_WIDTH, MAX_HEIGHT};
POINT ptSrc = {0, 0};
UpdateLayeredWindow(hwnd, hdc, &ptLocation, &szWnd, memdc, &ptSrc, 0, &blend,
ULW_ALPHA);
SelectObject(hdc, original);
DeleteObject(bmp);
DeleteObject(memdc);
}
Run Code Online (Sandbox Code Playgroud)