- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
(来源:khason.net)
var ID = 1234;
var FilePath = "C:\\file.dll";
IntPtr hMod = LoadLibraryEx(FilePath, IntPtr.Zero, 2); //LOAD_LIBRARY_AS_DATAFILE = 2
IntPtr hRes = FindResource(hMod, "#" + ID, "PNG");
byte[] Bytes = new byte[SizeofResource(hMod, hRes)];
Marshal.Copy(LoadResource(hMod, hRes), Bytes, 0, Bytes.Length);
FreeLibrary(hMod);
System.IO.File.WriteAllBytes("C:\\img.png", Bytes);
上面的代码对 PNG
和其他自定义类型工作正常,但对 BITMAP
无效,我尝试了所有可能的组合:
FindResource(hMod, "#" + ID, "RT_BITMAP");
FindResource(hMod, "#" + ID, "BITMAP");
FindResource(hMod, "#" + ID, "Bitmap");
FindResource(hMod, "#" + ID, "BMP");
FindResource(hMod, ID, "Bitmap"); //also changed P/Invoke signature
FindResource(hMod, ID, "BITMAP"); //...
FindResource(hMod, ID, "BMP");
有人知道我在这里错过了什么吗?
我不想在这里使用LoadBitmap
,因为这个函数可以满足我的所有需求。
编辑:
以下返回一些大小正确*但内容不正确的数据(如某种不同的编码):
FindResource(hMod, "#" + ID, "#2"); //RT_BITMAP = 2
FindResource(hMod, ID, 2); //RT_BITMAP = 2; changed sig
*每次大约少 12-14 个字节
P/调用签名:
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern IntPtr LoadLibraryEx(string lpFileName, IntPtr hFile, uint dwFlags);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern bool FreeLibrary(IntPtr hModule);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern IntPtr FindResource(IntPtr hModule, string lpName, string lpType);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern IntPtr FindResource(IntPtr hModule, int lpName, int lpType);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern uint SizeofResource(IntPtr hModule, IntPtr hResInfo);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern IntPtr LoadResource(IntPtr hModule, IntPtr hResInfo);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern IntPtr LockResource(IntPtr hResData);
最佳答案
根本问题是RT_BITMAP
资源没有以位图文件的格式存储。如果将原始数据保存到文件中,则最终不会得到有效的位图文件。原始数据旨在由 LoadBitmap
或 LoadImage
解释以创建 HBITMAP
。
给出了更多细节here :
If, instead of calling LoadBitmap(), the application calls FindResource() (with RT_BITMAP type), LoadResource(), and LockResource(), a pointer to a packed DIB will be the result. A packed DIB is a BITMAPINFO structure followed by an array of bytes containing the bitmap bits.
因此,如果您坚决反对使用 LoadBitmap
或 LoadImage
,那么您将不得不弄清楚如何将打包的 DIB 转换为位图文件。本质上,您需要写出适当的位图文件头,然后在其后加上打包的 DIB 数据。
本质上,代码可能如下所示。首先定义文件头类型。
[StructLayout(LayoutKind.Sequential, Pack=1)]
struct BitmapFileHeader
{
public ushort id;
public int size;
public ushort res1;
public ushort res2;
public int offset;
}
然后为了方便把各种大小放到局部变量中:
int resSize = SizeofResource(hMod, hRes);
int headerSize = Marshal.SizeOf(typeof(BitmapFileHeader));
然后为文件内容分配足够的空间:
byte[] Bytes = new byte[headerSize + resSize];
现在填充标题:
BitmapFileHeader header;
header.id = 0x4D42;
header.size = Bytes.Length;
header.res1 = 0;
header.res2 = 0;
header.offset = headerSize + 40;
// magic constant, size of BITMAPINFOHEADER
最后,用文件头填充字节数组,然后是打包的DIB:
IntPtr headerPtr = Marshal.AllocHGlobal(headerSize);
try
{
Marshal.StructureToPtr(header, headerPtr, false);
Marshal.Copy(headerPtr, Bytes, 0, headerSize);
Marshal.Copy(pRes, Bytes, headerSize, resSize);
}
finally
{
Marshal.FreeHGlobal(headerPtr);
}
然后您可以像以前一样将字节数组保存到磁盘,您应该可以开始了。
FindResource
的声明如下:
HRSRC WINAPI FindResource(
_In_opt_ HMODULE hModule,
_In_ LPCTSTR lpName,
_In_ LPCTSTR lpType
);
虽然 lpName
是 lpType
声明为空终止的 C 字符串,但它们并不总是这种形式。它们可以使用 MAKEINTRESOURCE 形成宏。文档说:
The return value is the specified value in the low-order word and zero in the high-order word.
这确实是 RT_BITMAP
的定义方式。它是 MAKEINTRESOURCE(2)
,详见 resource types文档。
所以你应该添加一些重载的 p/invoke 声明:
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern IntPtr FindResource(IntPtr hModule, string lpName, string lpType);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern IntPtr FindResource(IntPtr hModule, IntPtr lpName, string lpType);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern IntPtr FindResource(IntPtr hModule, string lpName, IntPtr lpType);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern IntPtr FindResource(IntPtr hModule, IntPtr lpName, IntPtr lpType);
然后您可以定义 RT_BITMAP
如下:
public const uint RT_BITMAP = 0x00000002;
然后当你调用函数pass时
(IntPtr)RT_BITMAP
作为 lpType
参数。
作为替代方案,您可以坚持问题中的声明,并使用 documentation 中指定的替代机制。 :
If the first character of the string is a pound sign (#), the remaining characters represent a decimal number that specifies the integer identifier of the resource's name or type. For example, the string "#258" represents the integer identifier 258.
您确实尝试了所有这些不同的选项。我建议您选择一个选项并坚持下去。
除此之外,您还省略了对 LockResource
的调用。您调用 FindResource
和 LoadResource
。但是您未能调用 LockResource
。请注意,LoadResource
返回一个 HGLOBAL
。为了获得指向资源数据的指针,您必须将 HGLOBAL
传递给 LockResource
。虽然事实证明,在现代 Windows 的实现中,您可以不执行 LockResource
步骤而逃脱,但为了遵守规则,您仍然应该执行它。
现在,如果您到达 SizeofResource
返回一个非零值,那么很明显您对 FindResource
的调用成功了。您断言 SizeofResource
返回的大小不正确的断言一定是弄错了。必须安全地假设像 SizeofResource
这样的基础 API 按设计工作。
我还想强调您的代码省略了错误检查。你真的应该补充一下。如果您这样做,您可能会发现您获得了有用的诊断信息。如果没有错误检查,您将不知道您的代码可能在哪里失败。
关于c# - FindResource 不适用于位图,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23615822/
我在我的 Xcode 项目目录中输入了以下内容: keytool -genkey -v -keystore release.keystore -alias mykey -keyalg RSA \
假设我有一个像这样的 DataFrame(或 Series): Value 0 0.5 1 0.8 2 -0.2 3 None 4 None 5 None
我正在对一个 Pandas 系列进行相对繁重的应用。有什么方法可以返回一些打印反馈,说明每次调用函数时在函数内部进行打印还有多远? 最佳答案 您可以使用跟踪器包装您的函数。以下两个示例,一个基于完成的
我有一个 DataFrame,其中一列包含列表作为单元格内容,如下所示: import pandas as pd df = pd.DataFrame({ 'col_lists': [[1, 2
我想使用 Pandas df.apply 但仅限于某些行 作为一个例子,我想做这样的事情,但我的实际问题有点复杂: import pandas as pd import math z = pd.Dat
我有以下 Pandas 数据框 id dist ds 0 0 0 0 5 1 0 0 7 2 0 0
这发生在我尝试使用 Gradle 构建时。由于字符串是对象,因此似乎没有理由发生此错误: No signature of method: java.util.HashMap.getOrDefault(
您好,有人可以解释为什么在 remaining() 函数中的 Backbone 示例应用程序 ( http://backbonejs.org/examples/todos/index.html ) 中
我有两个域类:用户 class User { String username String password String email Date dateCreated
问题陈述: 一个 pandas dataframe 列系列,same_group 需要根据两个现有列 row 和 col 的值从 bool 值创建。如果两个值在字典 memberships 中具有相似
apporable 报告以下错误: error: unknown type name 'MKMapItem'; did you mean 'MKMapView'? MKMapItem* destina
我有一个带有地址列的大型 DataFrame: data addr 0 0.617964 IN,Krishnagiri,635115 1 0.635428 IN,Chennai
我有一个列表list,里面有这样的项目 ElementA: Number=1, Version=1 ElementB: Number=1, Version=2 ElementC: Number=1,
我正在编译我的源代码,它只是在没有运行应用程序的情况下终止。这是我得到的日志: Build/android-armeabi-debug/com.app4u.portaldorugby/PortalDo
我正在尝试根据另一个单元格的值更改单元格值(颜色“红色”或“绿色”)。我运行以下命令: df.loc[0, 'Colour'] = df.loc[0, 'Count'].apply(lambda x:
我想弄清楚如何使用 StateT结合两个 State基于对我的 Scalaz state monad examples 的评论的状态转换器回答。 看来我已经很接近了,但是在尝试申请 sequence
如果我已经为它绑定(bind)了集合,我该如何添加 RibbonLibrary 默认的快速访问项容器。当我从 UI 添加快速访问工具项时,它会抛出 Operation is not valid whi
在我学习期间Typoclassopedia我遇到了这个证明,但我不确定我的证明是否正确。问题是: One might imagine a variant of the interchange law
我是一名优秀的程序员,十分优秀!