Article by Ayman Alheraki in October 23 2024 01:45 AM
In C++, the standard library does not provide built-in functions for drawing or loading images, especially in Windows programs. However, you can use WinAPI (Windows API) to program graphics and display them on the screen without the need for any external libraries.
Here’s the basic method for using WinAPI to draw on a window in a C++ program:
Using CLion + mingw64 GCC for windows OS compiler Start by creating a window using Windows API by calling the functions designed for window creation.
LRESULT CALLBACK WindowProcedure(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) {
switch (msg) {
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd, msg, wp, lp);
}
return 0;
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
WNDCLASS wc = {0};
wc.hbrBackground = (HBRUSH)COLOR_WINDOW;
wc.hInstance = hInstance;
wc.lpszClassName = L"myWindowClass";
wc.lpfnWndProc = WindowProcedure;
if (!RegisterClass(&wc)) {
return -1;
}
HWND hwnd = CreateWindow(wc.lpszClassName, L"My Window", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
100, 100, 500, 500, NULL, NULL, hInstance, NULL);
MSG msg = {0};
while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
To add graphics to the window, we use the WM_PAINT
message, which is triggered whenever the system needs to repaint the window. Functions like Rectangle
and Ellipse
can be used for drawing.
Here’s how to draw a rectangle and a circle:
LRESULT CALLBACK WindowProcedure(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) {
switch (msg) {
case WM_PAINT: {
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
// Draw a rectangle
Rectangle(hdc, 50, 50, 200, 200);
// Draw a circle (ellipse inside a rectangle)
Ellipse(hdc, 250, 50, 400, 200);
EndPaint(hwnd, &ps);
break;
}
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd, msg, wp, lp);
}
return 0;
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
WNDCLASS wc = {0};
wc.hbrBackground = (HBRUSH)COLOR_WINDOW;
wc.hInstance = hInstance;
wc.lpszClassName = L"myWindowClass";
wc.lpfnWndProc = WindowProcedure;
if (!RegisterClass(&wc)) {
return -1;
}
HWND hwnd = CreateWindow(wc.lpszClassName, L"My Window", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
100, 100, 500, 500, NULL, NULL, hInstance, NULL);
MSG msg = {0};
while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
WindowProcedure
: This is the function that handles events (such as painting or closing the window). In this case, we handle the WM_PAINT
event to draw on the window using the HDC
(device context).
BeginPaint
and EndPaint
: These are used to define the drawing area and then complete the drawing process when finished.
Rectangle
and Ellipse
: These are WinAPI functions to draw basic shapes (a rectangle and a circle).
No External Libraries: We are using built-in WinAPI functions without the need for third-party libraries.
Full Control: You have direct control over how shapes are drawn to the screen.
Higher Complexity: Working with WinAPI requires a deeper understanding of the operating system, which makes programming more complex compared to using external libraries like SDL or SFML.
Maintenance: Code that uses WinAPI for drawing can be more difficult to maintain and extend compared to more modern solutions.
If you're looking to implement basic graphics in a Windows environment without relying on external libraries, using WinAPI is an effective solution.