自定的在.Net Compact Framework中进行截屏的函数,运行一段时间后,程序死了.
最近由于项目需要写了一个在.Net Compact Framework中进行截屏的函数,主程序定时的去调用这个函数.函数调用可获得位图数据,只是每次程序运行一段时间后,程序就死了.多谢大家帮我看看这个函数,是不是那有问题,或用内存泄漏的地方.因为当中使用了非托管代码.
函数代码如下 .
/// <summary>
///
/// </summary>
/// <param name="hReal">窗口句柄</param>
/// <param name="rect">窗口坐标区域</param>
/// <returns></returns>
public static byte [] SnapshotToBit(IntPtr hReal, Rectangle rect)
{
byte[] data = null;
try
{
int nWidth = rect.Width;
int nHeight = rect.Height;
IntPtr hDCInk = IntPtr.Zero, hMemDC = IntPtr.Zero;
//通过窗口句柄获得窗口所属的DC句柄
hDCInk = GetDC(hReal);
//用CreateCompatibleDC建了一个Memory DC
hMemDC = CreateCompatibleDC(hDCInk);
try
{
BITMAPINFOHEADER bi = new BITMAPINFOHEADER();
bi.biSize = (uint)Marshal.SizeOf(bi);
//bi.biBitCount = 24; // Creating RGB bitmap. The following three members don't matter
bi.biBitCount = 16; // Creating RGB bitmap. The following three members don't matter
bi.biClrUsed = 0;
bi.biClrImportant = 0;
bi.biCompression = 0;
bi.biHeight = nHeight;
bi.biWidth = nWidth;
bi.biPlanes = 1;
int cb = (int)(bi.biHeight * bi.biWidth * bi.biBitCount / 8); //8 is bits per byte
bi.biSizeImage = (uint)cb;
bi.biXPelsPerMeter = 0xb12; // 72 ppi, 96 would work well too
bi.biYPelsPerMeter = 0xb12; // 72 ppi
IntPtr pBits = IntPtr.Zero;
//Allocate memory for bitmap bits
IntPtr pBI = LocalAlloc(GPTR, (int)bi.biSize);
// Not sure if this needed - simply trying to keep marshaller happy
Marshal.StructureToPtr(bi, pBI, false);
//This will return IntPtr to actual DIB bits in pBits
IntPtr hBmp = CreateDIBSection(hDCInk, pBI, 0, ref pBits, IntPtr.Zero, 0);
//Marshall back - now we have BITMAPINFOHEADER correctly filled in
Marshal.PtrToStructure(pBI, bi);
BITMAPINFOHEADER biNew = (BITMAPINFOHEADER)Marshal.PtrToStructure(pBI, typeof( BITMAPINFOHEADER ));
LocalFree(pBI);
//Usual stuff
IntPtr hOldBitmap = SelectObject(hMemDC, hBmp);
try
{
//Grab bitmap
int nRet = BitBlt(hMemDC, 0, 0, nWidth, nHeight, hDCInk, 0, 0, SRCCOPY);
// Allocate memory for a copy of bitmap bits
byte[] RealBits = new byte[cb];
// And grab bits from DIBSestion data
Marshal.Copy(pBits, RealBits, 0, cb);
// This simply creates valid bitmap file header, so it can be saved to disk
BITMAPFILEHEADER bfh = new BITMAPFILEHEADER();
bfh.bfSize = (uint)cb + 0x36; // Size of header + size of BITMAPINFOHEADER size of bitmap bits
bfh.bfType = 0x4d42; //BM
bfh.bfOffBits = 0x36; //
int HdrSize = 14;
byte[] header = new byte[HdrSize];
BitConverter.GetBytes(bfh.bfType).CopyTo(header, 0);
BitConverter.GetBytes(bfh.bfSize).CopyTo(header, 2);
BitConverter.GetBytes(bfh.bfOffBits).CopyTo(header, 10);
//Allocate enough memory for complete bitmap file
data = new byte[cb+0x36];
//BITMAPFILEHEADER
header.CopyTo(data, 0);
//BITMAPINFOHEADER
header = new byte[Marshal.SizeOf(bi)];
IntPtr pHeader = LocalAlloc(GPTR, Marshal.SizeOf(bi));
Marshal.StructureToPtr(biNew, pHeader, false);
Marshal.Copy(pHeader, header, 0, Marshal.SizeOf(bi));
LocalFree(pHeader);
header.CopyTo(data, HdrSize);
//Bitmap bits
RealBits.CopyTo(data, 0x36);
//data = null;
}
catch(Exception exc)
{
}
finally
{
DeleteObject(SelectObject(hMemDC, hOldBitmap));
LocalFree(pBI);
}
}
catch(Exception exc)
{
}
finally
{
if (hMemDC != IntPtr.Zero)
{
DeleteDC(hMemDC);
}
if(hDCInk != IntPtr.Zero)
{
ReleaseDC(hDCInk);
}
}
}
catch(Exception exc)
{
}
finally
{
}
return data;
}