将图像从非托管图像列表转储到磁盘

时间:2012-10-24 14:49:56

标签: c# .net winapi pinvoke unmanaged

我正在从USB设备移植C ++ SDK以通过pinvoke在C#中使用而且到目前为止我已经取得了很好的进展,现在的问题是建立一个我可以用来附加的图像列表的功能使用SetImageList等函数的其他控件。

我想要做的是将此列表中的所有图像保存到磁盘并稍后使用。

还有其他函数返回此列表中的paraticular图像的索引,因此我可以传递此索引,然后将图像保存到磁盘。

2 个答案:

答案 0 :(得分:2)

使用CImageList class实例(通过调用Detach method实例上的GetImageList method上的CListCtrl获得),您可以获得Detach method实例1}}通过调用Platform Invocation Services (P/Invoke) layer来处理。

从那里,您可以通过IntPtr调用基础Windows API。

以下假设您在ImageList_GetImageCount function中有HIMAGELIST指针:

HIMAGELIST

首先,您需要在.NET中声明ImageList_GetImageInfo

IntPtr imageList = ...;

当然,将该调用的结果存储在变量中:

[DllImport("Comctl32.dll", SetLastError = true)]
static extern int ImageList_GetImageCount(IntPtr himl);

您还需要能够获取有关每张图片的详细信息,因此您需要拨打IMAGEINFO structure

int imageCount = ImageList_GetImageCount(imageList);

通过这些,您可以开始循环以获取有关图像的信息:

[StructLayout(LayoutKind.Sequential)]
struct RECT
{
    public int left, top, right, bottom;
}

[StructLayout(LayoutKind.Sequential)]
struct IMAGEINFO
{
    public IntPtr hbmImage;
    public IntPtr hbmMask;
    public int Unused1;
    public int Unused2;
    public RECT rcImage;
}

[DllImport("Comctl32.dll", SetLastError = true)]
static extern bool ImageList_GetImageInfo(IntPtr himl, int i,
    ref IMAGEINFO pImageInfo);

请注意,HBITMAP中有一个字段,其中包含指向位图的指针(for (int i = 0; i < imageCount; ++i) { // The image info. var imageInfo = new IMAGEINFO(); // Get the call to ImageList_GetImageInfo. if (!ImageList_GetImageInfo(imageList, i, ref imageInfo) throw new System.ComponentModel.Win32Exception(); 字段)。

这是Bitmap class句柄的句柄,在FromHbitmap method中具有.NET中的等价句柄。您可以通过调用Image class上的静态Save method来翻译两者(是的,奇怪的是它不在hbmImage类上):

Bitmap

获得 using (Bitmap bitmap = Image.FromHbitmap(imageInfo.hbmImage)) { 实例后,可以调用每个实例上的ImageList class将其转储到磁盘:

Bitmap

请注意,.NET中有{{3}},但是无法将 bitmap.Save("<need to generate a filename>.<and extension>"); } } 句柄传递给托管实现(这会使这更容易)。

答案 1 :(得分:0)

实际上,可以从HIMAGELIST句柄创建托管的ImageList。 我测试了这2分钟。前:

Public Shared Function ImageList_FromHIMAGELIST(cxcy As Integer, uFlags As UInteger, initSize As Integer, growSize As Integer, _
                                         hicons() As IntPtr) As ImageList

    Dim himl = ImageList_Create(cxcy, cxcy, uFlags, initSize, growSize)
    If Not IsNothing(hicons) AndAlso hicons.Length > 0 Then
        For Each HIcon As IntPtr In hicons
            ImageList_ReplaceIcon(himl, -1, HIcon)
        Next
    End If
    Dim NativeILType As Type = _
        GetType(Button).Assembly.GetType("System.Windows.Forms.ImageList+NativeImageList", False, True)
    If IsNothing(NativeILType) Then
        Return Nothing
    Else
        Dim natObj As Object = _
            Activator.CreateInstance( _
                NativeILType, BindingFlags.Instance Or BindingFlags.NonPublic, Nothing, {himl}, Nothing)


        If Not IsNothing(natObj) Then
            Dim iml As New ImageList With {.ImageSize = New Size(cxcy, cxcy)}
            iml.GetType.InvokeMember("nativeImageList", _
                                     BindingFlags.NonPublic Or BindingFlags.Instance Or BindingFlags.SetField, _
                                      Nothing, iml, {natObj})
            Return iml
        End If
    End If
    Return Nothing
End Function