I am trying to create a program with the Win32 api in c to draw triangles. I am at the point where I have gotten bresenham's algorithm to work but for some reason whenever I try to draw more than one line it will only draw the first one. the code is split into three parts, the algorithm, the triangle function, and WinMain.
DrawLine:
void DrawLine(HWND hwnd, int x0, int y0, int x1, int y1) {
//sets up "SetPixel"
PAINTSTRUCT ps;
RECT r;
GetClientRect(hwnd, &r);
if (r.bottom == 0) {
return;
}
HDC hdc = BeginPaint(hwnd, &ps);
//This is where the algorithm begins
int d,dx,dy,x,y,yi;
dx = x1-x0;
dy = y1-y0;
yi = 1;
//Checks if we need to increase or decrease y
if(dy < 0){
yi = -yi;
dy = -dy;
}
d = (2*dy)-dx;
x = x0;
y = y0;
for(int i = 0;i <= dx;i ){
SetPixel(hdc,x,y,RGB(0,0,0));
if(d > 0){
y = yi;
d = 2*(dy-dx);
} else {
d = 2*dy;
}
x ;
}
}
DrawTriangle:
void DrawTriangle(HWND hwnd, int x0, int y0, int x1, int y1, int x2, int y2){
DrawLine(hwnd, x0, y0, x1, y1);
DrawLine(hwnd, x1, y1, x2, y2);
DrawLine(hwnd, x2, y2, x0, y0);
}
WinMain:
#include <windows.h>
void DrawLine(HWND hwnd, int x0, int y0, int x1, int y1);
void DrawTriangle(HWND hwnd, int x0, int y0, int x1, int y1, int x2, int y2);
using namespace std;
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
int WINAPI
WinMain (HINSTANCE hInstance, HINSTANCE hPrevInst, LPTSTR lpCmdLine, int nShowCmd) {
MSG msg;
WNDCLASSW wc = {0};
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpszClassName = L"Pixels";
wc.hInstance = hInstance;
wc.hbrBackground = GetSysColorBrush(COLOR_3DFACE);
wc.lpfnWndProc = WndProc;
wc.hCursor = LoadCursor(0, IDC_ARROW);
RegisterClassW(&wc);
CreateWindowW(wc.lpszClassName, L"Pixels",
WS_OVERLAPPEDWINDOW | WS_VISIBLE,
100, 100, 300, 250, NULL, NULL, hInstance, NULL);
while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (int) msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg,
WPARAM wParam, LPARAM lParam) {
switch(msg) {
case WM_PAINT:
DrawTriangle(hwnd, 40, 30, 60, 20, 100, 80);
break;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProcW(hwnd, msg, wParam, lParam);
}
CodePudding user response:
Your DrawTriangle()
/DrawLine()
functions are taking in an HWND
as input when they should be taking in an HDC
instead. Every call to DrawLine()
is calling BeginPaint()
(but not EndPaint()
!) to obtain a new HDC
from the HWND
, which can trigger the HWND
to immediately repaint over any existing content before allowing you to then paint new stuff onto the HDC
.
You need to move BeginPaint()
into your WM_PAINT
handler, and then pass the resulting HDC
to DrawTriangle()
, eg:
void DrawLine(HDC hdc, int x0, int y0, int x1, int y1) {
//This is where the algorithm begins
int d,dx,dy,x,y,yi;
dx = x1-x0;
dy = y1-y0;
yi = 1;
//Checks if we need to increase or decrease y
if(dy < 0){
yi = -yi;
dy = -dy;
}
d = (2*dy)-dx;
x = x0;
y = y0;
for(int i = 0;i <= dx;i ){
SetPixel(hdc,x,y,RGB(0,0,0));
if(d > 0){
y = yi;
d = 2*(dy-dx);
} else {
d = 2*dy;
}
x ;
}
}
void DrawTriangle(HDC hdc, int x0, int y0, int x1, int y1, int x2, int y2){
DrawLine(hdc, x0, y0, x1, y1);
DrawLine(hdc, x1, y1, x2, y2);
DrawLine(hdc, x2, y2, x0, y0);
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
switch(msg) {
case WM_PAINT: {
PAINTSTRUCT ps;
BeginPaint(hwnd, &ps);
RECT r;
GetClientRect(hwnd, &r);
if (r.bottom != 0)
DrawTriangle(ps.hdc, 40, 30, 60, 20, 100, 80);
EndPaint(hwnd, &ps);
break;
}
...
}
...
}