C# - 自定义TabControl类内存泄漏onHover

时间:2017-03-30 09:39:13

标签: c# memory memory-management memory-leaks

    // Top-level build file where you can add configuration options common to all sub-projects/modules.

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:2.3.0'
        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
        classpath 'com.google.gms:google-services:3.0.0'
    }
}

allprojects {
    repositories {
        jcenter()
    }
}

task clean(type: Delete) {
    delete rootProject.buildDir
}
apply plugin: 'jacoco'
jacoco {
    toolVersion = "0.7.6.201602180812"
    reportsDir = file("$buildDir/customJacocoReportDir")
}
def coverageSourceDirs = [
        'src/main/java',
]
task jacocoTestReport(type: JacocoReport, dependsOn: "connectedDebugAndroidTest") {
    group = "Reporting"
    description = "Generate Jacoco coverage reports after running tests."
    reports {
        xml.enabled = true
        html.enabled = true
    }
    classDirectories = fileTree(
            dir: './build/intermediates/classes/debug',
            excludes: ['**/R*.class'

            ])
    sourceDirectories = files(coverageSourceDirs)
    executionData = files("$buildDir/jacoco/testDebug.exec")
    // Bit hacky but fixes https://code.google.com/p/android/issues/detail?id=69174.
    // We iterate through the compiled .class tree and rename $$ to $.
    doFirst {
        new File("$buildDir/intermediates/classes/").eachFileRecurse { file ->
            if (file.name.contains('$$')) {
                file.renameTo(file.path.replace('$$', '$'))
            }
        }
    }
}

