Relationship between AFX_WM_DRAW2D and WM_PAINT in MFC Application

1.2k views Asked by At

What is the relationship between the two messages in the subject? When exactly the AFX_WM_DRAW2D is passed to application queue.

I am asking because I have encountered the strangest recursive call of AFX_WM_DRAW2D handler. Whenever I am trying to paint something inside the AFX_WM_DRAW2Din compatibe render target the handler is somehow called recursively which I have difficulty to explain. The structure of MFC application is like that:-

BEGIN_MESSAGE_MAP(CTACSIView, CView)
    // Standard printing commands
    ...
    ON_REGISTERED_MESSAGE(AFX_WM_DRAW2D, &CTACSIView::OnDraw2D)
END_MESSAGE_MAP()


afx_msg LRESULT CTACSIView::OnDraw2D(WPARAM wParam, LPARAM lParam)
{

    CHwndRenderTarget* pRenderTarget = (CHwndRenderTarget*)lParam;
    ASSERT_VALID(pRenderTarget);


    CRect clientRect;
    GetClientRect(clientRect);

    if (m_BackGroundHasChanged)
    {


        CBitmapRenderTarget compatibleRenderTarget;
        pRenderTarget->CreateCompatibleRenderTarget(compatibleRenderTarget, m_viewScreenSize);

        compatibleRenderTarget.BeginDraw();


        // 
        // ----> HERE THE RECURSIVE CALL OCCURS <----
        //
            D2D1::Matrix3x2F shiftRightTranslation = D2D1::Matrix3x2F::Translation(D2D1::SizeF(TACSI_VIEW_BATTLE_FIELD_OFFSET_X, 0));
    m_pRulerBitmapBrush_X.SetTransform(&shiftRightTranslation);

    compatibleRenderTarget.FillRectangle(rulerRectangle_X, &m_pRulerBitmapBrush_X);
1

There are 1 answers

3
23W On BEST ANSWER

MFC internally to process WM_PAINT message (look at CWnd::OnWndMsg source) and try to do D2D paint (call protected CWnd::DoD2DPaint() method). This method checks if D2D enabled for window (method CWnd::EnableD2DSupport) and send internal MFC message AFX_WM_DRAW2D for this window.

Thus if you process AFX_WM_DRAW2D in your code then CWnd::DoD2DPaint() returns TRUE and further processing WM_PAINT is blocked. If AFX_WM_DRAW2D is not processed or D2D is not supported by OS or not enabled then standard WM_PAIT algorithm is working.

P.S.: MFC 12 contains only D2D 1.0 support, not D2D 1.1 or D2D 1.2! Because D2D 1.x requires full Direct3D initialization as underground level for D2D, thus it's very hard to write universal code in MFC for them.

P.P.S.: If your APP performs printing throw MFC then viewer OnDraw method will be called. This is because D2D renders are not support drawing to the printer context. Any D2D application that prints must realize two method: OnDraw() for printing and old OS (where D2D is not supported) and AFX_WM_DRAW2D handling for draw on screen.