2016-09-16 88 views
0

所以我尝试从dll文件加载图像资源。为此,我创建了方法GDI +调用LoadImage返回的句柄上的Image.FromHBitmap时出错

static Bitmap GetImageResource(IntPtr handle, string resourceId) 
{ 
    IntPtr img_ptr = NativeMethods.LoadImage(handle, "#" + resourceId, IMAGE_ICON, 16, 16, 0); 

    if (img_ptr == IntPtr.Zero) 
     throw new System.ComponentModel.Win32Exception((int)NativeMethods.GetLastError()); 

    return Image.FromHbitmap(img_ptr); 
} 

从给定句柄和资源ID的DLL中加载图像资源。根据this question I asked yesterday,我必须在id前加一个#,这是我所做的。现在的LoadImage返回的句柄不为零了,但是当我尝试使用这个句柄创建位图图像 Image.FromHbitmap我得到了System.Runtime.InteropServices.ExternalException

GDI中发生一般性错误+

(或我没有收到英文的消息,所以我大致翻译了它)

我已经阅读thisthis的问题,但他们没有帮助我。

这是为什么?在此先感谢

+0

这完全正常,您正在加载图标,而不是图像。使用Icon.FromHandle()代替。之后,在确定Icon对象不能再次使用后,必须使用DestroyIcon再次销毁该图标。 –

回答

0

如果DLL是一个.NET组件,您可以拨打Assembly.GetManifestResourceStream,像这样:

public static Bitmap getBitmapFromAssemblyPath(string assemblyPath, string resourceId) { 
    Assembly assemb = Assembly.LoadFrom(assemblyPath); 
    Stream stream = assemb.GetManifestResourceStream(resourceId); 
    Bitmap bmp = new Bitmap(stream); 
    return bmp; 
} 

如果是本地的dll(未装配),你将不得不使用互操作,而不是。你有一个解决方案here,并且可以总结如下:加入

[DllImport("kernel32.dll", SetLastError = true)] 
static extern IntPtr LoadLibraryEx(string lpFileName, IntPtr hFile, uint dwFlags); 

[DllImport("kernel32.dll")] 
static extern IntPtr FindResource(IntPtr hModule, int lpID, string lpType); 

[DllImport("kernel32.dll", SetLastError = true)] 
static extern IntPtr LoadResource(IntPtr hModule, IntPtr hResInfo); 

[DllImport("kernel32.dll", SetLastError = true)] 
static extern uint SizeofResource(IntPtr hModule, IntPtr hResInfo); 

[DllImport("kernel32.dll", SetLastError=true)] 
[return: MarshalAs(UnmanagedType.Bool)] 
static extern bool FreeLibrary(IntPtr hModule); 

static const int LOAD_LIBRARY_AS_DATAFILE = 0x00000002; 

public static Bitmap getImageFromNativeDll(string dllPath, string resourceName, int resourceId) { 
    Bitmap bmp = null; 
    IntPtr dllHandle = LoadLibraryEx(dllPath, IntPtr.Zero, LOAD_LIBRARY_AS_DATAFILE); 
    IntPtr resourceHandle = FindResource(dllHandle, resourceId, resourceName); 
    uint resourceSize = SizeofResource(dllHandle, resourceHandle); 
    IntPtr resourceUnmanagedBytesPtr = LoadResource(dllHandle, resourceHandle); 

    byte[] resourceManagedBytes = new byte[resourceSize]; 
    Marshal.Copy(resourceUnmanagedBytesPtr, resourceManagedBytes, 0, (int)resourceSize); 
    using (MemoryStream m = new MemoryStream(resourceManagedBytes)) { 
     bmp = (Bitmap)Bitmap.FromStream(m); 
    } 

    FreeLibrary(dllHandle); 

    return bmp; 
} 

任何错误处理,这是不产品代码。

注意:如果你需要一个图标,你可以使用图标构造函数接收流:

using (MemoryStream m = new MemoryStream(resourceManagedBytes)) { 
     bmp = (Icon)new Icon(m); 
    } 

你应该相应改变的返回类型。

+0

“bptr”究竟是什么? –

+1

一个错字。我用适当的变量名称更改了代码。 –

+0

我只有资源的ID,我应该使用什么'resourceName'参数? –