user655261
user655261

Reputation: 99

Displaying image in MFC method that is not ONPaint

I am trying to display an image in a dialog dynamically, it works no problem if I put the code in the on paint method and use the dc from there, I can't do this though I need to display after the window is shown, the code I am using is as follows, I am getting the dc of the client window creating the bitmap from a resource and "trying" to display it in the window but nothing displays, Any suggestions what might be wrong?

void CProcessSteps::OnShowWindow(BOOL bShow, UINT nStatus) 
{
    CDialog::OnShowWindow(bShow, nStatus);  

    SetupInstructions();<-----------------Call To Method
}




void CProcessSteps::OnPaint() 
{   
    CPaintDC dc(this);
}

void CProcessSteps::SetupInstructions()
{
    CDC *pDC = new CDC();<------------------------------Problem starts here
    CFontUtil cfu;
    cfu.SetFont(&LineFont,30);

    CDC memDC;
    memDC.CreateCompatibleDC(pDC);

    int stepTop = 10;
    int stepEnd = 230;
    int imageLeft = 30;
    STEP_STRUCT* step;

    CBitmap iconImage;
    iconImage.LoadBitmap ( IDB_TID_CHECK );

    memDC.SelectObject(&iconImage);

    CRect iconRect;
    BITMAP bmInfo;
    iconImage.GetObject ( sizeof ( bmInfo ), &bmInfo );
    iconRect.SetRect ( imageLeft, stepTop, imageLeft+bmInfo.bmWidth, stepTop+bmInfo.bmHeight );

    pDC = this->GetDC();
    pDC->BitBlt(imageLeft, stepTop, imageLeft+bmInfo.bmWidth, stepTop+bmInfo.bmHeight, &memDC, 0, 0, SRCCOPY);

    //RedrawWindow();<-------- tried this here no luck

    int stepCount = m_pageStructure->PageSteps.GetCount();<----------------------------Bellow this works correctly

    POSITION pos = m_pageStructure->PageSteps.GetHeadPosition();
    while (pos)
    {
        step = m_pageStructure->PageSteps.GetNext(pos);

        CStatic *label = new CStatic;
        label->Create(_T( step->StepInstruction ),WS_CHILD | WS_VISIBLE, CRect(80, stepTop, 480, stepEnd), this);
        label->SetFont(&LineFont, true);


        label->GetWindowRect(rect);
        ScreenToClient(rect);

        pDC = label->GetDC();
        pDC->SelectObject(&LineFont);
        pDC->DrawText(step->StepInstruction, &rect, DT_CALCRECT|DT_WORDBREAK); 
        label->ReleaseDC(pDC);
        label->MoveWindow(rect);    

        stepTop += rect.Height();
        stepTop += 30;
        stepEnd += rect.Height();
    }
}

Upvotes: 0

Views: 2707

Answers (3)

Javier De Pedro
Javier De Pedro

Reputation: 2239

I suppose CProcessSteps derives from CWnd, perhaps a CDialog?

If you want to draw in the client area of a CWnd derived class you have to get the DC using the CWnd GetDC method. I don't understand why you create your own CDC, you should get the CWnd DC at the beginning of SetupInstructions and use this DC everywhere, also to create your memDC.

Also you should be careful when you allocate memory (new CStatic) if you don't call delete for this variables you will have memory leaks. If you really need to create this CStatics dynamically you will have to keep a pointer to all of them in order to delete them before closing the dialog/view.

As people suggested, I don't think you are following the right way by drawing using OnShowWindow. You should use OnPaint to make your drawing stuff, if you don't want to draw the image until the window is fully initialized you should use a member variable of the window (for instance a bool) initialized to false in the constructor and set it to true when you are ready to draw the image. Then calling Invalidate will draw the image. Something like:

In the .h:

class CProcessSteps : CDialog
{
   ...

private:
   bool m_bReadyToDraw;
}; 

In the .cpp:

CProcessSteps::CProcessSteps() : CDialog()
{ 
   m_bReadyToDraw = false;
}

BOOL CProcessSteps::OnInitDialog() 
{
   CDialog:OnInitDialog();

   m_bReadyToDraw = true;

   return TRUE;
}
void CProcessSteps::OnPaint() 
{   
    CPaintDC dc(this);

    if(m_bReadyToDraw)
    {
       CFontUtil cfu;
       cfu.SetFont(&LineFont,30);

       CDC memDC;
       memDC.CreateCompatibleDC(&dc);        

       ...

    }
}

Hope it helps.

Javier

Upvotes: 0

Eric Decker
Eric Decker

Reputation: 42

I think there's more in the BeginPaint-function than just giving you the CDC. And BeginPaint can only be called from the OnPaint-method.

To solve your problem, use the Invalidate-functions to force a repaint from your "SetupInstructions" method. Then do the drawing inside the OnPaint function.

Upvotes: 1

Serge Wautier
Serge Wautier

Reputation: 21878

Reasons why you can't use OnPaint() are not clear.

The usual strategy when one needs to redraw all or part of a window upon some event is to call InvalidateRect().

Windows will in turn send WM_PAINT (handled by your OnPaint() method) to your app, specifying which part of the window should be redrawn.

Upvotes: 2

Related Questions