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.
  • CPalliniC CPallini

    You can see drawing operations occurred into a memory device context only if you BitBlt it to a 'standard' device context (see, for instance "CDC::CreateCompatibleDC" at MSDN[^].

    Veni, vidi, vici.

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

    I added a statement:

    int nX = tRect.left + tRect.Width() / 2;
    int nY = tRect.top + tRect.Height() / 2;
    pDC->BitBlt(nX, nY, tRect.Width()/3, tRect.Height()/3, &MemDC,
    0, 0, SRCCOPY);

    But still get nothing on the screen.

    1 Reply Last reply
    0
    • 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