.NET CF Forms - Me.Font - 处理控件默认字体

时间:2016-07-05 16:36:12

标签: vb.net winforms compact-framework

当我注意到奇怪的事情时,我一直在尝试用自定义控件识别内存泄漏:

Private f = Me.Font

Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
     If f IsNot Me.Font Then 'ALWAYS TRUE
         f.Dispose()
         f = Me.Font
     End If
     ...
End Sub

Me.Font每次都会返回一个不同的实例,这会让我质疑我调用Me.Font的其他情况。

通常情况下这不是什么大问题,但在此控件中可以每隔500毫秒调用一次。

每次调用时都会生成Me.Font因此应该每次处理吗?有没有像这样的其他控制属性我需要警惕?

1 个答案:

答案 0 :(得分:2)

如果您使用的是从System.Windows.Forms.Control继承的控件而您尚未更改当前字体默认字体,那么这似乎很合乎逻辑

如果我们查看.NET Framework Microsoft's Reference Source,我们可以看到Control.Font property最初尝试获取控件的当前字体:

Font font = (Font)Properties.GetObject(PropFont);
if (font != null) {
    return font;
}

如果没有当前字体(如果它是null或Visual Basic中的Nothing),它会尝试获取其父字体:

Font f = GetParentFont();
if (f != null) {
    return f;
}

现在,如果控件没有父级,GetParentFont()将返回null(这可能会一直返回到父窗体)。如果这到达最后一个父GetParentFont()将返回null,从而继续执行。由于控件不是ActiveX控件,if (IsActiveX)检查将失败并继续执行:

AmbientProperties ambient = AmbientPropertiesService;
if (ambient != null && ambient.Font != null) {
    return ambient.Font;
}

我不确定这是做什么的,但即使检查失败,我们也会进入有趣的部分:

return DefaultFont;

控件返回DefaultFont属性,如果我们go to its code

if (defaultFont == null) {
    defaultFont = SystemFonts.DefaultFont;
    Debug.Assert(defaultFont != null, "defaultFont wasn't set!");
}

return defaultFont;

我们可以看到它检查控件是否已经定义了自己的默认字体,如果没有,它将返回所有标准控件的默认字体(通过SystemFonts.DefaultFont )。

如果我们最终跳转到the code for SystemFonts.DefaultFont,我们可以看到它会创建一个名为defaultFont的变量,它最终会返回。

Font defaultFont = null;

现在,在查看变量的分配方式时,我们可以看到它始终会创建一个新的Font实例(这会导致您的问题):

//Each line represents an example taken from the code.
defaultFont = new Font("MS UI Gothic", 9);
defaultFont = new Font("Tahoma", 8); //This appears two times.
defaultFont = new Font(FontFamily.GenericSansSerif, 8);
defaultFont = FontInPoints(defaultFont);

//FontInPoints only have one line: "return new Font(...);"

因此,我们现在可以得出结论,每次拨打YourControl.Font时,如果您没有 ,它将返回新的Font实例 分配了自定义字体/自定义默认字体, 如果所有其他检查失败 使其获得Windows的默认字体。