我正在尝试使用资源名称和资源类型为“ RT_BITMAP”或任何其他名称列出程序的所有资源。
代码 :
var
Form1: TForm1;
list_resources: string;
function EnumResNameProc(lpszName: PChar; lParam: integer; lpszType: PChar;
hModule: Cardinal): BOOL;
begin
list_resources := list_resources + sLineBreak + lpszName + ' - ' + lpszType;
Result := True;
end;
procedure TForm1.btnListResourcesClick(Sender: TObject);
begin
EnumResourceNames(0, RT_RCDATA, @EnumResNameProc, 0);
Memo1.Lines.Add(list_resources);
end;
代码运行良好,但是从不显示资源类型,这是什么问题?
您的代码的第一个问题是回调函数具有错误的调用约定和确实错误的签名。应该这样声明:
function EnumResNameProc(hModule: HMODULE; lpszType, lpszName: PChar;
lParam: LONG_PTR): BOOL; stdcall;
您的代码产生的输出完全是偶然的。正确获得这些功能的签名非常重要。我不知道您的签名来自哪里。看起来您刚刚做好了!MSDN上的文档具有正确的签名。Embarcadero通过声明接受回调的API函数(这意味着忽略对签名的类型检查)来使事情变得困难。因此,责任就落在了你身上。请非常仔细地阅读文档。
解决此问题后,还有更多工作要做。资源类型以及实际上的资源名称可以是整数或字符串。习惯上,将<65536的值解释为整数,否则,该值是指向以null终止的字符数组的指针。您可以调用Is_IntResource
Windows宏的Delphi转换,而不是硬编码该魔术常数IS_INTRESOURCE
。
在您的情况下,您将接收命名资源,但是资源类型实际上是整数值。在Windows单元中:
const
RT_CURSOR = MakeIntResource(1);
RT_BITMAP = MakeIntResource(2);
RT_ICON = MakeIntResource(3);
RT_MENU = MakeIntResource(4);
RT_DIALOG = MakeIntResource(5);
RT_STRING = MakeIntResource(6);
RT_FONTDIR = MakeIntResource(7);
RT_FONT = MakeIntResource(8);
RT_ACCELERATOR = MakeIntResource(9);
RT_RCDATA = System.Types.RT_RCDATA; //MakeIntResource(10);
DIFFERENCE = 11;
RT_GROUP_CURSOR = MakeIntResource(DWORD(RT_CURSOR) + DIFFERENCE);
RT_GROUP_ICON = MakeIntResource(DWORD(RT_ICON) + DIFFERENCE);
RT_VERSION = MakeIntResource(16);
RT_DLGINCLUDE = MakeIntResource(17);
RT_PLUGPLAY = MakeIntResource(19);
RT_VXD = MakeIntResource(20);
RT_ANICURSOR = MakeIntResource(21);
RT_ANIICON = MakeIntResource(22);
RT_HTML = MakeIntResource(23);
RT_MANIFEST = MakeIntResource(24);
另一个惯例是,您使用#
符号来表示数字标识符。因此,您可以采用以下策略:
Is_IntResource
返回True
,则将数值转换为字符串并以前缀#
。代码很简单:
function ResourceNameToString(lpszName: PChar): string;
begin
if Is_IntResource(lpszName) then
Result := '#' + IntToStr(NativeUInt(lpszName))
else
Result := lpszName;
end;
必须对名称和类型执行此操作。否则,当您的代码尝试取消对实际上表示整数的指针的引用时,您的代码将因运行时访问冲突错误而失败。如果您修复了回调签名,但没有进行进一步更改,则问题中的代码将以这种方式失败。
如果希望您的代码更有帮助,您将检测预定义的资源类型并给予特殊对待。
function ResourceTypeToString(lpszType: PChar): string;
begin
case NativeUInt(lpszType) of
NativeUInt(RT_CURSOR):
Result := 'RT_CURSOR';
NativeUInt(RT_BITMAP):
Result := 'RT_BITMAP';
NativeUInt(RT_RCDATA):
Result := 'RT_RCDATA';
// etc.
else
Result := ResourceNameToString(lpszType);
end;
end;
我让您填写缺失的值。
像这样将它们放在一起:
{$APPTYPE CONSOLE}
uses
SysUtils, Windows;
function ResourceNameToString(lpszName: PChar): string;
begin
if Is_IntResource(lpszName) then
Result := '#' + IntToStr(NativeUInt(lpszName))
else
Result := lpszName;
end;
function ResourceTypeToString(lpszType: PChar): string;
begin
case NativeUInt(lpszType) of
NativeUInt(RT_CURSOR):
Result := 'RT_CURSOR';
NativeUInt(RT_BITMAP):
Result := 'RT_BITMAP';
NativeUInt(RT_RCDATA):
Result := 'RT_RCDATA';
// etc.
else
Result := ResourceNameToString(lpszType);
end;
end;
function EnumResNameProc(hModule: HMODULE; lpszType, lpszName: PChar;
lParam: LONG_PTR): BOOL; stdcall;
begin
Writeln(ResourceTypeToString(lpszType) + ' - ' + ResourceNameToString(lpszName));
Result := True;
end;
begin
EnumResourceNames(0, RT_RCDATA, @EnumResNameProc, 0);
Readln;
end.
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句