1

Attempting to create a basic drawing program using C and GDI in the Windows API. The idea is that the user clicks and drags to create a rectangle or any other shape that is selected. The size is specified by where the user clicks down and releases (just like any drawing program). I'm having an issue where the first shape that the user draws will be painted to the screen, however anything successive is not. I initially was not drawing the shapes in WM_PAINT, but I read on another thread that I need to do that, so I created a struct to store information about objects that have been painted and those are drawn each time the WM_PAINT message is received.

Here's my code for WM_PAINT

case WM_PAINT:
{
    for (int i = 0; i < drawingcount; i++)
    {

        PAINTSTRUCT ps;
        HDC hdc = BeginPaint(hwnd, &ps);
        HPEN hMyPen = CreatePen(mydrawings[i].style, mydrawings[i].thick, RGB(0,255,0));
        HPEN hOldPen = SelectObject(hdc, hMyPen);

        if (mydrawings[i].shape == RECTANGLE)
        {
            Rectangle(hdc, mydrawings[i].start_x, mydrawings[i].start_y, mydrawings[i].end_x, mydrawings[i].end_y);
        }
        else if (mydrawings[i].shape == ELLIPSE)
        {
            Ellipse(hdc, mydrawings[i].start_x, mydrawings[i].start_y, mydrawings[i].end_x, mydrawings[i].end_y);
        }
        else if (mydrawings[i].shape == LINE)
        {
            MoveToEx(hdc, mydrawings[i].start_x, mydrawings[i].start_y, 0);
            LineTo(hdc, mydrawings[i].end_x, mydrawings[i].end_y);
        }
        SelectObject(hdc, hOldPen);
        DeleteObject(hMyPen);
        //DeleteObject(hOldPen);
        EndPaint(hwnd, &ps);
    }
}
break;

And here for WM_LBUTTONUP (once user finishes drawing their shape)

case WM_LBUTTONUP:
{
    yendclick = GET_Y_LPARAM(lParam);
    xendclick = GET_X_LPARAM(lParam);
    mydrawings[drawingcount].shape = selected_shape;
    mydrawings[drawingcount].start_x = xclick;
    mydrawings[drawingcount].start_y = yclick;
    mydrawings[drawingcount].end_x = xendclick;
    mydrawings[drawingcount].end_y = yendclick;
    mydrawings[drawingcount].thick = thickness;
    mydrawings[drawingcount].style = style;
    drawingcount++;
    SendMessage(hwnd, WM_PAINT, wParam, lParam);
}

Struct and enum declarations:

typedef enum myshape
{
    RECTANGLE,
    ELLIPSE,
    LINE,
    MAX_SHAPE
} shape;
typedef struct drawing
{
    int start_x;
    int start_y;
    int end_x;
    int end_y;
    int thick;
    int style;
    shape shape;
} drawings;

Would very much appreciate any guidance with this!

Swemoph
  • 326
  • 4
  • 12
  • Is there a `break` after the brace for the `case WM_LBUTTONUP`, and are there further cases? – unwind Jun 02 '16 at 09:56
  • Yep there is a `break` sorry I omitted it in the post. There are cases after this one, but I have them all terminated with `break` to prevent fall through. – Swemoph Jun 02 '16 at 10:01
  • 1
    I'm no Win32 expert but it would make way more sense to change the final three calls to `EndPaint(); SelectObject(); DeleteObject();`, it seems the current order deletes things when they are in use. – unwind Jun 02 '16 at 10:13
  • Thanks for the suggestion! I actually just got it working now by moving the `HDC hdc = BeginPaint(hwnd, &ps)` and `EndPaint(hwnd, &ps)` out of the for loop - the for loop is happening inside the drawing now instead of restarting it each time. – Swemoph Jun 02 '16 at 10:29

1 Answers1

2

Don't use PostMessage WM_PAINT, use InvalidateRect and perhaps UpdateWindow instead. See also here: why not to send WM_PAINT manually

Community
  • 1
  • 1
Ton Plooij
  • 2,583
  • 12
  • 15
  • Thank you for the response! I've replaced my `SendMessage` with `InvalidateRect` but am still facing the same issue sadly. I've also tried adding `UpdateWindow(hwnd)`. – Swemoph Jun 02 '16 at 09:41
  • @Swemoph the problem is probably in your logic. hard to tell what's going on with that little code you show. – Jabberwocky Jun 02 '16 at 11:45