如何在 C# 中 FindResource (pinvoke) 字符串资源?
我搜索了很多,但我找不到如何加载ID是字符串的资源。教程 这里 很好,但没有这样做。有人知道怎么做吗?这是我的结构。我想加载 png。
代码:
[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr LoadLibraryEx(string lpFileName, IntPtr hFile, uint dwFlags);
[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr FindResource(IntPtr hModule, string lpName, string lpType);
[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);
const uint LOAD_LIBRARY_AS_DATAFILE = 0x00000002;
void LoadSkin() {
IntPtr hMod = LoadLibraryEx(@"C:\Users\myuser\Desktop\skin.dll", IntPtr.Zero, LOAD_LIBRARY_AS_DATAFILE);
IntPtr hRes = FindResource(hMod, "BACK.PNG", "23");
MessageBox.Show(hRes.ToString()); // <- 0 here.
uint size = SizeofResource(hMod, hRes);
IntPtr pt = LoadResource(hMod, hRes);
Bitmap bmp;
byte[] bPtr = new byte[size];
Marshal.Copy(pt, bPtr, 0, (int) size);
using (MemoryStream m = new MemoryStream(bPtr))
bmp = (Bitmap) Bitmap.FromStream(m);
}
编辑:
修复它。问题出在 FindResource 的声明中。对于我的情况,正确的是:
[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr FindResource(IntPtr hModule, string lpName, uint lpType);
I've searched a lot, but I couldn't find how to load a resource which ID is a string. The tutorial Here is good, but doesn't do that. Does someone know how to make it? Here's my structure. I want to load the pngs.
And the code:
[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr LoadLibraryEx(string lpFileName, IntPtr hFile, uint dwFlags);
[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr FindResource(IntPtr hModule, string lpName, string lpType);
[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);
const uint LOAD_LIBRARY_AS_DATAFILE = 0x00000002;
void LoadSkin() {
IntPtr hMod = LoadLibraryEx(@"C:\Users\myuser\Desktop\skin.dll", IntPtr.Zero, LOAD_LIBRARY_AS_DATAFILE);
IntPtr hRes = FindResource(hMod, "BACK.PNG", "23");
MessageBox.Show(hRes.ToString()); // <- 0 here.
uint size = SizeofResource(hMod, hRes);
IntPtr pt = LoadResource(hMod, hRes);
Bitmap bmp;
byte[] bPtr = new byte[size];
Marshal.Copy(pt, bPtr, 0, (int) size);
using (MemoryStream m = new MemoryStream(bPtr))
bmp = (Bitmap) Bitmap.FromStream(m);
}
EDIT:
Fixed it. The problem was in the declaration of FindResource. For my case the correct one was:
[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr FindResource(IntPtr hModule, string lpName, uint lpType);
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
显然无法加载 DLL。通过这样编写来获得更好的诊断:
Win32Exception 类的默认构造函数已经负责挖掘 Marshal.GetLastWin32Error() 错误代码并为其生成适当的消息。
此处可能找不到文件。您必须注意 Desktop 文件夹,外壳实际上并不显示 c:\users\yourname\desktop 文件夹的内容,您会看到多个文件夹的混合。当您在代码中引用该文件夹时,不会发生这种混合。该文件的一个可能位置是 c:\users\public\desktop。以正确的方式解决这个问题,确保 DLL 与主 EXE 位于同一目录中。项目 + 添加现有项,导航到 DLL,以便将其添加到您的项目中。选择它并将“复制到输出目录”属性设置为“如果较新则复制”。
编辑后:资源类型参数也可能很麻烦。使用“#23”或将参数类型声明为整数,以便可以传递 23。
Clearly the DLL could not be loaded. Get a better diagnostic by writing it like this:
The default constructor for the Win32Exception class already takes care of digging up the Marshal.GetLastWin32Error() error code and generating the appropriate message for it.
File not found is likely here. You have to watch out for the Desktop folder, the shell doesn't actually show the content of the c:\users\yourname\desktop folder, you get a blend of several folders. This blending doesn't happen when you refer to the folder in your code. One possible location for the file is c:\users\public\desktop. Solve this problem the right way, ensure that the DLL is located in the same directory as your main EXE. Project + Add Existing Item, navigate to the DLL so it is added to your project. Select it and set the Copy to Output Directory property to "Copy if newer".
After edit: the resource type argument could be trouble too. Either use "#23" or declare the argument type as integer so you can pass 23.