public override void Start(int delay, int left, int top, int width, int height, double scale, ProjectInfo project) { base.Start(delay, left, top, width, height, scale, project); _infoHeader = new Util.Native.BitmapInfoHeader(); _infoHeader.biSize = (uint)Marshal.SizeOf(_infoHeader); _infoHeader.biBitCount = 24; //Without alpha channel. _infoHeader.biClrUsed = 0; _infoHeader.biClrImportant = 0; _infoHeader.biCompression = 0; _infoHeader.biHeight = -StartHeight; //Negative, so the Y-axis will be positioned correctly. _infoHeader.biWidth = StartWidth; _infoHeader.biPlanes = 1; //This was working with 32 bits: 3L * Width * Height; _byteLength = (StartWidth * _infoHeader.biBitCount + 31) / 32 * 4 * StartHeight; //Due to a strange behavior with the GetDiBits method while the cursor is IBeam, it's best to use 24 bits, to ignore the alpha values. //This capture mode ignores the alpha value. project.BitDepth = 24; _fileStream = new FileStream(project.CachePath, FileMode.Create, FileAccess.Write, FileShare.None); _bufferedStream = new BufferedStream(_fileStream, UserSettings.All.MemoryCacheSize * 1048576); //Each 1 MB has 1_048_576 bytes. _compressStream = new DeflateStream(_bufferedStream, UserSettings.All.CaptureCompression, true); }
public void Other() { var hDC = Util.Native.GetWindowDC(IntPtr.Zero); var hMemDC = Util.Native.CreateCompatibleDC(hDC); var bi = new Util.Native.BitmapInfoHeader(); bi.biSize = (uint)Marshal.SizeOf(bi); bi.biBitCount = 24; //Creating RGB bitmap. The following three members don't matter bi.biClrUsed = 0; bi.biClrImportant = 0; bi.biCompression = 0; bi.biHeight = Height; bi.biWidth = Width; bi.biPlanes = 1; var cb = (int)(bi.biHeight * bi.biWidth * bi.biBitCount / 8); //8 is bits per byte. bi.biSizeImage = (uint)(((((bi.biWidth * bi.biBitCount) + 31) & ~31) / 8) * bi.biHeight); //bi.biXPelsPerMeter = XPelsPerMeter; //bi.biYPelsPerMeter = YPelsPerMeter; bi.biXPelsPerMeter = 96; bi.biYPelsPerMeter = 96; var pBits = IntPtr.Zero; //Allocate memory for bitmap bits var pBI = Util.Native.LocalAlloc((uint)Util.Native.LocalMemoryFlags.LPTR, new UIntPtr(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 var hBmp = Util.Native.CreateDIBSection(hDC, ref pBI, 0, out pBits, IntPtr.Zero, 0); //Marshall back - now we have BitmapInfoHeader correctly filled in Marshal.PtrToStructure(pBI, bi); var biNew = (Util.Native.BitmapInfoHeader)Marshal.PtrToStructure(pBI, typeof(Util.Native.BitmapInfoHeader)); //Usual stuff var hOldBitmap = Util.Native.SelectObject(hMemDC, hBmp); //Grab bitmap var nRet = Util.Native.BitBlt(hMemDC, 0, 0, bi.biWidth, bi.biHeight, hDC, Left, Top, Util.Native.CopyPixelOperation.SourceCopy | Util.Native.CopyPixelOperation.CaptureBlt); // Allocate memory for a copy of bitmap bits var 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 var bfh = new Util.Native.BitmapFileHeader(); bfh.bfSize = (uint)cb + 0x36; // Size of header + size of Native.BitmapInfoHeader size of bitmap bits bfh.bfType = 0x4d42; //BM bfh.bfOffBits = 0x36; // var HdrSize = 14; var 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 var data = new byte[cb + bfh.bfOffBits]; //BITMAPFILEHEADER header.CopyTo(data, 0); //BitmapInfoHeader header = new byte[Marshal.SizeOf(bi)]; var pHeader = Util.Native.LocalAlloc((uint)Util.Native.LocalMemoryFlags.LPTR, new UIntPtr((uint)Marshal.SizeOf(bi))); Marshal.StructureToPtr(biNew, pHeader, false); Marshal.Copy(pHeader, header, 0, Marshal.SizeOf(bi)); Util.Native.LocalFree(pHeader); header.CopyTo(data, HdrSize); //Bitmap bits RealBits.CopyTo(data, (int)bfh.bfOffBits); //Native.SelectObject(_compatibleDeviceContext, _oldBitmap); //Native.DeleteObject(_compatibleBitmap); //Native.DeleteDC(_compatibleDeviceContext); //Native.ReleaseDC(_desktopWindow, _windowDeviceContext); Util.Native.SelectObject(hMemDC, hOldBitmap); Util.Native.DeleteObject(hBmp); Util.Native.DeleteDC(hMemDC); Util.Native.ReleaseDC(IntPtr.Zero, hDC); }