C++ 为什么将鼠标悬停在静态Win32控件上会增加内存并删除GUI?
如果处理不当,Windows API资源可能导致内存泄漏。不管这个问题是否如此,我认为这是相关的。虽然我展示了我是如何确定问题来自何方的,但我一直未能解决它 我有两种使用Win32 API的静态类控件,它们在我的类中进行了抽象:C++ 为什么将鼠标悬停在静态Win32控件上会增加内存并删除GUI?,c++,winapi,C++,Winapi,如果处理不当,Windows API资源可能导致内存泄漏。不管这个问题是否如此,我认为这是相关的。虽然我展示了我是如何确定问题来自何方的,但我一直未能解决它 我有两种使用Win32 API的静态类控件,它们在我的类中进行了抽象: Label LinkLabel 问题:每当我添加这两个控件时,Visual Studio 2017的诊断工具都会显示当我同时启用setFont()或setHoverColor()行时,进程内存(MB)从3MB增加到11MB,最终我的GUI空间中的所有内容都消失了——
Label
LinkLabel
问题:每当我添加这两个控件时,Visual Studio 2017的诊断工具都会显示当我同时启用setFont()或setHoverColor()行时,进程内存(MB)从3MB增加到11MB,最终我的GUI空间中的所有内容都消失了——消失了,就像一些知名书店一样
此代码正常(3MB在进程内存中保持不变的速率):
下面的代码取消注释最后一行。将鼠标悬停在myLabel上,出现红色突出显示颜色后,进程内存的3MB增加到7MB+。它会停留一段时间,然后上升到9MB+。所以,它有点不对劲
// 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);
那么,让我们深入了解我的setHoverColor()
好的,上面的代码没有什么太令人惊讶的地方。这告诉我去WndProc看看
此静态控件使用的事件是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));
}
}
它还调用setFont()来更新它:
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;
}
我猜这是一个很大的更新创建字体和重新创建它的基础上每一个悬停。我的理由是它不会更新字体颜色,除非再次设置字体。虽然我在不久的将来看到了这样做的空间,但我是否忘记删除这里的资源或其他内容?任何想法都欢迎。这肯定也能解决LinkLabel问题。你的基本问题是不断生成新字体,而从不发布旧字体 每次调用setfont时,您都要分配并选择一种新字体。但当你在HDC中选择新字体时,你永远不会清理旧字体 SelectFont返回以前选择的字体,您需要该字体(除非它是常用字体)在其上执行DeleteFont操作 此外,在GetDC调用中存在更大的资源泄漏-GetDC的MS文档建议您在完成使用后使用releaseDC
据我所知,仅仅为了重置颜色,不需要重置字体。tl;你博士在“…像一些著名的书店”失去了我的注意力。不知道你在谈论什么商店,也不知道它们与这个问题有什么关系。有点幽默感。你可能想看看或者。至少试着读一下WM_SETCURSOR文档…?闻起来像是资源泄漏。如果您有一个。字体设置为
SendMessage
(不返回以前的字体)。据我所知,DC部分只是计算指标。如果getHoverCursor每次都创建一个新的游标,那么可能还会有另一个漏洞。这很有效!虽然重置悬停光标会引起问题,但我相信。使用。。。SetClassLongPtr(frm.getLinkLabelControl(i).getHandle(),GCLP_HCURSOR,(LONG_PTR)LoadCursor(NULL,IDC_箭头));
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));
}
}
void Label::setColor(const COLORREF color)
{
m_foreColor = color;
setFont(m_fontName, m_fontSize, m_bold, m_italic, m_underlined);
}
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;
}