USBデバイスからC++SDKを移植してpinvokeを介してC#で使用していますが、これまでのところ順調に進んでいます。問題は、他のコントロールに接続するために使用できる画像リストを作成する関数にあります。SetImageListなどの関数を使用します。
私がやりたいのは、このリストのすべての画像をディスクに保存し、後で使用することです。
このリスト内に特定の画像のインデックスを返す関数は他にもあるので、このインデックスを渡してから画像をディスクに保存することができます。
CImageList
クラスインスタンス (所有しているインスタンスのメソッドのメソッドを呼び出して取得)をDetach
使用すると、 Detach メソッドを呼び出すことでハンドルを取得できます。GetImageList
CListCtrl
HIMAGELIST
そこから、プラットフォーム呼び出しサービス (P/Invoke) レイヤーを介して、基になる Windows API を呼び出すことができます。
HIMAGELIST
以下は、このポインターが にあると仮定していますIntPtr
。
IntPtr imageList = ...;
まず、 .NETでImageList_GetImageCount
関数を宣言する必要があります。
[DllImport("Comctl32.dll", SetLastError = true)]
static extern int ImageList_GetImageCount(IntPtr himl);
そしてもちろん、その呼び出しの結果を変数に格納します。
int imageCount = ImageList_GetImageCount(imageList);
また、各画像の詳細を取得できる必要があるため、次の呼び出しが必要になりますImageList_GetImageInfo
。
[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);
これらを使用して、ループを開始して画像に関する情報を取得できます。
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();
IMAGEINFO
構造体には、ビットマップへのポインターを含むフィールド (フィールド) があることに注意してくださいhbmImage
。
これはハンドルへのハンドルであり、クラスHBITMAP
.NET に同等のものがあります。クラスで静的メソッドを呼び出すことにより、2 つの間で変換できます (はい、クラスにないのは奇妙です)。Bitmap
FromHbitmap
Image
Bitmap
using (Bitmap bitmap = Image.FromHbitmap(imageInfo.hbmImage))
{
インスタンスを取得したら、各インスタンスでメソッドBitmap
を呼び出してディスクにダンプできます。Save
bitmap.Save("<need to generate a filename>.<and extension>");
}
}
.NET にはImageList
クラスがありますが、マネージ実装にハンドルを渡す方法がないことに注意してくださいHIMAGELIST
(これにより、はるかに簡単になります)。
実際、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