Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
CODE PROJECT For Those Who Code
  • Home
  • Articles
  • FAQ
Community
  1. Home
  2. General Programming
  3. C / C++ / MFC
  4. MFC CreateCompatibleDC(), Drawtext() no display [Solved]

MFC CreateCompatibleDC(), Drawtext() no display [Solved]

Scheduled Pinned Locked Moved C / C++ / MFC
c++help
15 Posts 3 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • E econy

    In OnTimer, I write a test program. if I don't use CreateCompatibleDC(), It works well, otherwise, no display. Please help me to find the reason.

    void CDynamicShowTextDlg::OnTimer(UINT nIDEvent)
    {
    CDC *pDC;
    CRect tRect;
    CDC MemDC;

    pDC = this->GetDC();	
    GetClientRect(&tRect);
    MemDC.CreateCompatibleDC(NULL); 
    MemDC.SetBkMode(TRANSPARENT);
    if (test == 0 ){
    MemDC.SetTextColor(RGB(255,255,255));
    MemDC.DrawText(\_T("My Test"),&tRect,DT\_CENTER|DT\_VCENTER|DT\_SINGLELINE);
    MemDC.SetTextColor(RGB(255,0,0));
    MemDC.DrawText(\_T("TEST"),&tRect,DT\_CENTER|DT\_VCENTER|DT\_SINGLELINE);
    
    //pDC->SetTextColor(RGB(255,255,255));
    //pDC->DrawText(\_T("My Test"),&tRect,DT\_CENTER|DT\_VCENTER|DT\_SINGLELINE);
    //pDC->SetTextColor(RGB(255,0,0));
    //pDC->DrawText(\_T("TEST"),&tRect,DT\_CENTER|DT\_VCENTER|DT\_SINGLELINE);
    }
    else  {
    MemDC.SetTextColor(RGB(255,255,255));
    MemDC.DrawText(\_T("TEST"),&tRect,DT\_CENTER|DT\_VCENTER|DT\_SINGLELINE);
    MemDC.SetTextColor(RGB(0,150,0));
    MemDC.DrawText(\_T("My Test"),&tRect,DT\_CENTER|DT\_VCENTER|DT\_SINGLELINE);
    
    //pDC->SetTextColor(RGB(255,255,255));
       //pDC->DrawText(\_T("TEST"),&tRect,DT\_CENTER|DT\_VCENTER|DT\_SINGLELINE);
    //pDC->SetTextColor(RGB(0,150,0));
    //pDC->DrawText(\_T("My Test"),&tRect,DT\_CENTER|DT\_VCENTER|DT\_SINGLELINE);
    }
    
    m\_Seconds++;
    m\_TimerEcho.Format(\_T("%d: Seconds have passed"), m\_Seconds); 
    test ^= 1;
    

    MemDC.DeleteDC();
    ReleaseDC(pDC);
    UpdateData(FALSE);
    }

    with pDC, it works well.

    C Offline
    C Offline
    Chris Losinger
    wrote on last edited by
    #4

    you need to create a bitmap for your memdc to draw on. see MSDN dox for CDC::CreateCompatibleDC: http://msdn.microsoft.com/en-us/library/kwxzck32.aspx[^] from the dox:

    When a memory device context is created, GDI automatically selects a 1-by-1 monochrome stock bitmap for it. GDI output functions can be used with a memory device context only if a bitmap has been created and selected into that context.

    image processing toolkits | batch image processing

    E 1 Reply Last reply
    0
    • C Chris Losinger

      you need to create a bitmap for your memdc to draw on. see MSDN dox for CDC::CreateCompatibleDC: http://msdn.microsoft.com/en-us/library/kwxzck32.aspx[^] from the dox:

      When a memory device context is created, GDI automatically selects a 1-by-1 monochrome stock bitmap for it. GDI output functions can be used with a memory device context only if a bitmap has been created and selected into that context.

      image processing toolkits | batch image processing

      E Offline
      E Offline
      econy
      wrote on last edited by
      #5

      Thanks, now the test string appeared. But, the client area is black, and show text string in while color only, no change. Please refer to the code:

      void CDrawTextTstDlg::OnTimer(UINT_PTR nIDEvent)
      {
      CDC *pDC;
      CRect tRect;
      CDC MemDC;

      pDC = this->GetDC();
      GetClientRect(&tRect);
      MemDC.CreateCompatibleDC(NULL);

      CBitmap bmp;
      bmp.CreateCompatibleBitmap(&MemDC, tRect.Width(), tRect.Height());
      CBitmap *oldBitmap = MemDC.SelectObject(&bmp);
      MemDC.SetBkMode(TRANSPARENT);

      if (gtest == 0 ){
      MemDC.SetTextColor(RGB(255,255,255));
      MemDC.DrawText(_T("My Test"),&tRect,DT_CENTER|DT_VCENTER|DT_SINGLELINE);
      MemDC.SetTextColor(RGB(255,0,0));
      MemDC.DrawText(_T("TEST"),&tRect,DT_CENTER|DT_VCENTER|DT_SINGLELINE);
      }
      else {
      MemDC.SetTextColor(RGB(255,255,255));
      MemDC.DrawText(_T("TEST"),&tRect,DT_CENTER|DT_VCENTER|DT_SINGLELINE);
      MemDC.SetTextColor(RGB(0,150,0));
      MemDC.DrawText(_T("My Test"),&tRect,DT_CENTER|DT_VCENTER|DT_SINGLELINE);

      }

      pDC->BitBlt(0, 0, tRect.Width(), tRect.Height(), &MemDC,
      0, 0, SRCCOPY);
      m_Seconds++;
      m_TimerEcho.Format(_T("%d: Seconds have passed"), m_Seconds);
      gtest ^= 1;

      MemDC.SelectObject(oldBitmap);
      bmp.DeleteObject();
      MemDC.DeleteDC();
      ReleaseDC(pDC);

      CDialog::OnTimer(nIDEvent);
      }

      C 1 Reply Last reply
      0
      • E econy

        Thanks, now the test string appeared. But, the client area is black, and show text string in while color only, no change. Please refer to the code:

        void CDrawTextTstDlg::OnTimer(UINT_PTR nIDEvent)
        {
        CDC *pDC;
        CRect tRect;
        CDC MemDC;

        pDC = this->GetDC();
        GetClientRect(&tRect);
        MemDC.CreateCompatibleDC(NULL);

        CBitmap bmp;
        bmp.CreateCompatibleBitmap(&MemDC, tRect.Width(), tRect.Height());
        CBitmap *oldBitmap = MemDC.SelectObject(&bmp);
        MemDC.SetBkMode(TRANSPARENT);

        if (gtest == 0 ){
        MemDC.SetTextColor(RGB(255,255,255));
        MemDC.DrawText(_T("My Test"),&tRect,DT_CENTER|DT_VCENTER|DT_SINGLELINE);
        MemDC.SetTextColor(RGB(255,0,0));
        MemDC.DrawText(_T("TEST"),&tRect,DT_CENTER|DT_VCENTER|DT_SINGLELINE);
        }
        else {
        MemDC.SetTextColor(RGB(255,255,255));
        MemDC.DrawText(_T("TEST"),&tRect,DT_CENTER|DT_VCENTER|DT_SINGLELINE);
        MemDC.SetTextColor(RGB(0,150,0));
        MemDC.DrawText(_T("My Test"),&tRect,DT_CENTER|DT_VCENTER|DT_SINGLELINE);

        }

        pDC->BitBlt(0, 0, tRect.Width(), tRect.Height(), &MemDC,
        0, 0, SRCCOPY);
        m_Seconds++;
        m_TimerEcho.Format(_T("%d: Seconds have passed"), m_Seconds);
        gtest ^= 1;

        MemDC.SelectObject(oldBitmap);
        bmp.DeleteObject();
        MemDC.DeleteDC();
        ReleaseDC(pDC);

        CDialog::OnTimer(nIDEvent);
        }

        C Offline
        C Offline
        Chris Losinger
        wrote on last edited by
        #6

        bmp.CreateCompatibleBitmap(&MemDC, tRect.Width(), tRect.Height());

        instead of MemDC there, use the DC that you used as the source for CreateCompatibleDC. when a memory DC is created, it has a 1x1 pixel monochrome bitmap selected into it. if you create a bitmap compatible with that, you'll get a monochrome bitmap. also, if you want a background color, you'll need to fill the bitmap with that color (CDC::FillSolidRect)

        image processing toolkits | batch image processing

        E 1 Reply Last reply
        0
        • C Chris Losinger

          bmp.CreateCompatibleBitmap(&MemDC, tRect.Width(), tRect.Height());

          instead of MemDC there, use the DC that you used as the source for CreateCompatibleDC. when a memory DC is created, it has a 1x1 pixel monochrome bitmap selected into it. if you create a bitmap compatible with that, you'll get a monochrome bitmap. also, if you want a background color, you'll need to fill the bitmap with that color (CDC::FillSolidRect)

          image processing toolkits | batch image processing

          E Offline
          E Offline
          econy
          wrote on last edited by
          #7

          Thank you very much. Now I can see the Text string color is changing. While, the whole dialog screen is black too, some controls, static texts all disappeared. Do I need to redraw all the controls like DrawText() ? and then BitBlt()? The original dialog screen is white.

          C 1 Reply Last reply
          0
          • E econy

            Thank you very much. Now I can see the Text string color is changing. While, the whole dialog screen is black too, some controls, static texts all disappeared. Do I need to redraw all the controls like DrawText() ? and then BitBlt()? The original dialog screen is white.

            C Offline
            C Offline
            Chris Losinger
            wrote on last edited by
            #8

            whenever i need to draw on a dialog, i put a static 'frame' control in the place where i want to draw. then i get that control's rectangle and limit my drawing to that rect.

            CRect outRect;
            m_myDrawingRectControl.GetWindowRect(outRect);
            ScreenToClient(outRect);

            also, you should only do drawing in your CDialog's OnPaint method. if you need to trigger drawing from a timer, just call CDialog::InvalidateRect() with your control's rectangle (as above). so:

            void CDynamicShowTextDlg::OnTimer(UINT nIDEvent)
            {
            CRect outRect;
            m_myDrawingRectControl.GetWindowRect(outRect);
            ScreenToClient(outRect);

            InvalidateRect(outRect);
            }

            void CDynamicShowTextDlg::OnPaint()
            {
            if (IsIconic())
            {
            ...}
            else
            {
            CRect outRect;
            m_myDrawingRectControl.GetWindowRect(outRect);
            ScreenToClient(outRect);

              CPaintDC dc(this); // device context for painting
            
              ...
            

            do your drawing here.
            use dc as the source for your CreateCompatible* stuff
            ...
            CDialog::OnPaint();
            }

            image processing toolkits | batch image processing

            E 2 Replies Last reply
            0
            • C Chris Losinger

              whenever i need to draw on a dialog, i put a static 'frame' control in the place where i want to draw. then i get that control's rectangle and limit my drawing to that rect.

              CRect outRect;
              m_myDrawingRectControl.GetWindowRect(outRect);
              ScreenToClient(outRect);

              also, you should only do drawing in your CDialog's OnPaint method. if you need to trigger drawing from a timer, just call CDialog::InvalidateRect() with your control's rectangle (as above). so:

              void CDynamicShowTextDlg::OnTimer(UINT nIDEvent)
              {
              CRect outRect;
              m_myDrawingRectControl.GetWindowRect(outRect);
              ScreenToClient(outRect);

              InvalidateRect(outRect);
              }

              void CDynamicShowTextDlg::OnPaint()
              {
              if (IsIconic())
              {
              ...}
              else
              {
              CRect outRect;
              m_myDrawingRectControl.GetWindowRect(outRect);
              ScreenToClient(outRect);

                CPaintDC dc(this); // device context for painting
              
                ...
              

              do your drawing here.
              use dc as the source for your CreateCompatible* stuff
              ...
              CDialog::OnPaint();
              }

              image processing toolkits | batch image processing

              E Offline
              E Offline
              econy
              wrote on last edited by
              #9

              Very very appreciate your help.

              1 Reply Last reply
              0
              • C Chris Losinger

                whenever i need to draw on a dialog, i put a static 'frame' control in the place where i want to draw. then i get that control's rectangle and limit my drawing to that rect.

                CRect outRect;
                m_myDrawingRectControl.GetWindowRect(outRect);
                ScreenToClient(outRect);

                also, you should only do drawing in your CDialog's OnPaint method. if you need to trigger drawing from a timer, just call CDialog::InvalidateRect() with your control's rectangle (as above). so:

                void CDynamicShowTextDlg::OnTimer(UINT nIDEvent)
                {
                CRect outRect;
                m_myDrawingRectControl.GetWindowRect(outRect);
                ScreenToClient(outRect);

                InvalidateRect(outRect);
                }

                void CDynamicShowTextDlg::OnPaint()
                {
                if (IsIconic())
                {
                ...}
                else
                {
                CRect outRect;
                m_myDrawingRectControl.GetWindowRect(outRect);
                ScreenToClient(outRect);

                  CPaintDC dc(this); // device context for painting
                
                  ...
                

                do your drawing here.
                use dc as the source for your CreateCompatible* stuff
                ...
                CDialog::OnPaint();
                }

                image processing toolkits | batch image processing

                E Offline
                E Offline
                econy
                wrote on last edited by
                #10

                And one more question, even I draw in Timer() function, then WM_PAINT also produced to the system,right?

                C 1 Reply Last reply
                0
                • E econy

                  And one more question, even I draw in Timer() function, then WM_PAINT also produced to the system,right?

                  C Offline
                  C Offline
                  Chris Losinger
                  wrote on last edited by
                  #11

                  right.

                  image processing toolkits | batch image processing

                  E 1 Reply Last reply
                  0
                  • C Chris Losinger

                    right.

                    image processing toolkits | batch image processing

                    E Offline
                    E Offline
                    econy
                    wrote on last edited by
                    #12

                    Hi, I wrote snippet code to test. first, I put a Static text in the dialog box, from the resource file:

                    IDD_ECHOBUTTONEVENT_DIALOG DIALOGEX 0, 0, 320, 200
                    ...
                    BEGIN
                    ...
                    LTEXT "Static",IDC_STATIC_TXT1,89,59,98,26
                    ...
                    END

                    In Ontimer():

                    CRect outRect;
                    CStatic* pTxt1Static;
                    pTxt1Static = (CStatic*)GetDlgItem(IDC_STATIC_TXT1);
                    pTxt1Static->GetWindowRect(&outRect);
                    ScreenToClient(&outRect);
                    InvalidateRect(&outRect);
                    UpdateData(FALSE);

                    In OnPaint():

                    if (IsIconic()) {
                    ...
                    }
                    else
                    {
                    CRect outRect;
                    CStatic* pTxt1Static;
                    pTxt1Static = (CStatic*)GetDlgItem(IDC_STATIC_TXT1);
                    pTxt1Static->GetWindowRect(&outRect);
                    ScreenToClient(&outRect);

                    CPaintDC dc(pTxt1Static); 
                    //dc.SetTextColor(RGB(255,255,255));
                    dc.SetTextColor(RGB(255,0,0));
                    dc.SetBkMode(TRANSPARENT);
                    	
                    dc.DrawText(\_T("My Test"),&outRect,DT\_CENTER|DT\_VCENTER);
                    	
                    CDialogEx::OnPaint();
                    

                    }

                    But, the string "My Test" 's position is not at same position of Static text(IDC_STATIC_TXT1). offset I guess is about 50 to 100 pixel. And if I change CPaintDC dc(pTxt1Static) to CPaintDC dc(this), I got nothing, even I stretch the dialog box to double, triple size. If I don't use ScreenToClient(&outRect) in OnTimer(), and OnPaint(), I can see "My Test" string, but, need to stretch the dialog; I set break point, pTxt1Static->GetWindowRect(&outRect); give : tagRECT = {top=309 bottom=351 left=577 right=724} run to ScreenToClient(&outRect); give: tagRECT = {top=96 bottom=138 left=134 right=281} Could you please help me to see what is the reason?

                    C 2 Replies Last reply
                    0
                    • E econy

                      Hi, I wrote snippet code to test. first, I put a Static text in the dialog box, from the resource file:

                      IDD_ECHOBUTTONEVENT_DIALOG DIALOGEX 0, 0, 320, 200
                      ...
                      BEGIN
                      ...
                      LTEXT "Static",IDC_STATIC_TXT1,89,59,98,26
                      ...
                      END

                      In Ontimer():

                      CRect outRect;
                      CStatic* pTxt1Static;
                      pTxt1Static = (CStatic*)GetDlgItem(IDC_STATIC_TXT1);
                      pTxt1Static->GetWindowRect(&outRect);
                      ScreenToClient(&outRect);
                      InvalidateRect(&outRect);
                      UpdateData(FALSE);

                      In OnPaint():

                      if (IsIconic()) {
                      ...
                      }
                      else
                      {
                      CRect outRect;
                      CStatic* pTxt1Static;
                      pTxt1Static = (CStatic*)GetDlgItem(IDC_STATIC_TXT1);
                      pTxt1Static->GetWindowRect(&outRect);
                      ScreenToClient(&outRect);

                      CPaintDC dc(pTxt1Static); 
                      //dc.SetTextColor(RGB(255,255,255));
                      dc.SetTextColor(RGB(255,0,0));
                      dc.SetBkMode(TRANSPARENT);
                      	
                      dc.DrawText(\_T("My Test"),&outRect,DT\_CENTER|DT\_VCENTER);
                      	
                      CDialogEx::OnPaint();
                      

                      }

                      But, the string "My Test" 's position is not at same position of Static text(IDC_STATIC_TXT1). offset I guess is about 50 to 100 pixel. And if I change CPaintDC dc(pTxt1Static) to CPaintDC dc(this), I got nothing, even I stretch the dialog box to double, triple size. If I don't use ScreenToClient(&outRect) in OnTimer(), and OnPaint(), I can see "My Test" string, but, need to stretch the dialog; I set break point, pTxt1Static->GetWindowRect(&outRect); give : tagRECT = {top=309 bottom=351 left=577 right=724} run to ScreenToClient(&outRect); give: tagRECT = {top=96 bottom=138 left=134 right=281} Could you please help me to see what is the reason?

                      C Offline
                      C Offline
                      Chris Losinger
                      wrote on last edited by
                      #13

                      econy wrote:

                      But, the string "My Test" 's position is not at same position of Static text(IDC_STATIC_TXT1).
                      offset I guess is about 50 to 100 pixel.

                      could that be due to the DT_CENTER|DT_VCENTER flags?

                      econy wrote:

                      And if I change CPaintDC dc(pTxt1Static) to CPaintDC dc(this),

                      it should be CPaintDC dc(this). you're painting the dialog, after all, not the static control. also, try making your static control a 'frame' type, not a static text. something like: CONTROL "",IDC_DRAWING_FRAME,"Static",SS_ETCHEDFRAME,12,199,169,66 that gives you a rectangle with no text in it.

                      image processing toolkits | batch image processing

                      1 Reply Last reply
                      0
                      • E econy

                        Hi, I wrote snippet code to test. first, I put a Static text in the dialog box, from the resource file:

                        IDD_ECHOBUTTONEVENT_DIALOG DIALOGEX 0, 0, 320, 200
                        ...
                        BEGIN
                        ...
                        LTEXT "Static",IDC_STATIC_TXT1,89,59,98,26
                        ...
                        END

                        In Ontimer():

                        CRect outRect;
                        CStatic* pTxt1Static;
                        pTxt1Static = (CStatic*)GetDlgItem(IDC_STATIC_TXT1);
                        pTxt1Static->GetWindowRect(&outRect);
                        ScreenToClient(&outRect);
                        InvalidateRect(&outRect);
                        UpdateData(FALSE);

                        In OnPaint():

                        if (IsIconic()) {
                        ...
                        }
                        else
                        {
                        CRect outRect;
                        CStatic* pTxt1Static;
                        pTxt1Static = (CStatic*)GetDlgItem(IDC_STATIC_TXT1);
                        pTxt1Static->GetWindowRect(&outRect);
                        ScreenToClient(&outRect);

                        CPaintDC dc(pTxt1Static); 
                        //dc.SetTextColor(RGB(255,255,255));
                        dc.SetTextColor(RGB(255,0,0));
                        dc.SetBkMode(TRANSPARENT);
                        	
                        dc.DrawText(\_T("My Test"),&outRect,DT\_CENTER|DT\_VCENTER);
                        	
                        CDialogEx::OnPaint();
                        

                        }

                        But, the string "My Test" 's position is not at same position of Static text(IDC_STATIC_TXT1). offset I guess is about 50 to 100 pixel. And if I change CPaintDC dc(pTxt1Static) to CPaintDC dc(this), I got nothing, even I stretch the dialog box to double, triple size. If I don't use ScreenToClient(&outRect) in OnTimer(), and OnPaint(), I can see "My Test" string, but, need to stretch the dialog; I set break point, pTxt1Static->GetWindowRect(&outRect); give : tagRECT = {top=309 bottom=351 left=577 right=724} run to ScreenToClient(&outRect); give: tagRECT = {top=96 bottom=138 left=134 right=281} Could you please help me to see what is the reason?

                        C Offline
                        C Offline
                        Chris Losinger
                        wrote on last edited by
                        #14

                        also, it is not essential that you use a static control at all. i use them because having an actual control i can move around in the resource dialog editor makes it easy to do the layout of all the other controls. but, if you just want to draw at an arbitrary rectangle and skip the GetWindowRect/ScreenToClient/etc. stuff , you can certainly do that, too.

                        image processing toolkits | batch image processing

                        E 1 Reply Last reply
                        0
                        • C Chris Losinger

                          also, it is not essential that you use a static control at all. i use them because having an actual control i can move around in the resource dialog editor makes it easy to do the layout of all the other controls. but, if you just want to draw at an arbitrary rectangle and skip the GetWindowRect/ScreenToClient/etc. stuff , you can certainly do that, too.

                          image processing toolkits | batch image processing

                          E Offline
                          E Offline
                          econy
                          wrote on last edited by
                          #15

                          Thank you very much.

                          1 Reply Last reply
                          0
                          Reply
                          • Reply as topic
                          Log in to reply
                          • Oldest to Newest
                          • Newest to Oldest
                          • Most Votes


                          • Login

                          • Don't have an account? Register

                          • Login or register to search.
                          • First post
                            Last post
                          0
                          • Categories
                          • Recent
                          • Tags
                          • Popular
                          • World
                          • Users
                          • Groups