问题描述
#include <Windows.h>
#include <objidl.h>
#include <gdiplus.h>
using namespace Gdiplus;
#pragma comment (lib,"Gdiplus.lib")
#pragma comment(lib,"dwmapi.lib")
...
auto CALLBACK BorderlessWindow::WndProc(HWND hwnd,UINT msg,WParaM wparam,LParaM lparam) noexcept -> LRESULT {
if (auto window_ptr = reinterpret_cast<BorderlessWindow*>(::getwindowlongPtrW(hwnd,GWLP_USERDATA))) {
auto& window = *window_ptr;
switch (msg) {
case WM_PAINT: {
HDC hdc;
PAINTSTRUCT ps;
hdc = BeginPaint(hwnd,&ps);
Graphics graphics(hdc);
Image image(L"C:\\my_image.png");
graphics.DrawImage(&image,50,50);
EndPaint(hwnd,&ps);
break;
}
}
}
return ::DefWindowProcW(hwnd,msg,wparam,lparam);
}
...
int CALLBACK WinMain(_In_ HINSTANCE hInstance,_In_opt_ HINSTANCE hPrevInstance,_In_ LPSTR lpCmdLine,_In_ int nCmdshow) {
GdiplusstartupInput gdiplusstartupInput;
ULONG_PTR gdiplusToken;
// Initialize GDI+.
Gdiplusstartup(&gdiplusToken,&gdiplusstartupInput,NULL);
...
GdiplusShutdown(gdiplusToken);
}
上面的代码适用于本地文件,我想使用我添加到我的项目中的资源文件。我该怎么做?
解决方法
TLDR:FindResource、LoadResource 和 LockResource 以获取指向图像字节的指针。然后从中制作一个 IStream。 IStream 可用于初始化 Gdi+ Image 或 Bitmap 对象。 (Gdiplus::Bitmap 派生自 Gdiplus::Image)
在 .rc 文件中添加一个新行:
IDI_MY_IMAGE_FILE PNG "foo.png"
并确保 IDI_MY_IMAGE_FILE 在您的 resource.h 头文件中定义为整数。
#define IDI_MY_IMAGE_FILE 131
然后在运行时加载图像:
Gdiplus::Bitmap* pBmp = LoadImageFromResource(hInstance,MAKEINTRESOURCE(IDI_MY_IMAGE_FILE),L"PNG");
其中 LoadImageFromResource
是一个辅助函数,它完成从应用程序资源加载 PNG 的所有繁重工作。
Gdiplus::Bitmap* LoadImageFromResource(HMODULE hMod,const wchar_t* resid,const wchar_t* restype)
{
IStream* pStream = nullptr;
Gdiplus::Bitmap* pBmp = nullptr;
HGLOBAL hGlobal = nullptr;
HRSRC hrsrc = FindResourceW(hInst,resid,restype); // get the handle to the resource
if (hrsrc)
{
DWORD dwResourceSize = SizeofResource(hMod,hrsrc);
if (dwResourceSize > 0)
{
HGLOBAL hGlobalResource = LoadResource(hMod,hrsrc); // load it
if (hGlobalResource)
{
void* imagebytes = LockResource(hGlobalResource); // get a pointer to the file bytes
// copy image bytes into a real hglobal memory handle
hGlobal = ::GlobalAlloc(GHND,dwResourceSize);
if (hGlobal)
{
void* pBuffer = ::GlobalLock(hGlobal);
if (pBuffer)
{
memcpy(pBuffer,imagebytes,dwResourceSize);
HRESULT hr = CreateStreamOnHGlobal(hGlobal,TRUE,&pStream);
if (SUCCEEDED(hr))
{
// pStream now owns the global handle and will invoke GlobalFree on release
hGlobal = nullptr;
pBmp = new Gdiplus::Bitmap(pStream);
}
}
}
}
}
}
if (pStream)
{
pStream->Release();
pStream = nullptr;
}
if (hGlobal)
{
GlobalFree(hGlobal);
hGlobal = nullptr;
}
return pBmp;
}