WinAPI中使用GDI+绘制图片时如何将宿主窗口设为透明仅显示图片
实现仅显示绘制图片的窗口方案
你可以通过分层窗口(Layered Window) + 无边框窗口样式的组合实现需求,核心逻辑是去掉窗口默认的标题栏、边框等装饰,再将窗口背景区域设为完全透明,仅保留你绘制的图片区域可见。
具体修改步骤
- 修改窗口创建参数:开启分层窗口扩展样式,替换默认的带标题栏边框的窗口样式为无边框样式
- 设置窗口透明色:通过
SetLayeredWindowAttributes指定某一颜色为透明键,所有使用该颜色绘制的区域都会被系统自动设为透明 - 修改窗口背景填充色为上述指定的透明键色,调整窗口尺寸和图片尺寸匹配,避免多余透明区域
修改后完整示例代码
#include <windows.h> #include <objidl.h> #include <gdiplus.h> using namespace Gdiplus; #pragma comment (lib, "Gdiplus.lib") // 定义透明键色,选择极少会用到的洋红色避免和图片内容冲突 #define TRANSPARENT_COLOR RGB(255, 0, 255) Image* pImage = nullptr; // 全局存储图片指针方便获取尺寸 void Example_DrawImage9(HDC hdc) { Graphics graphics(hdc); graphics.DrawImage(pImage, 0, 0); // 从窗口左上角开始绘制,避免偏移 } LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR pCmdLine, int nCmdShow) { ULONG_PTR token; GdiplusStartupInput input = { 0 }; input.GdiplusVersion = 1; GdiplusStartup(&token, &input, NULL); // 提前加载图片获取宽高 pImage = new Image(L"C:/Users/Darek/Fallout2/data/art/iface/armor_info.bmp"); int imgWidth = pImage->GetWidth(); int imgHeight = pImage->GetHeight(); const wchar_t CLASS_NAME[] = L"Sample Window Class"; WNDCLASS wc = {}; wc.lpfnWndProc = &WindowProc; wc.hInstance = hInstance; wc.lpszClassName = CLASS_NAME; // 设置窗口背景刷为透明键色,避免刷新时闪烁 wc.hbrBackground = CreateSolidBrush(TRANSPARENT_COLOR); RegisterClass(&wc); // 扩展样式添加WS_EX_LAYERED开启分层窗口,可选添加WS_EX_TOOLWINDOW隐藏任务栏图标 HWND hwnd = CreateWindowEx( WS_EX_LAYERED | WS_EX_TOOLWINDOW, CLASS_NAME, L"", WS_POPUP, // 无边框样式,去掉标题栏、边框等装饰 CW_USEDEFAULT, CW_USEDEFAULT, imgWidth, imgHeight, // 窗口尺寸和图片完全匹配 NULL, NULL, hInstance, NULL ); if (hwnd != NULL) { // 设置透明键,所有TRANSPARENT_COLOR颜色的区域都会透明 SetLayeredWindowAttributes(hwnd, TRANSPARENT_COLOR, 0, LWA_COLORKEY); ShowWindow(hwnd, nCmdShow); MSG msg; while (GetMessage(&msg, NULL, 0, 0) > 0) { TranslateMessage(&msg); DispatchMessage(&msg); } } delete pImage; GdiplusShutdown(token); return 0; } LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { case WM_DESTROY: PostQuitMessage(0); return 0; case WM_PAINT: { PAINTSTRUCT ps; HDC hdc = BeginPaint(hwnd, &ps); // 背景填充为透明键色,会被自动穿透 FillRect(hdc, &ps.rcPaint, (HBRUSH)GetStockObject(GRAY_BRUSH)); Example_DrawImage9(hdc); EndPaint(hwnd, &ps); return 0; } } return DefWindowProc(hwnd, uMsg, wParam, lParam); }
补充说明
- 如果你的图片本身带alpha透明通道,需要更精细的透明效果,可以使用
UpdateLayeredWindow直接将带alpha的图片内容贴到窗口上,不需要指定透明键色,效果更平滑 - 如果你需要允许用户拖拽图片移动,可以在
WindowProc中响应WM_NCHITTEST消息,返回HTCAPTION即可实现点击图片任意位置拖动窗口的效果 - 不需要的话可以去掉
WS_EX_TOOLWINDOW扩展样式,窗口会正常显示在任务栏中
内容的提问来源于stack exchange,提问作者Daros911
相关产品推荐
相关产品推荐

