Home > database >  Win32 wont let me draw multiple lines
Win32 wont let me draw multiple lines

Time:12-13

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;
        }
    
        ...
    }

    ...
}
  • Related