I'm trying to draw a line with gdi+ by clicking button using WM_COMMAND
, but the line doesn't show up when I click the button. It works when I use WM_PAINT
though but I need it to show up when clicking the button.
#include <Windows.h>
#include <gdiplus.h>
#pragma comment(lib, "gdiplus.lib")
#define onButtonClicked 1
using namespace Gdiplus;
WNDCLASS NewWindowClass(HBRUSH BGColor, HCURSOR Cursor, HINSTANCE hInt, HICON Icon, LPCWSTR Name, WNDPROC Procedure);
LRESULT CALLBACK mainProcedure(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp);
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR args, int ncmdshow) {
GdiplusStartupInput gdiplusStartupInput;
ULONG_PTR gdiplusToken;
GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, nullptr);
WNDCLASS mainClass = NewWindowClass((HBRUSH)COLOR_WINDOW, LoadCursor(NULL, IDC_ARROW), hInst, LoadIcon(NULL, IDI_APPLICATION), L"Window", mainProcedure);
if (!RegisterClassW(&mainClass)) return -1;
MSG mainMessage = { 0 };
CreateWindow(L"Main", L"Main window", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 500, 500, 500, 400, NULL, NULL, NULL, NULL);
while (GetMessage(&mainMessage, NULL, NULL, NULL)) {
TranslateMessage(&mainMessage);
DispatchMessage(&mainMessage);
}
GdiplusShutdown(gdiplusToken);
return 0;
}
WNDCLASS NewWindowClass(HBRUSH BGColor, HCURSOR Cursor, HINSTANCE hInt, HICON Icon, LPCWSTR Name, WNDPROC Procedure) {
WNDCLASS NWC = { 0 };
NWC.hbrBackground = BGColor;
NWC.hCursor = Cursor;
NWC.hInstance = hInt;
NWC.hIcon = Icon;
NWC.lpszClassName = Name;
NWC.lpfnWndProc = Procedure;
return NWC;
}
LRESULT CALLBACK mainProcedure(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) {
HDC hdc;
PAINTSTRUCT ps;
switch (msg) {
case WM_CREATE:
CreateWindowA("button", "Draw", WS_VISIBLE | WS_CHILD, 10, 10, 50, 20, hWnd, (HMENU)onButtonClicked, NULL, NULL);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_COMMAND:
switch (wp) {
case onButtonClicked:
hdc = BeginPaint(hWnd, &ps);
Graphics gf(hdc);
Pen pen(Color(0, 0, 0));
gf.DrawLine(&pen, 10, 160, 50, 200);
EndPaint(hWnd, &ps);
break;
}
break;
default:
return DefWindowProc(hWnd, msg, wp, lp);
}
}
Is it possible to use gdi+ functions in WM_COMMAND
? If not, what should I use instead?
In WM_COMMAND
, you need to save your desired drawing info (ie, the coordinates to draw from/to) and then call InvalidateRect()
to trigger a new WM_PAINT
, where you then use the saved info to do the actual drawing.
Do not call InvalidateRect()
in WM_PAINT
, as you will cause an infinite paint loop.
Try something like this:
bool doDrawLine = false;
Point lineStart, lineEnd;
...
LRESULT CALLBACK mainProcedure(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) {
switch (msg) {
...
case WM_COMMAND: {
switch (wp) {
case onButtonClicked: {
lineStart = Point(10, 160);
lineEnd = Point(50, 200);
doDrawLine = true;
InvalidateRect(hWnd, NULL, TRUE);
break;
}
}
break;
}
case WM_PAINT: {
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);
if (doDrawLine) {
Graphics gf(hdc);
Pen pen(Color(0, 0, 0));
gf.DrawLine(&pen, lineStart, lineEnd);
}
EndPaint(hWnd, &ps);
break;
}
...
}
}