C#でimageres.dll.mun
からProgressRingのリソースのPNGデータを読み込むサンプルコードです。実際には複数のPNGリソースが保管されているため、代表としてリソースID 5021を読み込んでいます。
Win32APIのLockResource
関数はリソースデータのアドレスを返すため、通常はバイト配列にMarshal.Copy
した後MemoryStream
を介してImage
クラスのインスタンスを作成できます。unsafe
環境ではアドレスを直接UnmanagedMemoryStream
に渡してImage
クラスのインスタンスを作成できます。
非unsafe
版
using System; using System.ComponentModel; using System.Drawing; using System.IO; using System.Runtime.InteropServices; using System.Windows.Forms; // DLLの場所をシステムフォルダに限定(DLLハイジャック対策) [assembly: DefaultDllImportSearchPaths(DllImportSearchPath.System32)] // リソースファイルからProgressRingのPNGデータを読み込む。 using var imageResDllMunHandle = SafeLibraryHandle.Load( @"SystemResources\imageres.dll.mun"); var pngData = Utility.LoadResource(imageResDllMunHandle, 5021, "PNG"); // ProgressRingのPNGデータから画像を作成する。 using var pngImage = Utility.CreateImageFromByteArray(pngData); // ProgressRingの画像をフォームへ表示する。 var mainForm = new Form(); var pictureBox = new PictureBox(); pictureBox.Image = pngImage; pictureBox.AutoSize = true; mainForm.Controls.Add(pictureBox); Application.Run(mainForm); static class Utility { /// <summary> /// バイト配列からImageインスタンスを返します。 /// </summary> public static Image CreateImageFromByteArray(byte[] data) { using var stream = new MemoryStream(data, false); return Image.FromStream(stream); } /// <summary> /// モジュールのリソースデータを読み込みます。 /// </summary> /// <remarks> /// モジュールが解放されても使用できるように関数はバイト配列を返します。 /// </remarks> public static byte[] LoadResource(SafeHandle handle, ushort id, string type) { return LoadResource(handle, "#" + id, type); } /// <summary> /// モジュールのリソースデータを読み込みます。 /// </summary> /// <remarks> /// モジュールが解放されても使用できるように関数はバイト配列を返します。 /// </remarks> public static byte[] LoadResource(SafeHandle handle, string name, string type) { var resInfoHandle = NativeMethods.FindResourceW(handle, name, type); if (resInfoHandle == default) throw new Win32Exception(); var resDataHandle = NativeMethods.LoadResource(handle, resInfoHandle); if (resDataHandle == default) throw new Win32Exception(); var resSize = NativeMethods.SizeofResource(handle, resInfoHandle); if (resSize == default) throw new Win32Exception(); var resPointer = NativeMethods.LockResource(resDataHandle); if (resPointer == default) throw new Win32Exception(); var buffer = new byte[resSize]; Marshal.Copy(resPointer, buffer, 0, buffer.Length); return buffer; } private static class NativeMethods { [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode, ExactSpelling = true)] public static extern IntPtr FindResourceW(SafeHandle hModule, [In] string lpName, [In] string lpType); [DllImport("kernel32.dll", SetLastError = true)] public static extern IntPtr LoadResource(SafeHandle hModule, IntPtr hResInfo); [DllImport("kernel32.dll", SetLastError = true)] public static extern IntPtr LockResource(IntPtr hResData); [DllImport("kernel32.dll", SetLastError = true)] public static extern uint SizeofResource(SafeHandle hModule, IntPtr hResInfo); } } /// <summary> /// ライブラリハンドルを安全に管理します。 /// </summary> sealed class SafeLibraryHandle : SafeHandle { private SafeLibraryHandle() : base(default, false) { } public SafeLibraryHandle(IntPtr handle, bool ownsHandle) : base(handle, ownsHandle) { } protected override bool ReleaseHandle() { NativeLibrary.Free(handle); return true; } public override bool IsInvalid => handle == default; public static SafeLibraryHandle Load(string path) { IntPtr handle = default; try { handle = NativeLibrary.Load(path); return new SafeLibraryHandle(handle, true); } catch { NativeLibrary.Free(handle); throw; } } }
unsafe
版
using System; using System.ComponentModel; using System.Drawing; using System.IO; using System.Runtime.InteropServices; using System.Windows.Forms; // DLLの場所をシステムフォルダに限定(DLLハイジャック対策) [assembly: DefaultDllImportSearchPaths(DllImportSearchPath.System32)] // リソースファイルからProgressRingのPNGデータを読み込む。 using var imageResDllMunHandle = SafeLibraryHandle.Load( @"SystemResources\imageres.dll.mun"); var pngImage = Utility.LoadResourceAsImage(imageResDllMunHandle, 5021, "PNG"); // ProgressRingの画像をフォームへ表示する。 var mainForm = new Form(); var pictureBox = new PictureBox(); pictureBox.Image = pngImage; pictureBox.AutoSize = true; mainForm.Controls.Add(pictureBox); Application.Run(mainForm); static class Utility { /// <summary> /// モジュールのリソースデータをImageクラスのインスタンスとして読み込みます。 /// </summary> /// <remarks> /// モジュールが解放されても使用できるように関数はバイト配列を返します。 /// </remarks> public static Image LoadResourceAsImage(SafeHandle handle, ushort id, string type) { return LoadResourceAsImage(handle, "#" + id, type); } /// <summary> /// モジュールのリソースデータをImageクラスのインスタンスとして読み込みます。 /// </summary> /// <remarks> /// モジュールが解放されても使用できるように関数はバイト配列を返します。 /// </remarks> public static Image LoadResourceAsImage(SafeHandle handle, string name, string type) { var resInfoHandle = NativeMethods.FindResourceW(handle, name, type); if (resInfoHandle == default) throw new Win32Exception(); var resDataHandle = NativeMethods.LoadResource(handle, resInfoHandle); if (resDataHandle == default) throw new Win32Exception(); var resSize = NativeMethods.SizeofResource(handle, resInfoHandle); if (resSize == default) throw new Win32Exception(); var resPointer = NativeMethods.LockResource(resDataHandle); if (resPointer == default) throw new Win32Exception(); unsafe { using var stream = new UnmanagedMemoryStream((byte*)resPointer, resSize); return Image.FromStream(stream); } } private static class NativeMethods { [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode, ExactSpelling = true)] public static extern IntPtr FindResourceW(SafeHandle hModule, [In] string lpName, [In] string lpType); [DllImport("kernel32.dll", SetLastError = true)] public static extern IntPtr LoadResource(SafeHandle hModule, IntPtr hResInfo); [DllImport("kernel32.dll", SetLastError = true)] public static extern IntPtr LockResource(IntPtr hResData); [DllImport("kernel32.dll", SetLastError = true)] public static extern uint SizeofResource(SafeHandle hModule, IntPtr hResInfo); } } /// <summary> /// ライブラリハンドルを安全に管理します。 /// </summary> sealed class SafeLibraryHandle : SafeHandle { private SafeLibraryHandle() : base(default, false) { } public SafeLibraryHandle(IntPtr handle, bool ownsHandle) : base(handle, ownsHandle) { } protected override bool ReleaseHandle() { NativeLibrary.Free(handle); return true; } public override bool IsInvalid => handle == default; public static SafeLibraryHandle Load(string path) { IntPtr handle = default; try { handle = NativeLibrary.Load(path); return new SafeLibraryHandle(handle, true); } catch { NativeLibrary.Free(handle); throw; } } }