See the question and my original answer on StackOverflow

The first thing to do is process WM_PAINT like instructed in the official documentation and in this Direct2D tutorial Drawing with Direct2D, ie: you need to tell Windows you have handled the WM_PAINT message.

So you code should instead be like this:

case WM_PAINT:
{
    // ==> I will handle WM_PAINT
    PAINTSTRUCT ps;
    HDC hdc = BeginPaint(hwnd, &ps);
    
    // Bind the DC render target to the HDC
    RECT rc;
    GetClientRect(hwnd, &rc);

    pDCRenderTarget->BindDC(hdc, &rc);

    // Create a compatible bitmap render target
    pDCRenderTarget->CreateCompatibleRenderTarget(&pBitmapRenderTarget);

    ...

    pBitmapRenderTarget->Release();
    pBitmapRenderTarget = nullptr;

    // ==> now, I have handled WM_PAINT
    EndPaint(hwnd, &ps);
    break;

If you don't do this, Windows will continue sending WM_PAINT messages continuously and this will eat your machine's resource (not really the WM_PAINT itself, but your code in there).

Then, depending on your goals, you also maybe keep the pBitmapRenderTarget instead of creating it each time you handle WM_PAINT, it really depends what you plan to do when you "paint" in the general sense (real time updates, seldom changes, etc.)

Note with Direct2D (and Direct3D, etc.) another way to do this is to just do BeginPaint+EndPaint once in WM_PAINT and do the rendering elsewhere, for example: https://gamedev.stackexchange.com/questions/12901/wm-paint-and-direct3d