我正在使用RIFFCHUNK
结构,在(外国“模块中)声明为(引用MMSystem
和DirectShow9
):
type FOURCC = DWORD; { a four character code }
type _riffchunk = record
fcc: FOURCC;
cb: DWORD;
end;
type RIFFCHUNK = _riffchunk;
我特别感兴趣的是fcc
字段,该字段解析为LongWord
。另一方面,fcc
的有意义值是由4个ASCII可打印单字节字符组成的字符串。我想避免以下丑陋(引用MMSystem
):
const FOURCC_RIFF = $46464952; { 'RIFF' }
...并使用实际的,自解释的四个字符串文字进行分配和比较。
到目前为止,我尝试了什么并且卡在了下面:
const idRIFF: packed array [1..4] of AnsiChar = 'RIFF';
var Chunk: RIFFCHUNK;
begin
Chunk.fcc := FOURCC(idRIFF); { works, but requires a typecast in implementation }
由于idRIFF
不是真常量,因此不能用于正确输入符号的声明。
那么,我想问一下这个美化事件的进一步建议?
请注意FOURCC
类型为“foreign”,因此我不能将其重新声明为字符数组。
答案 0 :(得分:4)
此声明将使用字符串文字将FOURCC_RIFF视为常量:
const
FOURCC_RIFF_S : array[0..SizeOf(FOURCC)-1] of AnsiChar = 'RIFF';
var
FOURCC_RIFF : FOURCC absolute FOURCC_RIFF_S;
如果启用了可写常量指令,那么也可以通过捕获编译器指令来修复。
{$IFOPT J+}
{$DEFINE UNDO_WRCONST}
{$J-}
{$ENDIF}
const
FOURCC_RIFF_S : array[0..SizeOf(FOURCC)-1] of AnsiChar = 'RIFF';
var
FOURCC_RIFF : FOURCC absolute FOURCC_RIFF_S;
{$IFDEF UNDO_WRCONST}
{$J+}
{$ENDIF}
不需要进行类型转换,编译器会将该值视为真常量。
var
Chunk: RIFFCHUNK;
...
Chunk.fcc := FOURCC_RIFF;
答案 1 :(得分:2)
你也可以写:
_riffchunk.fcc := PCardinal(PAnsiChar('RIFF'))^;
是的,它有效!
这实际上与写作相同:
const
FOURCC_RIFF: PAnsiChar = 'RIFF';
...
_riffchunk.fcc := PCardinal(FOURCC_RIFF)^;
因此,您可以使用以下功能:
function ToFourCC(const s: AnsiString): FOURCC; inline;
begin
result := PCardinal(s)^;
end;
_riffchunk.fcc := ToFourCC('RIFF');
当然,所有这些都不能与NextGen编译器一起使用。
答案 2 :(得分:2)
多媒体API定义了MAKEFOURCC()
和mmioFOURCC()
个宏,这两个宏都将4个字符转换为FOURCC
值,例如:
Chunk.fcc := MAKEFOURCC('R', 'I', 'F', 'F');
Chunk.fcc := mmioMAKEFOURCC('R', 'I', 'F', 'F');
如果Delphi在MMSystem
单元中没有现有的翻译(它应该,但我现在无法检查),这里有一个:
function MAKEFOURCC(ch0, ch1, ch2, ch3: AnsiChar): LongWord;
begin
Result := LongWord(Ord(ch0)) or (LongWord(Ord(ch1)) shl 8) or (LongWord(Ord(ch2)) shl 16) or (LongWord(Ord(ch3)) shl 24);
end;
答案 3 :(得分:1)
我想不出比助手功能更好的东西:
function FourCCfromString(const Value: AnsiString): FOURCC;
begin
if Length(Value)<>SizeOf(Result) then
raise ESomeException.Create(...);
Move(Pointer(Value)^, Result, SizeOf(Result));
end;
我能看到的好处是:
我认为你不能在这里使用带有类操作符的记录助手。您无法在记录助手中定义类操作符。
您可以使用Implicit
类运算符定义记录以执行转换。它看起来像这样:
type
TMyFourCC = record
Value: FOURCC;
class operator Implicit(const Value: AnsiString): TMyFourCC;
class operator Implicit(const Value: string): TMyFourCC;
class operator Implicit(const Value: TMyFourCC): FOURCC;
end;
但是你需要写:
Chunk.fcc := 'RIFF';
并且无法编译,因为编译器无法推断您希望从string
转到TMyFourCC
然后转到FOURCC
。不幸的是,隐式转换运算符只允许单跳。