无需使用*.DLL库能否开发显示PNG图片的启动闪屏?
可行性结论
完全可以实现,无需额外引入第三方DLL,仅依赖Windows系统内置的GDI+和Win32 API即可完成PNG闪屏开发,同时支持自定义显示位置、自定义显示时长的需求。
支持特性
- 完整支持带透明通道的PNG图片渲染
- 支持两种位置配置:屏幕自动居中、任意指定左上角坐标
- 支持自定义显示时长,精度为毫秒级
- 可选支持点击闪屏提前关闭
- 无额外DLL分发需求,系统内置组件即可运行
完整实现代码(C++ Win32)
#include <windows.h> #include <gdiplus.h> #pragma comment(lib, "gdiplus.lib") // 配置参数,可自行修改 #define SPLASH_PNG_RES_ID IDR_PNG1 // 你的PNG资源ID #define SPLASH_DISPLAY_TIME 3000 // 显示时长,单位毫秒,3000=3秒 #define SPLASH_CUSTOM_POS_X CW_USEDEFAULT // 自定义X坐标,CW_USEDEFAULT为居中 #define SPLASH_CUSTOM_POS_Y CW_USEDEFAULT // 自定义Y坐标,CW_USEDEFAULT为居中 ULONG_PTR g_gdiplusToken = 0; HWND g_hSplashWnd = NULL; // 从资源加载PNG图片 Gdiplus::Bitmap* LoadPngFromResource(UINT resId) { HRSRC hRes = FindResource(NULL, MAKEINTRESOURCE(resId), L"PNG"); HGLOBAL hGlobal = LoadResource(NULL, hRes); DWORD resSize = SizeofResource(NULL, hRes); HGLOBAL hBuffer = GlobalAlloc(GMEM_MOVEABLE, resSize); LPVOID pBuffer = GlobalLock(hBuffer); CopyMemory(pBuffer, LockResource(hGlobal), resSize); GlobalUnlock(hBuffer); IStream* pStream = NULL; CreateStreamOnHGlobal(hBuffer, TRUE, &pStream); Gdiplus::Bitmap* pBitmap = Gdiplus::Bitmap::FromStream(pStream); pStream->Release(); return pBitmap; } // 闪屏窗口过程 LRESULT CALLBACK SplashWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch(msg) { case WM_CREATE: { Gdiplus::Bitmap* pBitmap = LoadPngFromResource(SPLASH_PNG_RES_ID); if(!pBitmap) break; int width = pBitmap->GetWidth(); int height = pBitmap->GetHeight(); // 计算窗口位置 int x = SPLASH_CUSTOM_POS_X; int y = SPLASH_CUSTOM_POS_Y; if(x == CW_USEDEFAULT || y == CW_USEDEFAULT) { int screenW = GetSystemMetrics(SM_CXSCREEN); int screenH = GetSystemMetrics(SM_CYSCREEN); x = (screenW - width) / 2; y = (screenH - height) / 2; } SetWindowPos(hWnd, HWND_TOPMOST, x, y, width, height, SWP_NOACTIVATE); // 配置分层窗口实现透明PNG渲染 HDC hdcScreen = GetDC(NULL); HDC hdcMem = CreateCompatibleDC(hdcScreen); HBITMAP hBmp = NULL; pBitmap->GetHBITMAP(Gdiplus::Color(0), &hBmp); HBITMAP hOldBmp = (HBITMAP)SelectObject(hdcMem, hBmp); BLENDFUNCTION blend = {0}; blend.BlendOp = AC_SRC_OVER; blend.SourceConstantAlpha = 255; blend.AlphaFormat = AC_SRC_ALPHA; UpdateLayeredWindow(hWnd, hdcScreen, NULL, &SIZE{width, height}, hdcMem, &POINT{0,0}, 0, &blend, ULW_ALPHA); SelectObject(hdcMem, hOldBmp); DeleteObject(hBmp); DeleteDC(hdcMem); ReleaseDC(NULL, hdcScreen); delete pBitmap; // 设置定时器到点关闭闪屏 SetTimer(hWnd, 1, SPLASH_DISPLAY_TIME, NULL); break; } case WM_TIMER: case WM_LBUTTONDOWN: // 点击鼠标左键提前关闭 DestroyWindow(hWnd); break; case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hWnd, msg, wParam, lParam); } return 0; } // 入口函数,你可以在程序启动时调用ShowSplash()来显示闪屏 void ShowSplash() { // 初始化GDI+ Gdiplus::GdiplusStartupInput input; Gdiplus::GdiplusStartup(&g_gdiplusToken, &input, NULL); // 注册窗口类 WNDCLASSEX wc = {0}; wc.cbSize = sizeof(wc); wc.lpfnWndProc = SplashWndProc; wc.hInstance = GetModuleHandle(NULL); wc.lpszClassName = L"SplashWindowClass"; wc.hCursor = LoadCursor(NULL, IDC_ARROW); RegisterClassEx(&wc); // 创建分层窗口 g_hSplashWnd = CreateWindowEx(WS_EX_LAYERED | WS_EX_TOOLWINDOW | WS_EX_TOPMOST, wc.lpszClassName, L"Splash", WS_POPUP, 0, 0, 0, 0, NULL, NULL, wc.hInstance, NULL); ShowWindow(g_hSplashWnd, SW_SHOW); UpdateWindow(g_hSplashWnd); // 消息循环 MSG msg; while(GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } // 清理资源 Gdiplus::GdiplusShutdown(g_gdiplusToken); }
配置说明
- 资源导入:将PNG图片添加到项目资源中,资源类型设置为
PNG,修改SPLASH_PNG_RES_ID宏为你实际的资源ID即可 - 位置配置:如果需要指定固定位置,修改
SPLASH_CUSTOM_POS_X和SPLASH_CUSTOM_POS_Y为你需要的坐标值即可,默认的CW_USEDEFAULT为自动居中显示 - 时长配置:修改
SPLASH_DISPLAY_TIME的数值即可调整显示时长,单位为毫秒 - 功能调整:如果不需要点击提前关闭,删除
WM_LBUTTONDOWN的响应分支即可
注意:代码依赖的gdiplus.dll为Windows Vista及以上系统内置组件,无需额外随程序分发,完全符合无第三方DLL的要求。
内容的提问来源于stack exchange,提问作者sesshoumaru81
相关产品推荐
相关产品推荐

