///
/// 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
}