Hallo,
Ik zit met een serieus c#.net probleem nl een memory leak ifv unmanaged code.
Voor een applicatie moet ik custom cursors maken adhv bitmaps. Ik heb een klasse gevonden op codeproject en aangepast naar mijn noden, die gebruik maakt van unmanaged functies. Daar dit de enige manier is om het te doen zonder .cur files aan te maken.
In men applicatie wordt dit gebruikt als tooltip. Daarom moet dit object erg vaak aangemaakt worden en eigenlijk altijd een andere bitmap tonen.
Het probleem zit in het afbreken van het object voordat een nieuw aangemaakt moet worden. Dit gebeurt niet correct, waardoor mijn ram in no time volzit.
Aangezien ik zo goed als geen kennis heb van unmanaged code en hoe erop te debuggen, zit ik redelijk vast.
Ik heb een mini vb project gemaakt die de klasse bevat en het probleem duidelijk aantoont. OnmouseMove worden continue nieuwe objecten aangemaakt waardoor uw ram aan +- 1MB/sec toeslibt.
Alvast bedankt om het even te bekijken
het project vind je hier: *snip*
De klasse:
using System;
using System.Windows.Forms;
using System.Drawing;
using System.Runtime.InteropServices;
namespace WindowsFormsApplication1
{
///
/// Creates a Cursor from any bitmap. You can use the alpha-channel
/// for transparency effects.
///
/// you can use the API function CreateIconIndirect to create any cursor from a bitmap.
/// There is not size limit so you can draw the item into a bitmap and convert it into a cursor.
/// The following class can be used for that. An instance of this class must exists as long as the cursor is displayed.
///
public class clsBitmapCursor : IDisposable
{
#region Win-API imports
///
/// API-Structure ICONINFO
///
///
[StructLayout(LayoutKind.Sequential)]
public struct ICONINFO
{
public bool fIcon;
public uint xHotspot;
public uint yHotspot;
public IntPtr hbmMask;
public IntPtr hbmColor;
}
///
/// API function CreateIconIndirect
///
[System.Runtime.InteropServices.DllImport("USER32.DLL")]
public static extern IntPtr CreateIconIndirect( ref ICONINFO iconinfo );
///
/// API function DestryIcon
///
[System.Runtime.InteropServices.DllImport("USER32.DLL")]
public static extern bool DestroyIcon( IntPtr hIcon );
#endregion
private ICONINFO iconInfo;
private Cursor cursor = null;
private IntPtr handle = IntPtr.Zero;
#region constructors and destructor
public clsBitmapCursor(System.Drawing.Bitmap bmp)
{
iconInfo = new ICONINFO();
iconInfo.fIcon = false;
iconInfo.xHotspot = 0;
iconInfo.yHotspot = 0;
iconInfo.hbmMask = bmp.GetHbitmap();
iconInfo.hbmColor = bmp.GetHbitmap();
Create();
}
public clsBitmapCursor( System.Drawing.Bitmap bmp, uint HotSpotX, uint HotSpotY )
{
iconInfo = new ICONINFO();
iconInfo.fIcon = false;
iconInfo.xHotspot = HotSpotX;
iconInfo.yHotspot = HotSpotY;
iconInfo.hbmMask = bmp.GetHbitmap();
iconInfo.hbmColor = bmp.GetHbitmap();
Create();
}
///
/// Creates a cursor from a bitmap and combines it with another cursor.
///
public clsBitmapCursor(System.Drawing.Bitmap bmp, Cursor Cursor)
{
iconInfo = new ICONINFO();
iconInfo.fIcon = false;
iconInfo.xHotspot = 0;
iconInfo.yHotspot = 0;
using( System.Drawing.Bitmap bmpdup = bmp.Clone() as System.Drawing.Bitmap )
{
using( Graphics g = Graphics.FromImage( bmpdup ) )
{
Cursor.Draw( g, new Rectangle( new Point( 0, 0 ), Cursor.Size ) );
}
iconInfo.hbmMask = bmpdup.GetHbitmap();
iconInfo.hbmColor = bmpdup.GetHbitmap();
Create();
}
}
///
/// destructor
///
~clsBitmapCursor()
{
Dispose();
}
#endregion
public void moveHotspot(int x, int y)
{
iconInfo.xHotspot = (uint)x;
iconInfo.yHotspot = (uint)y;
Create();
}
private void Create()
{
Dispose();
handle = CreateIconIndirect(ref iconInfo);
cursor = new Cursor(handle);
}
///
/// free the used handles
///
public void Dispose()
{
GC.SuppressFinalize( this );
if(cursor != null) cursor.Dispose();
if (handle != IntPtr.Zero)
DestroyIcon(handle);
}
///
/// The Cursor-Object you can use
///
public Cursor Cursor
{
get
{
return cursor;
}
}
}
}
//de functie die object aanmaakt
private void PrepareCustomCursor()
{
Bitmap bm = new Bitmap(1000, 1000);
Graphics g = Graphics.FromImage(bm);
GraphicsPath gp = new GraphicsPath();
Point lo = new Point(0, 10);
Point lb = new Point(0, 0);
Point rb = new Point(10, 0);
Point ro = new Point(10, 10);
gp.AddLine(lb, rb);
gp.AddLine(rb, ro);
gp.AddLine(ro, lo);
gp.AddLine(lo, lb);
Pen pen = new Pen(Color.Black, 1);
g.DrawPath(pen, gp);
g.Dispose();
gp.Dispose();
pen.Dispose();
if(CursorPixelRectangle != null) CursorPixelRectangle.Dispose();
CursorPixelRectangle = new clsBitmapCursor(bm);
bm.Dispose();
}
Ik zit met een serieus c#.net probleem nl een memory leak ifv unmanaged code.
Voor een applicatie moet ik custom cursors maken adhv bitmaps. Ik heb een klasse gevonden op codeproject en aangepast naar mijn noden, die gebruik maakt van unmanaged functies. Daar dit de enige manier is om het te doen zonder .cur files aan te maken.
In men applicatie wordt dit gebruikt als tooltip. Daarom moet dit object erg vaak aangemaakt worden en eigenlijk altijd een andere bitmap tonen.
Het probleem zit in het afbreken van het object voordat een nieuw aangemaakt moet worden. Dit gebeurt niet correct, waardoor mijn ram in no time volzit.
Aangezien ik zo goed als geen kennis heb van unmanaged code en hoe erop te debuggen, zit ik redelijk vast.
Ik heb een mini vb project gemaakt die de klasse bevat en het probleem duidelijk aantoont. OnmouseMove worden continue nieuwe objecten aangemaakt waardoor uw ram aan +- 1MB/sec toeslibt.
Alvast bedankt om het even te bekijken
het project vind je hier: *snip*
De klasse:
using System;
using System.Windows.Forms;
using System.Drawing;
using System.Runtime.InteropServices;
namespace WindowsFormsApplication1
{
///
/// Creates a Cursor from any bitmap. You can use the alpha-channel
/// for transparency effects.
///
/// you can use the API function CreateIconIndirect to create any cursor from a bitmap.
/// There is not size limit so you can draw the item into a bitmap and convert it into a cursor.
/// The following class can be used for that. An instance of this class must exists as long as the cursor is displayed.
///
public class clsBitmapCursor : IDisposable
{
#region Win-API imports
///
/// API-Structure ICONINFO
///
///
[StructLayout(LayoutKind.Sequential)]
public struct ICONINFO
{
public bool fIcon;
public uint xHotspot;
public uint yHotspot;
public IntPtr hbmMask;
public IntPtr hbmColor;
}
///
/// API function CreateIconIndirect
///
[System.Runtime.InteropServices.DllImport("USER32.DLL")]
public static extern IntPtr CreateIconIndirect( ref ICONINFO iconinfo );
///
/// API function DestryIcon
///
[System.Runtime.InteropServices.DllImport("USER32.DLL")]
public static extern bool DestroyIcon( IntPtr hIcon );
#endregion
private ICONINFO iconInfo;
private Cursor cursor = null;
private IntPtr handle = IntPtr.Zero;
#region constructors and destructor
public clsBitmapCursor(System.Drawing.Bitmap bmp)
{
iconInfo = new ICONINFO();
iconInfo.fIcon = false;
iconInfo.xHotspot = 0;
iconInfo.yHotspot = 0;
iconInfo.hbmMask = bmp.GetHbitmap();
iconInfo.hbmColor = bmp.GetHbitmap();
Create();
}
public clsBitmapCursor( System.Drawing.Bitmap bmp, uint HotSpotX, uint HotSpotY )
{
iconInfo = new ICONINFO();
iconInfo.fIcon = false;
iconInfo.xHotspot = HotSpotX;
iconInfo.yHotspot = HotSpotY;
iconInfo.hbmMask = bmp.GetHbitmap();
iconInfo.hbmColor = bmp.GetHbitmap();
Create();
}
///
/// Creates a cursor from a bitmap and combines it with another cursor.
///
public clsBitmapCursor(System.Drawing.Bitmap bmp, Cursor Cursor)
{
iconInfo = new ICONINFO();
iconInfo.fIcon = false;
iconInfo.xHotspot = 0;
iconInfo.yHotspot = 0;
using( System.Drawing.Bitmap bmpdup = bmp.Clone() as System.Drawing.Bitmap )
{
using( Graphics g = Graphics.FromImage( bmpdup ) )
{
Cursor.Draw( g, new Rectangle( new Point( 0, 0 ), Cursor.Size ) );
}
iconInfo.hbmMask = bmpdup.GetHbitmap();
iconInfo.hbmColor = bmpdup.GetHbitmap();
Create();
}
}
///
/// destructor
///
~clsBitmapCursor()
{
Dispose();
}
#endregion
public void moveHotspot(int x, int y)
{
iconInfo.xHotspot = (uint)x;
iconInfo.yHotspot = (uint)y;
Create();
}
private void Create()
{
Dispose();
handle = CreateIconIndirect(ref iconInfo);
cursor = new Cursor(handle);
}
///
/// free the used handles
///
public void Dispose()
{
GC.SuppressFinalize( this );
if(cursor != null) cursor.Dispose();
if (handle != IntPtr.Zero)
DestroyIcon(handle);
}
///
/// The Cursor-Object you can use
///
public Cursor Cursor
{
get
{
return cursor;
}
}
}
}
//de functie die object aanmaakt
private void PrepareCustomCursor()
{
Bitmap bm = new Bitmap(1000, 1000);
Graphics g = Graphics.FromImage(bm);
GraphicsPath gp = new GraphicsPath();
Point lo = new Point(0, 10);
Point lb = new Point(0, 0);
Point rb = new Point(10, 0);
Point ro = new Point(10, 10);
gp.AddLine(lb, rb);
gp.AddLine(rb, ro);
gp.AddLine(ro, lo);
gp.AddLine(lo, lb);
Pen pen = new Pen(Color.Black, 1);
g.DrawPath(pen, gp);
g.Dispose();
gp.Dispose();
pen.Dispose();
if(CursorPixelRectangle != null) CursorPixelRectangle.Dispose();
CursorPixelRectangle = new clsBitmapCursor(bm);
bm.Dispose();
}