Did you include any code to initialize Gdiplus?
Refer to https://video2.skills-academy.com/en-us/windows/win32/api/gdiplusinit/nf-gdiplusinit-gdiplusstartup
This browser is no longer supported.
Upgrade to Microsoft Edge to take advantage of the latest features, security updates, and technical support.
hi, I want to draw a bitmap, as simple as that. From the beginning, the first step was to create a basic desktop app
Since the app Visual Studio creates does not include a Window class definition, I declared the bitmap as a global variable
// Global Variables:
HINSTANCE hInst; // current instance
WCHAR szTitle[MAX_LOADSTRING]; // The title bar text
WCHAR szWindowClass[MAX_LOADSTRING]; // the main window class name
// -- edit
Bitmap* bmap;
even though current GDI documentation says Bitmap is declared in gdiplusheaders.h, if I place
#include <gdiplusheaders.h>
it will show a lot of errors. What finally worked by copying from an example was
#include "framework.h"
#include "WindowsProject1.h"
// -- edit
#include <windows.h>
#include <objidl.h>
#include <gdiplus.h>
using namespace Gdiplus;
#pragma comment (lib,"Gdiplus.lib")
To initialize the bitmap, in the mWinMain function, before the message loop I placed this:
// -- edit
try {
bmap = new Bitmap(L"test.png");
//if (bmap->)
}
catch (int _exc) {
return FALSE;
}
I could not find any information on how to check if the bitmap was loaded correctly or not. The constructor does not throw an exception, and there was no difference whether I copied test.png in the source folder or not. I also could not find a property or a flag showing if the bitmap was able to load correctly in the bitmap object
I copied some lines from the GetPixel example, that is supposed to change pixels in a checker pattern, I was not able to see the patter either, so the bitmap may not render at all
To paint the bitmap, in the paint event I placed this:
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);
// TODO: Add any drawing code that uses hdc here...
Graphics _gr(hWnd);
_gr.DrawImage(bmap, 0, 0);
EndPaint(hWnd, &ps);
}
break;
That's all. If there is a test.png file in the same folder as the program is supposed to create a bitmap from that file and render it, nothing complicated, but is not doing it. The window does not show any bitmap. I placed the file both in the same source folder and in the binary output folder, I tried to run it both ways and it does not show any bitmap. Any pointers?
Thanks
Did you include any code to initialize Gdiplus?
Refer to https://video2.skills-academy.com/en-us/windows/win32/api/gdiplusinit/nf-gdiplusinit-gdiplusstartup
You must initialize GdiPlus and you can test GetLastStatus
Basic sample :
#include <windows.h>
#include <tchar.h>
#include <gdiplus.h>
using namespace Gdiplus;
#pragma comment(lib, "gdiplus.lib")
#pragma comment(linker,"\"/manifestdependency:type='win32' \
name='Microsoft.Windows.Common-Controls' version='6.0.0.0' \
processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
HINSTANCE hInst;
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
int nWidth = 600, nHeight = 400;
Gdiplus::Bitmap* bitmap = NULL;
int APIENTRY wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPWSTR lpCmdLine, _In_ int nCmdShow)
{
GdiplusStartupInput gdiplusStartupInput;
ULONG_PTR gdiplusToken;
GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
hInst = hInstance;
WNDCLASSEX wcex =
{
sizeof(WNDCLASSEX), CS_HREDRAW | CS_VREDRAW, WndProc, 0, 0, hInst, LoadIcon(NULL, IDI_APPLICATION),
LoadCursor(NULL, IDC_ARROW), (HBRUSH)(COLOR_WINDOW + 1), NULL, TEXT("WindowClass"), NULL,
};
if (!RegisterClassEx(&wcex))
return MessageBox(NULL, TEXT("Cannot register class !"), TEXT("Error"), MB_ICONERROR | MB_OK);
int nX = (GetSystemMetrics(SM_CXSCREEN) - nWidth) / 2, nY = (GetSystemMetrics(SM_CYSCREEN) - nHeight) / 2;
HWND hWnd = CreateWindowEx(0, wcex.lpszClassName, TEXT("Test"), WS_OVERLAPPEDWINDOW, nX, nY, nWidth, nHeight, NULL, NULL, hInst, NULL);
if (!hWnd)
return MessageBox(NULL, TEXT("Cannot create window !"), TEXT("Error"), MB_ICONERROR | MB_OK);
ShowWindow(hWnd, SW_SHOWNORMAL);
UpdateWindow(hWnd);
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
GdiplusShutdown(gdiplusToken);
return (int)msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static HWND hWndButton = NULL, hWndStatic = NULL;
int wmId, wmEvent;
switch (message)
{
case WM_CREATE:
{
bitmap = new Gdiplus::Bitmap(L"Hulk.png");
if (bitmap->GetLastStatus() != Ok)
{
delete bitmap;
bitmap = NULL;
}
return 0;
}
break;
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hDC = BeginPaint(hWnd, &ps);
if (bitmap != NULL)
{
Graphics graphics(hDC);
graphics.DrawImage(bitmap, 0, 0);
}
EndPaint(hWnd, &ps);
}
break;
case WM_DESTROY:
{
if (bitmap != NULL)
{
delete bitmap;
bitmap = NULL;
}
PostQuitMessage(0);
return 0;
}
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
thank you both, it seems it had to do with not initializing GDI.
Initially I changed my wWinMain (for default app created by wizard) for this, it still did not work not sure why:
int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPWSTR lpCmdLine,
_In_ int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
// TODO: Place code here.
// Initialize global strings
LoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadStringW(hInstance, IDC_WINDOWSPROJECT1, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance);
// Perform application initialization:
if (!InitInstance(hInstance, nCmdShow))
{
return FALSE;
}
// -- edit
try {
if (GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL) != Ok)
return FALSE;
bmap = new Bitmap(L"test.png"); //if (bmap->)
}
catch (int _exc) {
return FALSE;
}
HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_WINDOWSPROJECT1));
MSG msg;
// Main message loop:
while (GetMessage(&msg, nullptr, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
// -- edit
GdiplusShutdown(gdiplusToken);
return (int)msg.wParam;
}
but then I copied/pasted the example that shows how to start GDI in desktop app, I commented the first line which was giving error and did not add any value
//#include <stdafx.h>
and I edited the on paint handler (is ugly but is a test, is not supposed to look pretty)
VOID OnPaint(HDC hdc)
{
Graphics graphics(hdc);
Pen pen(Color(255, 0, 0, 255));
graphics.DrawLine(&pen, 0, 0, 200, 100);
// --
Bitmap* bmap;
bmap = new Bitmap(L"test.png");
graphics.DrawImage(bmap, 0, 0);
}
and now it works, it does show the bitmap. Thank you
You are missing a call to GdiplusStartup. It is necessary.
GdiplusStartupInput gdiplusStartupInput;
ULONG_PTR gdiplusToken;
GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
No need to be so complicated. Image::FromFile from gdiplus will be easier. https://stackoverflow.com/questions/78143741/winapi-32-and-gdi-move-window-when-draggin-a-png-image-with-some-region-with-tr
Image* image; // Declare the image pointer globally
int imageWidth = 0;
int imageHeight = 0;
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
// Initialize GDI+
GdiplusStartupInput gdiplusStartupInput;
ULONG_PTR gdiplusToken;
GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
// Load the PNG image
image = Image::FromFile(L"C:\\Users\\hacktooth\\Downloads\\bg.png"); // Replace with your image path
if (image) {
imageWidth = image->GetWidth();
imageHeight = image->GetHeight();
...
...
}