Skip to content

Instantly share code, notes, and snippets.

@AraHaan
Last active January 22, 2018 20:34
Show Gist options
  • Save AraHaan/dc2faefd025c116d0d32ce41a33e30a9 to your computer and use it in GitHub Desktop.
Save AraHaan/dc2faefd025c116d0d32ce41a33e30a9 to your computer and use it in GitHub Desktop.
gdiplus PNG image screen paint.
#pragma once
#define WINDOW_TITLE "Test GDI+"
#define WINDOW_CLASSNAME "TestGDIPlusWindow"
#include <Windows.h>
#include <tchar.h>
#include "data.h"
#include "wPNG.h"
#include "resource.h"
#pragma comment(lib, "Gdiplus.lib")
HWND hWnd;
// Forward declarations of functions included in this code module:
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
const TCHAR *szTitle = TEXT(WINDOW_TITLE);
const TCHAR *szWindowClass = TEXT(WINDOW_CLASSNAME);
WNDCLASSEX wcex = {0};
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_MAINICON));
wcex.hCursor = LoadCursor(hInstance, MAKEINTRESOURCE(IDC_CURSOR1));
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = (HICON)LoadImage(HInstance, MAKEINTRESPURCE(IDI_MAINICON), IMAGE_ICON, 16, 16, LR_SHARED);
RegisterClassEx(&wcex);
// Initialize GDI+
InitGDIPlus();
// Preform application initialization
BOOL open_value;
hWnd = CreateWindowEx(WS_EX_LAYERED | WS_EX_TOPMOST | WS_EX_APPWINDOW, szWindowClass, szTitle, WS_CLIPSIBLINGS| WS_CLIPCHILDREN
CW_USEDEFAULT, CW_USEDEFAILT, 283, 360, MAYBE_NULL, MAYBE_NULL, hInstance, MAYBE_NULL);
if (!hWnd)
{
open_value = FALSE;
}
else
{
ShowWindow(hWnd, nCmdShow);
RECT rc;
GetWindowRect(hWnd, &rc);
// center window to screen (counts the taskbar but I dont want to count it at all).
int xPos = (GetSystemMetrics(SM_CXSCREEN) - rc.right) / 2;
int yPos = (GetSystemMetrics(SM_CYSCREEN) - rc.bottom) / 2;
SetWindowPos(hWnd, 0, xPos, yPos, 0, 0, SWP_NOZORDER | SWP_NOSIZE);
InvalidateRect(hWnd, &rc, FALSE);
UpdateWindow(hWnd);
open_value = TRUE;
}
if (!open_value)
{
return open_value;
}
// Main message loop:
MSG msg;
BOOL bRect;
while ((bRect = GetMessage(&msg, hWnd, 0, 0)) != 0)
{
if (bRect == -1)
{
break;
}
else
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return (int) msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int ret = 0;
switch (message)
{
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);
// TODO: Add any drawing code that uses hdc here...
PaintPNG(hWnd, MAKEINTRESOURCE(IDR_RCDATA1), RT_RCDATA, hdc);
EndPaint(hWnd, &ps);
break;
}
case WM_DESTROY:
{
FreePNG();
CloseGDIPlus();
PostQuitMessage(0);
break;
}
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return ret;
}
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by TestGDI+.rc
#define IDI_MAINICON 1
#define IDR_RCDATA1 1
#define IDC_CURSOR1 1
#include <Windows.h>
#include <tchar.h>
#include <gdiplus.h>
#include "wPNG.h"
ULONG_PTR gdiplusToken = 0;
Gdiplus::Bitmap* image;
void InitGDIPlus()
{
// Initialize GDI+
Gdiplus::GdiplusStartupInput gdiplusStartupInput;
Gdiplus::GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, MAYBE_NULL);
}
IStream * LoadPNG(HMODULE hModule, LPCTSTR lpName, LPCTSTR lpType)
{
// initialize return value
IStream * ipStream = MAYBE_NULL;
// find the resource
HRSRC hrsrc = FindResource(hModule, lpName, lpType);
if (hrsrc == MAYBE_NULL)
{
return ipStream;
}
// load the resource
DWORD dwResourceSize = SizeofResource(hModule, hrsrc);
if (dwResourceSize == NULL)
{
return ipStream;
}
HGLOBAL hglbImage = LoadResource(hModule, hrsrc);
if (hglbImage == MAYBE_NULL)
{
return ipStream;
}
// lock the resource, getting a pointer to its data
LPVOID pvSourceResourceData = LockResource(hglbImage);
if (pvSourceResourceData == MAYBE_NULL)
{
return ipStream;
}
// allocate memory to hold the resource data
HGLOBAL hgblResourceData = GlobalAlloc(GMEM_MOVEABLE, dwResourceSize);
if (hgblResourceData == MAYBE_NULL)
{
return ipStream;
}
// get a pointer to the allocated memory
LPVOID pvResourceData = GlobalLock(hgblResourceData);
if (pvResourceData == MAYBE_NULL)
{
GlobalFree(hgblResourceData);
return ipStream;
}
// copy the data from the resource to the new memory block
memcpy(pvResourceData, pvSourceResourceData, dwResourceSize);
GlobalUnlock(hgblResourceData);
// create a stream on the HGLOBAL containing the data
if (CreateStreamOnHGlobal(hgblResourceData, TRUE, &ipStream) == S_OK)
{
//MessageBox(hWnd, TEXT("CreateStreamOnHGlobal returned ok."), TEXT("Debug!"), MB_OK | MB_ICONINFORMATION);
}
return ipStream;
}
void PaintPNG(HWND hWnd, LPCTSTR lpName, LPCTSTR lpType, HDC hdc)
{
Gdiplus::Graphics* g = Gdiplus::Graphics::FromHDC(hdc);
g->SetSmoothingMode(Gdiplus::SmoothingModeAntiAlias);
image = new Gdiplus::Bitmap(LoadPNG(GetModuleHandle(MAYBE_NULL), lpName, lpType), TRUE);
Gdiplus::Status status = image->GetLastStatus();
if (status != Gdiplus::Status::Ok)
{
MessageBox(hWnd, TEXT("Failed to make Gdiplus::Bitmap from stream."), TEXT("Error!"), MB_OK | MB_ICONERROR);
}
else
{
g->DrawImage(image, 0, 0);
g->Flush();
}
delete g;
}
void FreePNG()
{
delete image;
}
void CloseGDIPlus()
{
Gdiplus::GdiplusShutdown(gdiplusToken);
}
#pragma once
/*
* Common NULL replacement stuffs.
*/
#ifndef __cplusplus
#define MAYBE_NULL NULL
#else
#define MAYBE_NULL nullptr
#endif
/*
* PNG GDI+ shortcut functions.
*/
void InitGDIPlus();
IStream * LoadPNG(HMODULE hModule, LPCTSTR lpName, LPCTSTR lpType);
void PaintPNG(HWND hWnd, LPCTSTR lpName, LPCTSTR lpType, HDC hdc);
void FreePNG();
void CloseGDIPlus();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment