/// /// Class to manage access to External Win32 Resources /// using System; using System.Drawing; using System.Drawing.Imaging; using System.Runtime.InteropServices; using System.IO; internal class ResourceLibrary : IDisposable { #region ALL Code private IntPtr hLib = IntPtr.Zero; private string filename = ""; #region Unmanged Code private const int SRCCOPY = 0xCC0020; private const int DONT_RESOLVE_DLL_REFERENCES = 0x1; private const int LOAD_LIBRARY_AS_DATAFILE = 0x2; private const int LOAD_WITH_ALTERED_SEARCH_PATH = 0x8; public enum ImageType { IMAGE_BITMAP = 0, IMAGE_ICON = 1, IMAGE_CURSOR = 2 } [Flags] public enum ImageLoadOptions { LR_DEFAULTCOLOR = 0, LR_MONOCHROME = 0x1, LR_COLOR = 0x2, LR_COPYRETURNORG = 0x4, LR_COPYDELETEORG = 0x8, LR_LOADFROMFILE = 0x10, LR_LOADTRANSPARENT = 0x20, LR_DEFAULTSIZE = 0x40, LR_VGACOLOR = 0x80, LR_LOADMAP3DCOLORS = 0x1000, LR_CREATEDIBSECTION = 0x2000, LR_COPYFROMRESOURCE = 0x4000, LR_SHARED = 0x8000 } [StructLayout(LayoutKind.Sequential, Pack=0)] private struct BITMAP { public Int32 bmType; public Int32 bmWidth; public Int32 bmHeight; public Int32 bmWidthBytes; public Int16 bmPlanes; public Int16 bmBitsPixel; public IntPtr bmBits; } [DllImport("gdi32", CharSet=CharSet.Auto, EntryPoint="GetObject")] private static extern int GetObjectBitmap(IntPtr hObject, int nCount, ref BITMAP lpObject ); [DllImport("gdi32")] private static extern int BitBlt(IntPtr hDestDC, int x , int y , int nWidth , int nHeight , IntPtr hSrcDC, int xSrc , int ySrc , int dwRop); [DllImport("kernel32", CharSet=CharSet.Auto)] private extern static IntPtr LoadLibraryEx(string lpLibFileName, IntPtr hFile, int dwFlags); [DllImport("kernel32", SetLastError = true)] private extern static IntPtr FindResource(IntPtr hModule, string lpName, int lpType); [DllImport("kernel32", EntryPoint = "LockResource")] private extern static IntPtr LockResource(IntPtr hGlobal); [DllImport("kernel32", SetLastError = true)] private extern static IntPtr LoadResource(IntPtr hModule, IntPtr hResInfo); [DllImport("kernel32", SetLastError = true)] private extern static uint SizeofResource(IntPtr hModule, IntPtr hResInfo); [DllImport("kernel32", CharSet=CharSet.Auto)] private extern static int FreeLibrary(IntPtr hLibModule); [DllImport("user32", CharSet=CharSet.Auto, EntryPoint="LoadImage")] private extern static IntPtr LoadImageLong(IntPtr hInst, int lpsz, int uType, int cX, int cY , int uFlags); [DllImport("user32", CharSet=CharSet.Auto, EntryPoint="LoadImage")] private extern static IntPtr LoadImageString(IntPtr hInst, string lpsz, int uType, int cX, int cY , int uFlags); [DllImport("gdi32")] private static extern IntPtr SelectObject (IntPtr hDC, IntPtr hObject); [DllImport("gdi32")] public static extern int DeleteObject(IntPtr hObject); [DllImport("gdi32")] private static extern IntPtr CreateCompatibleDC(IntPtr hDC); [DllImport("user32")] public static extern bool DestroyIcon(IntPtr hIcon); [DllImport("gdi32")] private static extern int DeleteDC(IntPtr hdc); [DllImport("user32")] private static extern IntPtr GetDesktopWindow(); [DllImport("user32")] private static extern IntPtr GetDC(IntPtr hWnd); [DllImport("user32")] private static extern int ReleaseDC (IntPtr hWnd, IntPtr hDC); #endregion /// /// Construct a new instance of the class /// public ResourceLibrary() { } /// /// Dispose and clear up any resources /// public void Dispose() { ClearUp(); } /// /// Set the filename of the external library /// public string Filename { get { return filename; } set { filename = value; Load(); } } /// /// Gets the handle to the library /// public IntPtr Handle { get { return hLib; } } /// /// Gets a stream resource by name /// /// Name to get /// MemoryStream if successful, otherwise null public byte[] GetResourceStream( string resourceId ) { byte[] result = null; if (!hLib.Equals(IntPtr.Zero)) { IntPtr hRes = FindResource(hLib, resourceId, 100); if (!hRes.Equals(IntPtr.Zero)) { IntPtr hLoadedRes = LoadResource(hLib, hRes); if (!hLoadedRes.Equals(IntPtr.Zero)) { IntPtr ptrRes = LockResource(hLoadedRes); if (!ptrRes.Equals(IntPtr.Zero)) { uint size = SizeofResource(hLib, hRes); if (size > 0) { result = new byte[size]; Marshal.Copy(ptrRes, result, 0, (int) size); } } } } } return result; } /// /// Gets an image resource by name /// /// Name to get /// Image type to get /// Options to use /// Handle to image resource if successful, otherwise IntPtr.Zero public IntPtr GetResource( string name, ImageType imageType, ImageLoadOptions options ) { IntPtr handle = IntPtr.Zero; if (!hLib.Equals(IntPtr.Zero)) { handle = LoadImageString(hLib, name, (int) imageType, 0, 0, (int) options); } return handle; } /// /// Loads the library. /// private void Load() { ClearUp(); hLib = LoadLibraryEx(filename, IntPtr.Zero, LOAD_LIBRARY_AS_DATAFILE); } /// /// Clears up any resources associated with the class. /// private void ClearUp() { if (!hLib.Equals(IntPtr.Zero)) { FreeLibrary(hLib); hLib = IntPtr.Zero; } } /// /// Converts a Windows DIBSection object to a Bitmap. /// /// Handle to a Windows DIBSection. /// Bitmap containing the DIBSection picture. public static Bitmap DibToBitmap( IntPtr hDib ) { BITMAP tBM = new BITMAP(); GetObjectBitmap(hDib, Marshal.SizeOf(tBM), ref tBM); Bitmap bm = new Bitmap(tBM.bmWidth, tBM.bmHeight); // set the bitmap's data to the data from // the DIB: if (tBM.bmBitsPixel == 32) { // Bizarre but true: you *must* clone the newly created // bitmap to get one with the correct pixel format, even // if you attempted to create the original one with the // correct format... bm = bm.Clone(new Rectangle(0, 0, tBM.bmWidth, tBM.bmHeight), PixelFormat.Format32bppArgb); // Lock the bitmap bits BitmapData destData = bm.LockBits( new Rectangle(0, 0, bm.Width, bm.Height), ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb); int destWidth = destData.Stride; IntPtr destScan0 = destData.Scan0; unsafe { byte * pDest = (byte *) (void *) destScan0; // The DIB is upside down compared to a GDI+ bitmap pDest += ((bm.Width * 4) * (bm.Height - 1)); byte * pSrc = (byte *) (void *) tBM.bmBits; for (int y = 0; y < bm.Height; ++y) { for (int x = 0; x < bm.Width; ++x) { pDest[0] = pSrc[0]; // blue pDest[1] = pSrc[1]; // green pDest[2] = pSrc[2]; // red pDest[3] = pSrc[3]; // alpha // Move to next BGRA pDest += 4; pSrc += 4; } pDest -= (bm.Width * 8); } } bm.UnlockBits(destData); } else { // Easier to just copy src -> dst using GDI. // Put the DIB into a DC: IntPtr hWndDesktop = GetDesktopWindow(); IntPtr hDCComp = GetDC(hWndDesktop); IntPtr hDCSrc = CreateCompatibleDC(hDCComp); ReleaseDC(hWndDesktop, hDCComp); IntPtr hBmpOld = SelectObject(hDCSrc, hDib); Graphics gfx = Graphics.FromImage(bm); IntPtr hDCDest = gfx.GetHdc(); BitBlt(hDCDest, 0, 0, tBM.bmWidth, tBM.bmHeight, hDCSrc, 0, 0, SRCCOPY); gfx.ReleaseHdc(hDCDest); SelectObject(hDCSrc, hBmpOld); DeleteDC(hDCSrc); } return bm; } #endregion }