我有这个自定义选项卡控件类更现代,左对齐而不是顶部对齐。它有效,但它存在巨大的内存泄漏问题。我正在使用#region CustomTabControl - Leak public class cTabControl : TabControl { #region Remove Padding protected override void WndProc(ref Message m) { if (m.Msg == 0x1300 + 40) { lparamrect rc = (lparamrect)m.GetLParam(typeof(lparamrect)); rc.Left -= 4; rc.Right += 4; rc.Top -= 2; rc.Bottom += 4; Marshal.StructureToPtr(rc, m.LParam, true); } base.WndProc(ref m); } internal struct lparamrect { public int Left; public int Top; public int Right; public int Bottom; } #endregion //Variables; private Rectangle Rect; private int _OverIndex = -1; private int OverIndex { get { return _OverIndex; } set { _OverIndex = value; Invalidate(); } } //Default Settings; public cTabControl() { DoubleBuffered = true; Alignment = TabAlignment.Left; SizeMode = TabSizeMode.Fixed; ItemSize = new Size(30, 32); } protected override void OnCreateControl() { base.OnCreateControl(); SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer | ControlStyles.ResizeRedraw | ControlStyles.UserPaint, true); } protected override void OnControlAdded(ControlEventArgs e) { base.OnControlAdded(e); e.Control.BackColor = Settings.Default.TabBackgroundColor; e.Control.ForeColor = ColorFromHex("#FFFFFF"); e.Control.Font = new Font("Kozuka Gothic Pro B", 9); } protected override void OnPaint(PaintEventArgs e) { //Set the Graphics Variable; Graphics G = e.Graphics; //Raise the Paint event; base.OnPaint(e); //Dynamically Darken the Parent's Color slightly; Color DarkParentColor = default(Color); if (ColorContrast(Parent.BackColor) == Color.White) { DarkParentColor = ControlPaint.Light(ControlPaint.Dark(Parent.BackColor, (float)0.01), (float)1.2); } else { DarkParentColor = ControlPaint.Light(ControlPaint.Dark(Parent.BackColor, (float)0.1), (float)0.35); } //Set the Tab's Background Color to the Darkened Parent's Color; G.Clear(DarkParentColor); //For Each Tab; for (int i = 0; i <= TabPages.Count - 1; i++) { if ((string)TabPages[i].Tag != "Hidden") { // Get the Tab's Rectangle Sizing Rect = GetTabRect(i); float x = Convert.ToSingle((Rect.X + (Rect.Height - 10)) - (Rect.Height / 2)); float y = Convert.ToSingle((Rect.Y + (Rect.Height - 10)) - (Rect.Height / 2)); // If the user is hovering over the tab if (!(OverIndex == -1)) { using (SolidBrush sb = new SolidBrush(Color.FromArgb(9, Color.Black))) { //Draw the Hover Background; G.FillRectangle(sb, new Rectangle(GetTabRect(OverIndex).X, GetTabRect(OverIndex).Y, GetTabRect(OverIndex).Width, GetTabRect(OverIndex).Height)); } } else { using (SolidBrush sb = new SolidBrush(DarkParentColor)) { // Set the Background Color to the Darkened Parent's Color G.FillRectangle(sb, new Rectangle(Rect.X, Rect.Y, Rect.Width + 6, Rect.Height)); } } // If its the selected tab if (SelectedIndex == i) { using (SolidBrush sb = new SolidBrush(Settings.Default.HighlightColor), sb2 = new SolidBrush(Color.FromArgb(30, Color.Black))) { // Set the Selected Indicator to the Highlight Color G.FillRectangle(sb, new Rectangle(Rect.X, Rect.Y, 2, Rect.Height)); //Draw the Hover Background; G.FillRectangle(sb2, new Rectangle(Rect.X, Rect.Y, Rect.Width, Rect.Height)); } } //Set Render Quality; G.TextRenderingHint = TextRenderingHint.AntiAlias; if ((!ReferenceEquals(Tag, "TextOnly"))) { if (!(SelectedIndex == i)) { using (Graphics gfx = Graphics.FromImage(new Bitmap(GetTabIcon(i).Width, GetTabIcon(i).Height))) { ColorMatrix matrix = new ColorMatrix(); matrix.Matrix33 = (float)0.5; ImageAttributes attributes = new ImageAttributes(); attributes.SetColorMatrix(matrix, ColorMatrixFlag.Default, ColorAdjustType.Bitmap); G.DrawImage(GetTabIcon(i), new Rectangle(Convert.ToInt32(x), Convert.ToInt32(y), 20, 20), 0, 0, GetTabIcon(i).Width, GetTabIcon(i).Height, GraphicsUnit.Pixel, attributes); } } else if (SelectedIndex == i) { using (Image ti = GetTabIcon(i)) { G.DrawImage(ti, new Rectangle(Convert.ToInt32(x) + 1, Convert.ToInt32(y), 20, 20)); } } } else { dynamic TabProperties = TabPages[i]; StringFormat sf = new StringFormat(); sf.LineAlignment = StringAlignment.Center; using (Font f = new Font(LoadFont(Resources.Roboto_Medium), 10f)) using (SolidBrush sb = new SolidBrush(TabProperties.ForeColor)) { G.DrawString(TabProperties.Text, f, sb, x + 2, Convert.ToSingle(Rect.Y + (Rect.Height / 2)), sf); } } } } } protected override void OnSelecting(TabControlCancelEventArgs e) { base.OnSelecting(e); if ((e.TabPage != null)) { if (!string.IsNullOrEmpty(Convert.ToString(e.TabPage.Tag))) { e.Cancel = true; } else { OverIndex = -1; } } } protected override void OnMouseMove(MouseEventArgs e) { base.OnMouseMove(e); for (int I = 0; I <= TabPages.Count - 1; I++) { if (GetTabRect(I).Contains(e.Location) & string.IsNullOrEmpty(Convert.ToString(TabPages[I].Tag))) { OverIndex = I; break; // TODO: might not be correct. Was : Exit For } else { OverIndex = -1; } } } protected override void OnMouseLeave(EventArgs e) { base.OnMouseLeave(e); OverIndex = -1; } } #endregion 来获取鼠标位置,然后将其与标签交叉匹配,但即使我将鼠标保持静止或移动到标签的中间位置,例如,显然执行数百万次,这会导致内存使用量大幅增加。

有什么方法吗?

Process Memory Diagnostic

2 个答案:

答案 0 :(得分:0)

在OnMouseMove中的for循环后缓存鼠标坐标。然后,在for循环之前,检查缓存的坐标对当前坐标。如果它们的差异低于您选择的阈值,则退出该功能。使用这种方法只会在对鼠标位置进行重大更改时执行您的逻辑。

答案 1 :(得分:0)

似乎它发生的原因是因为对于TextOnly,它使用LoadFont gdi32.dll加载Roboto,并且由于某种原因它需要使用大量资源来加载它,删除所有LoadFont( )完全然后在GetTabIcon()的Bitmaps上添加using()使它完全稳定!