Understanding Cartesian Coordinates vs. Window Coordinates in C++
In this tutorial, we explore C++ graphics programming by showing how to draw a Cartesian plane and plot points. Since the coordinate system in C++ has its origin at the top-left corner, the y-axis grows downward, which is different from the mathematical convention. We'll walk through drawing in a window frame using device context (DC) and functions such as BeginPaint and EndPaint.
The Cartesian Plane is the standard graph surface we are taught in school. It has two axes: the x-axis (horizontal) and the y-axis (vertical), where the y-values increase upwards. In contrast, when working with a C++ window frame, the coordinate system is slightly different:
- The x-axis increases from left to right, just like in math.
 - The y-axis starts at the top of the screen and increases downward.
 
                        In C++, the Window Frame would represent something like a graph book; and this graph book
 is plotted
                        or drawn on using code.
                    
Drawing on the C++ Window Frame
In C++ programming, the window frame can be thought of as a “graph book.” Just like plotting on graph paper, we use code to draw and represent data structures on this frame.
                        In C++, drawing is done on a window frame   
                        - actually, drawing is done on some sort of graphic context beforehand, then transferred to the screen.
                        To plot graphs in C++, we often use Win32 GDI functions such as 'BeginPaint', 'EndPaint', 'GetDC', and 'ReleaseDC'. 
                        These allow us to draw lines, points, and shapes on the window client area.
                        
                        Remember, there is a subtle difference between the way we use graphs naturally and the C++ graphic context (window frame):
                        
                            The y-axis of the C++ window frame is measured from the top and increases as you move downwards.
                        
                    
                        Create a new C++ project;
                        call it Dymetric.
                        Type out the adjoining C++ code to see what the Window Frame feels like.
                    
Note: This block shows how you can draw directly onto the C++ window frame. More advanced graph implementations can use this foundation to represent nodes, edges, adjacency lists, and adjacency matrices.
                        Note: The bulk of the adjoining code is automatically generated by the Visual Studio IDE, all you just have to do is
                        to fill in what we have added to generated code.
                        
                        To help make the filling in easier, and harder to miss any added code,
                        we have marked out all the code parts we added with the delimiters (separators)
                        
                            /*PoI* ____________________________________ *PoI*/
                                           .
                                           .
                            /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
                        
                        
                        (We've used PoI to mean Point of Interest here.)
                    
What You've Learnt on Graphs and C++ Window Frame
Graphs are one of the most important data structures in C++. They are widely used in mathematics, computer science, and real-world applications such as navigation systems, social networks, and data analysis. In this tutorial, we've explored how graphs are represented in C++, how the Cartesian plane relates to the C++ window frame, and provide example code for drawing simple graphics.
Key Takeaway on Graphs and C++ Window Frame
Graphs play a key role in C++ data structures and algorithms. Understanding how to work with them - both as mathematical models and as graphics on a C++ window frame-is essential for senior secondary students and aspiring developers.
By practicing with C++ graph implementations such as adjacency lists, adjacency matrices, and traversal algorithms, you'll build a strong foundation in both programming and applied mathematics.
C++ Graph Code for Window Display - Header File
#include "resource.h"
C++ Graph Code for Window Display - Window Display
#include "Dymetric.h"
#define MAX_LOADSTRING 100
// Global Variables:
HINSTANCE hInst; // current instance
WCHAR szTitle[MAX_LOADSTRING]; // The title bar text
WCHAR szWindowClass[MAX_LOADSTRING]; // the main window class name
// Forward declarations of functions included in this code module:
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM);
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_DYMETRIC, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance);
// Perform application initialization:
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}
HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_DYMETRIC));
MSG msg;
// Main message loop:
while (GetMessage(&msg, nullptr, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return (int) msg.wParam;
}
//
// FUNCTION: MyRegisterClass()
//
// PURPOSE: Registers the window class.
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEXW wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_DYMETRIC));
wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = MAKEINTRESOURCEW(IDC_DYMETRIC);
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
return RegisterClassExW(&wcex);
}
//
// FUNCTION: InitInstance(HINSTANCE, int)
//
// PURPOSE: Saves instance handle and creates main window
//
// COMMENTS:
//
// In this function, we save the instance handle in a global variable and
// create and display the main program window.
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
hInst = hInstance; // Store instance handle in our global variable
HWND hWnd = CreateWindowW(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr, nullptr, hInstance, nullptr);
if (!hWnd)
{
return FALSE;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;
}
//
// FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM)
//
// PURPOSE: Processes messages for the main window.
//
// WM_COMMAND - process the application menu
// WM_PAINT - Paint the main window
// WM_DESTROY - post a quit message and return
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_COMMAND:
{
int wmId = LOWORD(wParam);
// Parse the menu selections:
switch (wmId)
{
case IDM_ABOUT:
DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
}
break;
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);
/*PoI* _________________________________________________________________ *PoI*/
FillRect(*hdc, &(ps->rcPaint), (HBRUSH)CreateSolidBrush(RGB(255, 0, 0)));
/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
EndPaint(hWnd, &ps);
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
// Message handler for about box.
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
UNREFERENCED_PARAMETER(lParam);
switch (message)
{
case WM_INITDIALOG:
return (INT_PTR)TRUE;
case WM_COMMAND:
if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
{
EndDialog(hDlg, LOWORD(wParam));
return (INT_PTR)TRUE;
}
break;
}
return (INT_PTR)FALSE;
}
C++ Drawing Tutorial Reference
                        For a thorough explanation of drawing graphics
                        in C++, please see the following link:
                        
                            Microsoft .Net Graphics Operations - Learning to Draw Basic Graphics in C++
                        
                             - largely apt for C++ beginners.