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
  1. Home
  2. General Programming
  3. C / C++ / MFC
  4. CStatic::Drawitem gets called repeatledly

CStatic::Drawitem gets called repeatledly

Scheduled Pinned Locked Moved C / C++ / MFC
data-structureshelp
10 Posts 2 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.
  • F Offline
    F Offline
    ForNow
    wrote on last edited by
    #1

    I have a OWNERDRAW static label which is surrounded by other static labels For some reason the DrawItem gets called repeatedly unit a stack exception occurs I have tried setting the WS_CLIPCHILDREN and WS_CLIPSIBLINGS on The parent Dialog and neighboring child controls but it doesn't seem to help any suggestions welcome

    J 1 Reply Last reply
    0
    • F ForNow

      I have a OWNERDRAW static label which is surrounded by other static labels For some reason the DrawItem gets called repeatedly unit a stack exception occurs I have tried setting the WS_CLIPCHILDREN and WS_CLIPSIBLINGS on The parent Dialog and neighboring child controls but it doesn't seem to help any suggestions welcome

      J Offline
      J Offline
      Jochen Arndt
      wrote on last edited by
      #2

      ForNow wrote:

      For some reason the DrawItem gets called repeatedly unit a stack exception occurs

      That indicates that your DrawItem implementation might be called recursive (probably not directly but by calling a function that results in a redraw). So check your code for such calls. A drawing function should only draw the control itself and do nothing else like changing properties of the control. If you for example change the selection within the drawing function, that would trigger another redraw.

      F 1 Reply Last reply
      0
      • J Jochen Arndt

        ForNow wrote:

        For some reason the DrawItem gets called repeatedly unit a stack exception occurs

        That indicates that your DrawItem implementation might be called recursive (probably not directly but by calling a function that results in a redraw). So check your code for such calls. A drawing function should only draw the control itself and do nothing else like changing properties of the control. If you for example change the selection within the drawing function, that would trigger another redraw.

        F Offline
        F Offline
        ForNow
        wrote on last edited by
        #3

        It was SetWindowText that was calling the DrawItem, I put it outside the DrawItem method However the Text isn't being displayed at all. Would you have any suggestion on how to set the Text in CStatic while using the DrawItem to change the font text color and background Thanks

        J 1 Reply Last reply
        0
        • F ForNow

          It was SetWindowText that was calling the DrawItem, I put it outside the DrawItem method However the Text isn't being displayed at all. Would you have any suggestion on how to set the Text in CStatic while using the DrawItem to change the font text color and background Thanks

          J Offline
          J Offline
          Jochen Arndt
          wrote on last edited by
          #4

          SetWindowText() sets the text and initiates drawing which must be implemented in your DrawItem function! Example (copied & pasted, unchecked, unthemed classic method):

          void CMyStatic::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
          {
          ASSERT(lpDrawItemStruct->CtlType == ODT_STATIC);
          CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC);
          ASSERT(pDC != NULL);
          pDC->FillSolidRect(&lpDrawItemStruct->rcItem, m_clrBkGnd);

          CString str;
          GetWindowText(str);
          if (!str.IsEmpty())
          {
              // Get text format options.
              UINT nFormat = m\_nFormat;
              // get actual settings in case they has been changed
              DWORD dwStyle = GetStyle(); 
              // Don't process '&' prefix sequences
              if (dwStyle & SS\_NOPREFIX) 
                  nFormat |= DT\_NOPREFIX;
              // vertically centered text and no new line
              if ((dwStyle & SS\_CENTERIMAGE) && str.Find(\_T('\\n')) < 0)
              {
                  nFormat &= ~DT\_WORDBREAK;
                  nFormat |= DT\_VCENTER | DT\_SINGLELINE;	// must set both!
              }
              if (dwStyle & SS\_ELLIPSISMASK)
              {
                  nFormat &= ~DT\_EXPANDTABS; // not supported with ellipsis
                  switch (dwStyle & SS\_ELLIPSISMASK)
                  {
                      case SS\_ENDELLIPSIS : 
                          nFormat |= DT\_END\_ELLIPSIS | DT\_MODIFYSTRING; break;
                      case SS\_PATHELLIPSIS : 
                          nFormat |= DT\_PATH\_ELLIPSIS | DT\_MODIFYSTRING; break;
                      case SS\_WORDELLIPSIS : 
                          nFormat |= DT\_WORD\_ELLIPSIS; break;
                  }
              }
              // The complete background has just been filled.
              // So use transparent mode for faster text drawing.
              // Saving and restoring of colors and mode is not necessary (drawing only performed here).
              pDC->SetBkMode(TRANSPARENT);
              pDC->SetTextColor(bDisabled ? ::GetSysColor(COLOR\_GRAYTEXT) : m\_clrText);
              
              // The text string may be modified if DT\_MODIFYSTRING is set!
              LPTSTR lpszText = str.GetBuffer();
              pDC->DrawText(lpszText, -1, &lpDrawItemStruct->rcItem, nFormat);
              str.ReleaseBuffer();
          }
          

          }

          F 2 Replies Last reply
          0
          • J Jochen Arndt

            SetWindowText() sets the text and initiates drawing which must be implemented in your DrawItem function! Example (copied & pasted, unchecked, unthemed classic method):

            void CMyStatic::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
            {
            ASSERT(lpDrawItemStruct->CtlType == ODT_STATIC);
            CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC);
            ASSERT(pDC != NULL);
            pDC->FillSolidRect(&lpDrawItemStruct->rcItem, m_clrBkGnd);

            CString str;
            GetWindowText(str);
            if (!str.IsEmpty())
            {
                // Get text format options.
                UINT nFormat = m\_nFormat;
                // get actual settings in case they has been changed
                DWORD dwStyle = GetStyle(); 
                // Don't process '&' prefix sequences
                if (dwStyle & SS\_NOPREFIX) 
                    nFormat |= DT\_NOPREFIX;
                // vertically centered text and no new line
                if ((dwStyle & SS\_CENTERIMAGE) && str.Find(\_T('\\n')) < 0)
                {
                    nFormat &= ~DT\_WORDBREAK;
                    nFormat |= DT\_VCENTER | DT\_SINGLELINE;	// must set both!
                }
                if (dwStyle & SS\_ELLIPSISMASK)
                {
                    nFormat &= ~DT\_EXPANDTABS; // not supported with ellipsis
                    switch (dwStyle & SS\_ELLIPSISMASK)
                    {
                        case SS\_ENDELLIPSIS : 
                            nFormat |= DT\_END\_ELLIPSIS | DT\_MODIFYSTRING; break;
                        case SS\_PATHELLIPSIS : 
                            nFormat |= DT\_PATH\_ELLIPSIS | DT\_MODIFYSTRING; break;
                        case SS\_WORDELLIPSIS : 
                            nFormat |= DT\_WORD\_ELLIPSIS; break;
                    }
                }
                // The complete background has just been filled.
                // So use transparent mode for faster text drawing.
                // Saving and restoring of colors and mode is not necessary (drawing only performed here).
                pDC->SetBkMode(TRANSPARENT);
                pDC->SetTextColor(bDisabled ? ::GetSysColor(COLOR\_GRAYTEXT) : m\_clrText);
                
                // The text string may be modified if DT\_MODIFYSTRING is set!
                LPTSTR lpszText = str.GetBuffer();
                pDC->DrawText(lpszText, -1, &lpDrawItemStruct->rcItem, nFormat);
                str.ReleaseBuffer();
            }
            

            }

            F Offline
            F Offline
            ForNow
            wrote on last edited by
            #5

            Thanks so much so anything written out to the control in DrawItem Must be in the guise of a device context e.g DrawText or TextOut Thanks again :)

            1 Reply Last reply
            0
            • J Jochen Arndt

              SetWindowText() sets the text and initiates drawing which must be implemented in your DrawItem function! Example (copied & pasted, unchecked, unthemed classic method):

              void CMyStatic::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
              {
              ASSERT(lpDrawItemStruct->CtlType == ODT_STATIC);
              CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC);
              ASSERT(pDC != NULL);
              pDC->FillSolidRect(&lpDrawItemStruct->rcItem, m_clrBkGnd);

              CString str;
              GetWindowText(str);
              if (!str.IsEmpty())
              {
                  // Get text format options.
                  UINT nFormat = m\_nFormat;
                  // get actual settings in case they has been changed
                  DWORD dwStyle = GetStyle(); 
                  // Don't process '&' prefix sequences
                  if (dwStyle & SS\_NOPREFIX) 
                      nFormat |= DT\_NOPREFIX;
                  // vertically centered text and no new line
                  if ((dwStyle & SS\_CENTERIMAGE) && str.Find(\_T('\\n')) < 0)
                  {
                      nFormat &= ~DT\_WORDBREAK;
                      nFormat |= DT\_VCENTER | DT\_SINGLELINE;	// must set both!
                  }
                  if (dwStyle & SS\_ELLIPSISMASK)
                  {
                      nFormat &= ~DT\_EXPANDTABS; // not supported with ellipsis
                      switch (dwStyle & SS\_ELLIPSISMASK)
                      {
                          case SS\_ENDELLIPSIS : 
                              nFormat |= DT\_END\_ELLIPSIS | DT\_MODIFYSTRING; break;
                          case SS\_PATHELLIPSIS : 
                              nFormat |= DT\_PATH\_ELLIPSIS | DT\_MODIFYSTRING; break;
                          case SS\_WORDELLIPSIS : 
                              nFormat |= DT\_WORD\_ELLIPSIS; break;
                      }
                  }
                  // The complete background has just been filled.
                  // So use transparent mode for faster text drawing.
                  // Saving and restoring of colors and mode is not necessary (drawing only performed here).
                  pDC->SetBkMode(TRANSPARENT);
                  pDC->SetTextColor(bDisabled ? ::GetSysColor(COLOR\_GRAYTEXT) : m\_clrText);
                  
                  // The text string may be modified if DT\_MODIFYSTRING is set!
                  LPTSTR lpszText = str.GetBuffer();
                  pDC->DrawText(lpszText, -1, &lpDrawItemStruct->rcItem, nFormat);
                  str.ReleaseBuffer();
              }
              

              }

              F Offline
              F Offline
              ForNow
              wrote on last edited by
              #6

              Thanks Code works great However when I inserted the following code to set a font for the text everything get messed up

              CFont l_font;
              LOGFONT lf;
              lf.lfHeight = 12;
              lf.lfWeight = 700;
              strcpy(lf.lfFaceName, "Arial"); // Need a face name "Arial".
              l_font.CreateFontIndirect(&lf);
              CFont* l_old_font = pDC->SelectObject(&l_font);

              as you can see from create the text show fit

              abendlabel->Create(_T("Abend Label"),WS_CHILD | SS_OWNERDRAW | WS_VISIBLE | WS_CLIPSIBLINGS, CRect(138, 14, 205, 31), this, IDC_ABEND_LABEL);

              Thasks

              J 1 Reply Last reply
              0
              • F ForNow

                Thanks Code works great However when I inserted the following code to set a font for the text everything get messed up

                CFont l_font;
                LOGFONT lf;
                lf.lfHeight = 12;
                lf.lfWeight = 700;
                strcpy(lf.lfFaceName, "Arial"); // Need a face name "Arial".
                l_font.CreateFontIndirect(&lf);
                CFont* l_old_font = pDC->SelectObject(&l_font);

                as you can see from create the text show fit

                abendlabel->Create(_T("Abend Label"),WS_CHILD | SS_OWNERDRAW | WS_VISIBLE | WS_CLIPSIBLINGS, CRect(138, 14, 205, 31), this, IDC_ABEND_LABEL);

                Thasks

                J Offline
                J Offline
                Jochen Arndt
                wrote on last edited by
                #7

                I would expect undefined behaviour if you have a Unicode build. The lfFaceName member is of type TCHAR[LF_FACESIZE] (see LOGFONT structure (Windows)[^]). So it must be

                _tcscpy(lf.lfFaceName, _T("Arial"));

                F 1 Reply Last reply
                0
                • J Jochen Arndt

                  I would expect undefined behaviour if you have a Unicode build. The lfFaceName member is of type TCHAR[LF_FACESIZE] (see LOGFONT structure (Windows)[^]). So it must be

                  _tcscpy(lf.lfFaceName, _T("Arial"));

                  F Offline
                  F Offline
                  ForNow
                  wrote on last edited by
                  #8

                  I have for "Character set" a value of "NOT SET" in that case I don't think I need the _T macro I have re-built a test application just display this dialog box as every test took me a long time to set up each test I going to try lf.Height either 0 or neg and see if it formats it better thanks for all your help :cool:

                  J 1 Reply Last reply
                  0
                  • F ForNow

                    I have for "Character set" a value of "NOT SET" in that case I don't think I need the _T macro I have re-built a test application just display this dialog box as every test took me a long time to set up each test I going to try lf.Height either 0 or neg and see if it formats it better thanks for all your help :cool:

                    J Offline
                    J Offline
                    Jochen Arndt
                    wrote on last edited by
                    #9

                    There is another error in your code. You have to initialise all members of your LOGFONT structure; usually by clearing them all before setting specific members:

                    memset(&lf, 0, sizeof(lf));

                    F 1 Reply Last reply
                    0
                    • J Jochen Arndt

                      There is another error in your code. You have to initialise all members of your LOGFONT structure; usually by clearing them all before setting specific members:

                      memset(&lf, 0, sizeof(lf));

                      F Offline
                      F Offline
                      ForNow
                      wrote on last edited by
                      #10

                      thanks lfHeight Value Meaning > 0 The font mapper transforms this value into device units and matches it against the cell height of the available fonts. 0 The font mapper uses a default height value when it searches for a match. < 0 The font mapper transforms this value into device units and matches its absolute value against the character height of the available fonts. Not quite sure what the above means but my question is the units sepcfied on the Crect parm of CStatic:Create the same as the units for lfHeight and lfWidth so if the width of my static control is 20 and I specify 3 for lfWidth and I have 5 characters the would = 15 units Thanks

                      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