Why is it hanging over a Win32 static controller adding memory and deleting my GUI?

Windows API resources can lead to memory leaks if not properly cared for. Whether or not this issue is involved, I guess it is related. While I'm showing how I got pinned to where this question came from, I haven't been able to resolve it.

I have two types of static class controls using the Win32 API that is abstracted in my classes:

Label
LinkLabel 

      

Problem: Whenever I add these two controls, Visual Studio 2017 Diagnostic Tools shows the process memory (MB) increases from 3 MB to 11 MB when I have either the setFont () or setHoverColor () lines, and eventually everything in my GUI space disappears - gone away from existence, like some famous bookstores.

This code is fine (3MB remains unchanged in process memory):

 // Linked Label
 myLinkLabel.init("http://www.google.com", 50, 450);
 myLinkLabel.setColor(0, 0, 255);
 myLinkLabel.onClick(lbl_Click);
 myLinkLabel.setFont("Arial", 40, true);
 //lbl.setHoverColor(255, 0, 0);  

 // label
 myLabel.init("A regular static label", 0, 0);
 myLabel.setColor(0, 255, 0);
 myLabel.setFont("Arial", 40);
 //myLabel.setHoverColor(255, 0, 0);

      

This next code will uncomment the last line. After hovering over myLabel and the appearance of a red backlight, Process Memory 3MB increases to 7 MB +. It sits a little, then goes up to 9MB +. So, there is something wrong with that.

// Linked Label
myLinkLabel.init("http://www.google.com", 50, 450);
myLinkLabel.setColor(0, 0, 255);
myLinkLabel.onClick(lbl_Click);
myLinkLabel.setFont("Arial", 40, true);
//lbl.setHoverColor(255, 0, 0);  

// label
myLabel.init("A regular static label", 0, 0);
myLabel.setColor(0, 255, 0);
myLabel.setFont("Arial", 48);
myLabel.setHoverColor(255, 0, 0);

      

So, let's dig into my setHoverColor ():

void Label::setHoverColor(const BYTE red, const BYTE blue, const BYTE green)
{
 m_hoverColorEnabled = true;
 m_hoverColor = RGB(red, green, blue);
}

      

Ok, no surprise in the code above. This tells me to look in WndProc.

The events used by this static control are WM_SETCURSOR.

 case WM_SETCURSOR:
 { 
 HWND m_handle = (HWND)wParam; 
 // Label
 for (int i = 0; i < frm.getLabelControlCount(); i++)
 {
     if (frm.getLabelControl(i).getHandle() == m_handle)
     {
          if (frm.getLinkLabelControl(i).isLink())
          {
               // Set hover color to link  
              if (frm.getLabelControl(i).isHoverColorEnabled())  
                       frm.getLabelControl(i).setColor(frm.getLabelControl(i).getHoverColor());
                       // Update cursor to hand 
                       SetClassLongPtr(frm.getLabelControl(i).getHandle(),   GCLP_HCURSOR, (LONG_PTR)frm.getLabelControl(i).getHoverCursor());
          }
      }
      else
      {
          // Set link to blue and use default arrow  
          if (frm.getLabelControl(i).isHoverColorEnabled())
             frm.getLabelControl(i).setColor(0, 0, 255);
          SetClassLongPtr(frm.getLabelControl(i).getHandle(), GCLP_HCURSOR,
         (LONG_PTR)LoadCursor(NULL, IDC_ARROW));
      }
}

      

Commenting out this section of code, Process Memory remains constant at 3MB. Uncommenting this section increases the process memory. So this is the main code that is causing the problem.

This section of code basically updates the text color of the labels based on the current hover state of the mouse. He was blue when he was not hovering and he blushed when he was hovered.

setColor () is the following code:

void Label::setColor(const COLORREF color)
{
 m_foreColor = color;
 setFont(m_fontName, m_fontSize, m_bold, m_italic, m_underlined);
}

      

Which also calls setFont () to update it:

bool Label::setFont(const std::string &fontName, const int size, const bool bold, 
 const bool italic, const bool underlined)
 DWORD dwItalic;
 DWORD dwBold;
 DWORD dwUnderlined;
 SIZE linkSize;
 dwItalic = (italic) ? TRUE : FALSE;
 dwBold = (bold) ? FW_BOLD : FW_DONTCARE;
 dwUnderlined = (underlined) ? TRUE : FALSE;
 m_font = CreateFont(size, 0, 0, 0, dwBold, dwItalic, dwUnderlined, FALSE,
  ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
  DEFAULT_PITCH | FF_SWISS, fontName.c_str());
 SendMessage(m_handle, WM_SETFONT, WPARAM(m_font), TRUE);
 
 // Calculate the correct width and height size  
 HDC hDC = GetDC(m_handle);
 SelectFont(hDC, m_font);
 GetTextExtentPoint32(hDC, m_text.c_str(), (int) m_text.length(), &linkSize);
 setSize(linkSize.cx, size);  
  
 // Store font information
 m_fontName = fontName;
 m_fontSize = size;
 m_bold = bold;
 m_underlined = underlined;
 m_italic = italic; 
  
 return true;
}

      

My guess is a lot of updates to build the font and re-create it based on every hover. My reasoning was that it would not update the font color if not reinstall the font. Although I see a place for this in the near future, am I forgetting to delete the resource or something here? Any thoughts are appreciated. LinkLabel will solve this pretty accurately.

+3


source to share


1 answer


The main problem is that you keep creating new fonts and never release old ones.

Each time setfont is called, you highlight and select a new font. But when you select a NEW font in HDC, you never clear the old font.

SelectFont returns the previously selected font, which you need (unless it's a stock font) to enable the DeleteFont.



Also, you have more resource leaks in the GetDC call - the MS documentation for getDC assumes you are using releaseDC when you finish using it.

As far as I understand, it does NOT need to reset the font just to reset the colors.

+4


source







All Articles