更改控件的字体时是否应该丢弃旧字体?

时间:2015-03-17 15:44:01

标签: c# winforms fonts dispose

C#,Windows Forms app。

我们正在为我们的应用程序重新设置皮肤,并且我还更改了旧版本中使用的可怕默认字体。因此我想我在加载表单时调用以下函数来更改表单上所有控件的字体。

  internal static void SetFonts(Control control)
  {
    Font oldFont = control.Font;
    if (oldFont.Name != GlobalFontName)
    {
      string familyName = GlobalFontName;
      Font newFont = new System.Drawing.Font(familyName,
        oldFont.Size, oldFont.Style, GraphicsUnit.Point, 0);
      control.Font = newFont;
      //oldFont.Dispose();
    }
    foreach (Control child in control.Controls)
      SetFonts(child);
  }

我认为如果在将控件重新分配给新控件之后处理旧字体会使资源保持不变,但在关闭表单时我会从一组第三方接收来自一种控件类型的访问冲突异常控制。 如果我注释掉了#34; oldFont.Dispose()"然后我没有得到例外。

这是第三方控制集的错误还是这是预期的?
记忆明智,我可以逃脱没有明确处理旧字体(应用程序在信息亭上运行12小时+一天)?

3 个答案:

答案 0 :(得分:1)

不要处理旧的Font,这是您正在更改其字体的Control的工作。此外,使用GDIView等工具来监控您的句柄(例如字体)。

答案 1 :(得分:1)

控制字体非常奇怪,因为Font对象实际上封装了两个不同的东西:

  1. 有关字体,打字等的信息
  2. GDI字体句柄。
  3. Font对象的后一个方面封装了一个资源;前者没有。在Dispose对象上调用Font会释放后者,但不会破坏前者。

    虽然我认为我没有看到他们的行为“正式”记录在任何地方,但似乎内置控件实际上从未使用用于设置{{1的Font对象实际绘制属性;相反,他们使用指定的Font对象的属性来生成新的GDI字体对象,然后使用它来绘制控件。尽管在字体对象上调用Font会使其无法用作Dispose或其他此类方法的参数,但它不会阻止其用作制作新字体对象的“模板”。

    这样做的结果是控件不关心分配的DrawString对象是否被处置(无论是在分配之前还是之后),也没有处理它。从控件中读取Font属性将始终返回上次分配给它的相同Font对象,而不考虑是否放置了Font对象。因此,似乎如果没有任何东西可以读取控件的Font属性并期望用它绘制,那么在没有临时资源泄漏的情况下分配控件的Font属性的最安全的方法将是非常奇怪的 - 寻找:

    Font

    这比阅读控件的using f = new Font(...) theControl.Font = f; 属性并在分配新值之前处理它更安全,因为上面的Font方法知道分配给控件的using赢了“ t用于其他任何事情,而后一种方法无法知道是否有一些其他代码使用相同的Font来反对它的处置。

    我真的希望MS记录了应该如何处理Font资源。不幸的是,据我所知,他们没有。

答案 2 :(得分:0)

我决定将创建的字体存储到列表中,并在form.Dispose()中处理它们。但是在某些窗口上我也遇到了错误。

我刚刚意识到第三方控件还必须在换肤/绘画时更改它的字体,因此列表中的字体不再对控件有效,并且可能已由GC处理。

因此,存储字体以供以后处理似乎不安全,我想知道是否应该存储已更改字体的控件。

此时继续沿着这条线的前景失去了它的吸引力,而是我手动浏览了我的应用程序中的所有200多个表单,而不是搜索/替换lol

我不是很高兴。