P / Invoke声明:
[DllImport("kernel32.dll")]
static extern bool UpdateResource(IntPtr hUpdate, IntPtr lpType, IntPtr lpName, ushort wLanguage, byte[] lpData, uint cbData);
[DllImport("kernel32.dll")]
static extern bool UpdateResource(IntPtr hUpdate, string lpType, int lpName, ushort wLanguage, byte[] lpData, uint cbData);
[DllImport("kernel32.dll")]
static extern IntPtr BeginUpdateResource(string pFileName, bool bDeleteExistingResources);
[DllImport("kernel32.dll")]
static extern bool EndUpdateResource(IntPtr hUpdate, bool fDiscard);
我的代码:
var hUpdate = BeginUpdateResource(FilePath, false);
var BMP = File.ReadAllBytes(BmpPath);
UpdateResource(hUpdate, "2", 123, 1033, BMP, (uint)BMP.Length);
UpdateResource(hUpdate, "#2", 123, 1033, BMP, (uint)BMP.Length);
UpdateResource(hUpdate, "RT_BITMAP", 123, 1033, BMP, (uint)BMP.Length);
UpdateResource(hUpdate, "BITMAP", 123, 1033, BMP, (uint)BMP.Length);
EndUpdateResource(hUpdate, false);
上述UpdateResource
次调用均无效。他们在名为#2, RT_BITMAP, BITMAP
的新资源类型下添加新资源,而不是更新现有资源。
在UpdateResource
的P / Invoke声明中,如果我将string lpType
重载为IntPtr lpType
并将其传递给new IntPtr(2)
,一切正常但我不想使用这个解决方案是因为有时我还需要string lpType
来定制自定义资源类型,而且我的当前代码设计需要进行太多的更改。
MSDN:
lpType [in]
类型:LPCTSTR
要更新的资源类型。或者,而不是指针, 此参数可以是MAKEINTRESOURCE(ID),其中ID是整数 表示预定义资源类型的值。如果是第一个字符 字符串是井号(#),然后是剩余的字符 表示一个十进制数,指定整数标识符 资源类型。例如,字符串“#258”表示 标识符258。
任何想法为什么我不能通过传递lpType
一个字符串来更新现有的位图?我正在完成MSDN中所述的内容。
PS:我绝对需要传递lpType
一个字符串,由于上述原因而无法通过重载使用IntPtr
(当前代码需要进行太多更改)设计)。
答案 0 :(得分:3)
很可能MSDN错了。
lpName
参数的文档说"创建新资源时,请不要使用以'#'开头的字符串。此参数的字符"。我想同样的限制适用于lpType
。
您可以在不改变代码其余部分结构的情况下解决此问题。
定义UpdateResource
的两个重载,但将它们设为私有并重命名(可能为UpdateResourceW
)。
然后在C#中定义您自己的公共UpdateResource
函数。这应检查lpType
参数。如果类型以#
开头,则将其转换为整数并调用IntPtr lpType
重载,否则请使用string lpType
重载。
因此,您可以在整个代码中使用字符串作为资源类型,并在一个位置处理此详细信息。