admin管理员组文章数量:1400863
Problem: I'm working on a custom vertical scrollbar control in WinForms. When I move the scrollbar (dragging the slider up and down), the memory usage of the application constantly increases. After I stop interacting with the scrollbar, the memory usage doesn't decrease, indicating a possible memory leak. I'm unsure where the issue lies in my code.
What I've Tried: Detached and reattached event handlers appropriately.
Attempted to dispose of the slider when no longer needed.
Used Invalidate() to refresh the control, but the issue still persists.
Tried handling custom resources (e.g., the slider control) manually to prevent leaks.
Expected Behavior: The memory usage should not increase while interacting with the scrollbar, and it should return to normal once the interaction stops.
Code:
using Chef_s_Codex.CustomUIElements;
using System;
using System.Drawing;
using System.Windows.Forms;
namespace Test.Custom
{
[DefaultEvent("VelChanged")]
public partial class CustonVScrollBar : UserControl
{
public delegate void VelChangedEventHandler(object sender, EventArgs e);
public event VelChangedEventHandler VelChanged;
private Color chennelColor = Color.Transparent;
private Color slederColor = Color.LightGray;
private Color focusChennelColor = Color.Transparent;
private Color focusSlederColor = Color.Gray;
private int chennelWidth = 15;
private int slederWidht = 15;
private int slederHeight = 75;
private int cornerradius = 7;
private int maxValue = 100;
private int minValue = 0;
private int vel = 0;
private int scaleValue = 5;
private int locYSlider = 0;
private bool isMove = false;
private int locYLast = 0;
private bool isFocus = false;
private int deltaY;
private RoundedPanel slider;
#region Properties
[Category("Scrollbar")]
[Browsable(true)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public Color ChennelColor
{
get { return chennelColor; }
set { chennelColor = value; this.BackColor = value; }
}
[Category("Scrollbar")]
[Browsable(true)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public Color SlederColor
{
get { return slederColor; }
set { slederColor = value; if (slider != null) slider.BackColor = value; }
}
[Category("Scrollbar")]
[Browsable(true)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public Color FocusChennelColor
{
get { return focusChennelColor; }
set { focusChennelColor = value; }
}
[Category("Scrollbar")]
[Browsable(true)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public Color FocusSlederColor
{
get { return focusSlederColor; }
set { focusSlederColor = value; }
}
[Category("Scrollbar")]
[Browsable(true)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public int ChennelWidth
{
get { return chennelWidth; }
set { chennelWidth = value; Invalidate(); }
}
[Category("Scrollbar")]
[Browsable(true)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public int SlederWidht
{
get { return slederWidht; }
set { slederWidht = value; if (slider != null) slider.Width = value; }
}
[Category("Scrollbar")]
[Browsable(true)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public int MaxValue
{
get { return maxValue; }
set { maxValue = value; }
}
[Category("Scrollbar")]
[Browsable(true)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public int MinValue
{
get { return minValue; }
set { minValue = value; }
}
[Category("Scrollbar")]
[Browsable(true)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public int Vel
{
get { return vel; }
set
{
if (value > maxValue) vel = maxValue;
else if (value < minValue) vel = minValue;
else vel = value;
locYSlider = UpdateLocYSlider(vel);
}
}
[Category("Scrollbar")]
[Browsable(true)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public int ScaleValue
{
get { return scaleValue; }
set { scaleValue = value; }
}
[Category("Scrollbar")]
[Browsable(true)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public int SlederHeight
{
get { return slederHeight; }
set { slederHeight = value; if (slider != null) slider.Height = slederHeight; }
}
[Category("Scrollbar")]
[Browsable(true)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public int CornerRadius
{
get { return cornerradius; }
set { cornerradius = value; }
}
#endregion
public CustonVScrollBar()
{
InitializeComponent();
this.SetStyle(ControlStyles.UserPaint | ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint, true);
roundedPanel1.MouseDown -= CustomScrollbar_MouseDown;
roundedPanel1.MouseUp -= CustomScrollbar_MouseUp;
roundedPanel1.MouseMove -= CustomScrollbar_MouseMove;
roundedPanel1.MouseDown += CustomScrollbar_MouseDown;
roundedPanel1.MouseUp += CustomScrollbar_MouseUp;
roundedPanel1.MouseMove += CustomScrollbar_MouseMove;
if (slederHeight < roundedPanel1.Height)
{
if (slider != null)
{
roundedPanel1.Controls.Remove(slider);
slider.Dispose();
slider = null;
}
SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer | ControlStyles.ResizeRedraw | ControlStyles.UserPaint, true);
slider = new RoundedPanel();
roundedPanel1.Controls.Add(slider);
slider.BorderStyle = BorderStyle.None;
slider.RadiusBottomLeft = 5;
slider.RadiusBottomRight = 5;
slider.RadiusTopLeft = 5;
slider.RadiusTopRight = 5;
slider.Height = slederHeight;
slider.Width = slederWidht;
slider.BackColor = slederColor;
slider.Location = new Point((roundedPanel1.Width - slederWidht) / 2, 20);
slider.Enabled = false;
}
locYSlider = 1;
locYLast = 1;
vel = UpdateValue();
}
protected override void CreateHandle()
{
base.CreateHandle();
roundedPanel1.BackColor = chennelColor;
this.BackColor = this.Parent.BackColor;
}
#region Callbacks
private void CustomScrollbar_MouseMove(object? sender, MouseEventArgs e)
{
if (slederHeight >= roundedPanel1.Height || !isMove) return;
int allowedTop = 1;
int allowedBottom = roundedPanel1.Height - 1;
deltaY = e.Y - locYLast;
if (deltaY == 0) return;
int newLocYSlider = locYSlider + deltaY;
newLocYSlider = Math.Clamp(newLocYSlider, allowedTop, allowedBottom - slederHeight);
if (newLocYSlider == locYSlider) return; // Prevent unnecessary updates
locYSlider = newLocYSlider;
locYLast = e.Y;
vel = UpdateValue();
OnVelChanged();
}
protected virtual void OnVelChanged()
{
VelChanged?.Invoke(this, EventArgs.Empty);
}
private int UpdateValue()
{
int availableHeight = this.Height - slederHeight;
if (availableHeight <= 0) return minValue; // Prevent division by zero
double ratio = (double)(locYSlider) / availableHeight;
int value = minValue + (int)((maxValue - minValue) * ratio);
slider.Location = new Point(slider.Location.X, locYSlider);
return Math.Clamp(value, minValue, maxValue);
}
private void CustomScrollbar_MouseUp(object? sender, MouseEventArgs e)
{
slider.BackColor = slederColor;
if (slederHeight >= roundedPanel1.Height) return;
isMove = false;
isFocus = false;
}
private void CustomScrollbar_MouseDown(object? sender, MouseEventArgs e)
{
slider.BackColor = focusSlederColor;
if (slederHeight >= roundedPanel1.Height) return;
isFocus = true;
locYLast = e.Y;
if (e.Button == MouseButtons.Left)
{
locYSlider = e.Y - (slederHeight / 2);
if (locYSlider < 0) locYSlider = 0;
if (locYSlider > roundedPanel1.Height - slederHeight) locYSlider = roundedPanel1.Height - slederHeight;
vel = UpdateValue();
OnVelChanged();
isMove = true;
}
}
private int UpdateLocYSlider(int valueSlider)
{
double d = (double)roundedPanel1.Height / (double)(maxValue - minValue);
int y = (int)(valueSlider * d);
if (y > roundedPanel1.Height - slederHeight) y -= slederHeight;
return y;
}
#endregion
}
}
and here is roundedPanel:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing.Drawing2D;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Test.Custom
{
public class RoundedPanel : Panel
{
private int radiusTopLeft = 0;
private int radiusTopRight = 0;
private int radiusBottomLeft = 0;
private int radiusBottomRight = 0;
public bool draw;
public bool isTest;
Graphics graphics;
[Browsable(true)]
[Category("Corner Radius")]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public int RadiusTopLeft
{
get => radiusTopLeft;
set { radiusTopLeft = Math.Max(0, value); Invalidate(); }
}
[Browsable(true)]
[Category("Corner Radius")]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public int RadiusTopRight
{
get => radiusTopRight;
set { radiusTopRight = Math.Max(0, value); Invalidate(); }
}
[Browsable(true)]
[Category("Corner Radius")]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public int RadiusBottomLeft
{
get => radiusBottomLeft;
set { radiusBottomLeft = Math.Max(0, value); Invalidate(); }
}
[Browsable(true)]
[Category("Corner Radius")]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public int RadiusBottomRight
{
get => radiusBottomRight;
set { radiusBottomRight = Math.Max(0, value); Invalidate(); }
}
public RoundedPanel()
{
this.SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer | ControlStyles.ResizeRedraw | ControlStyles.UserPaint, true);
this.BorderStyle = BorderStyle.None;
graphics = this.CreateGraphics();
graphics.SmoothingMode = SmoothingMode.AntiAlias;
graphics.CompositingQuality = CompositingQuality.HighQuality;
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
}
private GraphicsPath GetFigurePath(RectangleF rect)
{
GraphicsPath path = new GraphicsPath();
path.StartFigure();
// Top-left corner
if (RadiusTopLeft > 0)
path.AddArc(rect.X, rect.Y, RadiusTopLeft * 2, RadiusTopLeft * 2, 180, 90);
else
path.AddLine(rect.X, rect.Y, rect.X + 1, rect.Y);
// Top-right corner
if (RadiusTopRight > 0)
path.AddArc(rect.Width - RadiusTopRight * 2, rect.Y, RadiusTopRight * 2, RadiusTopRight * 2, 270, 90);
else
path.AddLine(rect.Width - 1, rect.Y, rect.Width, rect.Y + 1);
// Bottom-right corner
if (RadiusBottomRight > 0)
path.AddArc(rect.Width - RadiusBottomRight * 2, rect.Height - RadiusBottomRight * 2, RadiusBottomRight * 2, RadiusBottomRight * 2, 0, 90);
else
path.AddLine(rect.Width, rect.Height - 1, rect.Width - 1, rect.Height);
// Bottom-left corner
if (RadiusBottomLeft > 0)
path.AddArc(rect.X, rect.Height - RadiusBottomLeft * 2, RadiusBottomLeft * 2, RadiusBottomLeft * 2, 90, 90);
else
path.AddLine(rect.X + 1, rect.Height, rect.X, rect.Height - 1);
path.CloseFigure();
return path;
}
protected override void OnResize(EventArgs eventargs)
{
base.OnResize(eventargs);
RectangleF rectangleF = new RectangleF(0, 0, this.Width, this.Height + 1);
if (this.Region != null)
{
this.Region.Dispose();
}
using (GraphicsPath path = GetFigurePath(rectangleF))
using (Pen pen = new Pen(this.Parent != null ? this.Parent.BackColor : this.BackColor, 2))
{
this.Region = new Region(path);
graphics.DrawPath(pen, path);
}
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
if (this.Region != null)
{
this.Region.Dispose();
this.Region = null;
}
}
base.Dispose(disposing);
}
}
}
本文标签: cCustom Scrollbar memory leakStack Overflow
版权声明:本文标题:c# - Custom Scrollbar memory leak - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1744275492a2598391.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论