/// <summary> /// Call this method in order to capture a bitmap of the current video window /// TODO - hook up to a button click event /// TODO - give the user the ability to provide a file name /// </summary> /// /// <remarks> /// This is the layout in memory, because this is the layout we need /// on the disk. /// /// <-------------------------- ptrBlock -----------------------------> /// <------- ptrImg -------------------------------> /// | BitmapFileHeader | BitmapInfoHeader | bytes of DIB | /// </remarks> private void TakeImage() { IBasicVideo iBV = (IBasicVideo)vcg.FilgraphManager; int len = 0; // Determine byte count needed to store the Device Independent // Bitmap (DIB) by calling with a null-pointer iBV.GetCurrentImage(ref len, IntPtr.Zero); // Allocate bytes, plus room for a BitmapFileHeader int sizeOfBFH = Marshal.SizeOf(typeof(BITMAPFILEHEADER)); IntPtr ptrBlock = Marshal.AllocCoTaskMem(len + sizeOfBFH); IntPtr ptrImg = new IntPtr(ptrBlock.ToInt64() + sizeOfBFH); try { // Get the DIB iBV.GetCurrentImage(ref len, ptrImg); // Get a copy of the BITMAPINFOHEADER, to be used in the BITMAPFILEHEADER BITMAPINFOHEADER bmih = (BITMAPINFOHEADER)Marshal.PtrToStructure( ptrImg, typeof(BITMAPINFOHEADER)); // Create header for a file of type .bmp BITMAPFILEHEADER bfh = new BITMAPFILEHEADER(); bfh.Type = (UInt16)((((byte)'M') << 8) | ((byte)'B')); bfh.Size = (uint)(len + sizeOfBFH); bfh.Reserved1 = 0; bfh.Reserved2 = 0; bfh.OffBits = (uint)(sizeOfBFH + bmih.Size); // Copy the BFH into unmanaged memory, so that we can copy // everything into a managed byte array all at once Marshal.StructureToPtr(bfh, ptrBlock, false); // Pull it out of unmanaged memory into a managed byte[] byte[] img = new byte[len + sizeOfBFH]; Marshal.Copy(ptrBlock, img, 0, len + sizeOfBFH); // Save the DIB to a file System.IO.File.WriteAllBytes("c:\\cxp.bmp", img); } finally { // Free the unmanaged memory if (ptrBlock != IntPtr.Zero) { Marshal.FreeCoTaskMem(ptrBlock); } } }