CreatePen returning NULL on window resizing

1

So I am experimenting with Win32 API and trying to plot a line with colour gradient (by creating a custom Pen). The code is working fine and I am getting my desired result but when I start resizing my window, CreatePen() function starts giving NULL value, and thus Windows start using the default black pen.

This is my WndProc code:

(https://pastebin.com/xiyzX5fu for full code)

LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    static int cxClient, cyClient;
    HDC hdc;
    HPEN hPen;
    PAINTSTRUCT ps;
    switch (message)
    {
    case WM_SIZE:
        cxClient = LOWORD(lParam);
        cyClient = HIWORD(lParam);
        return 0;
 
    case WM_PAINT:
        printf("%d\t%d\n", cxClient, cyClient); //Printing the resolution
        hdc = BeginPaint(hwnd, &ps);
        MoveToEx(hdc, 0, cyClient / 2, NULL);
        int count = 0;
 
        //Plotting 256 lines each of length (cxClient/256) with different color
        for (int i = 0; i < cxClient; i += cxClient / 256)
        {
            if ((hPen = CreatePen(PS_SOLID, 10, RGB(count, 255, 255))) == NULL)
            {
                DWORD lasterror;
                lasterror = GetLastError();
                printf("We got a NULL Value and last error code was %lu\n", lasterror);
                break;
            }
            else
                SelectObject(hdc, hPen);
 
            count += 1; // For uniform color gradient across width
            LineTo(hdc, i, cyClient / 2);
        }
        DeleteObject(hPen);
        EndPaint(hwnd, &ps);
        return 0;
 
    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
    }
    return DefWindowProc(hwnd, message, wParam, lParam);
}

I am trying to debug it for the last few hours and here are some of my observations:

  • My calculation for RGB are correct. In fact, even a default pen CreatePen(PS_SOLID, 1, 0x00000000) leads to same error.
  • The error is more profound if the increment value is smaller, i.e. for i += cxClient/5 (plots only 5 lines) CreatePen would return NULL values much less often while resizing as compared to i += cxClient/256 (plots 256 lines) (Line 59)
  • Interesting One: I print the size of my Client Area using printf (Line 53). The moment CreatePen() returns a NULL value, the console will stop printing the statement containing the Client Area and will only print the NULL error statement (Line 65) again and again. It will print both only when I add a break (Line 66) after printing the NULL error statement.
  • I think I am not able to capture the error of CreatePen() using GetlastError() (Line 64) correctly because it always prints 0 (ERROR_SUCCESS) on the console.

Based on these observations I think the problem doesn't lie in CreatePen() but in my way of calculating the length of each line.

c
windows
winapi
asked on Stack Overflow Sep 29, 2020 by ImperfeKt

2 Answers

1

You are creating the pen, selecting it into the dc, and then deleting it while it is still selected in the dc. This will case DeleteObject to fail. You need to remember the old pen that was selected, and then select that back into the dc before deleting your pen:

HPEN oldPen;
...
oldPen = SelectObject(hdc, hPen);
...
SelectObject(hdc, oldPen);
DeleteObject(hPen);
answered on Stack Overflow Sep 29, 2020 by psmears
0

Yes, you are leaking GDI object. When the number of GDI objects in your process reaches 10,000, the system will no longer allow the creation of new GDI objects. This is why hPen will eventually return NULL.

Furthermore, as we saw last time, the maximum number of window manager objects that can be created is around 32,700. Giving a program 10,000 is already a third of the total amount available. That’s already pretty darned generous, if you ask me. Preventing a program from running away and consuming all of the window manager objects is an attempt to contain the damage caused by a runaway program. Even if a program goes haywire, there’s still around 20,000 objects available for the other programs to use.

Refer: Why is the limit of window handles per process 10,000?

answered on Stack Overflow Sep 29, 2020 by Strive Sun - MSFT • edited Sep 29, 2020 by Strive Sun - MSFT

User contributions licensed under CC BY-SA 3.0