从Windows API调用(GetUserPreferredUILanguages()
),我得到一个字符串列表 one null-delimited PWideChar
。我需要将其转换为Delphi字符串列表。我开始编写代码来手动遍历列表,寻找#0
个字符。
有更聪明的方法吗?
PWideChar
返回的GetUserPreferredUILanguages
示例:
('e','n','-','U','S',#0,'f','r','-','F','R',#0,#0,...)
(基于我在文档中读到的内容,因为当我在计算机上调用该函数时,它只返回一种语言,即'en-US'#0#0)
到目前为止,这是我的代码:
procedure GetWinLanguages(aList: TStringList);
var lCount, lSize: ULong;
lChars: array of WideChar;
lIndex, lLastIndex: integer;
begin
lSize := 1000;
SetLength(lChars, lSize);
GetUserPreferredUILanguages(MUI_LANGUAGE_NAME, @lCount, @lChars[0], @lSize);
// untested quick solution to convert from lChars to aList
lIndex := 0;
lLastIndex := -1;
while (lIndex<=lSize) do
begin
while (lIndex<lSize) and (lChars[lIndex]<>#0) do
inc(lIndex);
if (lIndex-lLastIndex)>1 then
begin
// here: copy range lLastIndex to lIndex, convert to string and add to aList
lLastIndex := lIndex;
inc(lIndex);
end else
Break;
end;
end;
PS。我在Windows 10上使用Delphi Berlin进行FMX项目。
答案 0 :(得分:5)
此API返回以双结尾的字符串。 该程序展示了如何解析这样的事情:
{$APPTYPE CONSOLE}
uses
System.SysUtils,
Winapi.Windows;
procedure Main;
var
NumLanguages, LanguagesBufferLen: ULONG;
LanguagesBuffer: TArray<WideChar>;
P: PWideChar;
str: string;
begin
LanguagesBufferLen := 0;
Win32Check(GetUserPreferredUILanguages(MUI_LANGUAGE_NAME, @NumLanguages, nil, @LanguagesBufferLen));
SetLength(LanguagesBuffer, LanguagesBufferLen);
Win32Check(GetUserPreferredUILanguages(MUI_LANGUAGE_NAME, @NumLanguages, @LanguagesBuffer[0], @LanguagesBufferLen));
P := @LanguagesBuffer[0];
while P^<>#0 do begin
str := P;
Writeln(str);
inc(P, Length(str)+1); // step over the string, and its null terminator
end;
end;
begin
try
Main;
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
Readln;
end.
显而易见的是,如何从此代码中提取一个函数来将以null结尾的字符串解析为字符串列表。这将允许您在其他地方重用代码。
答案 1 :(得分:1)
API返回一个以双重结尾的字符串,其中每个子字符串由#0
字符分隔,然后列表以额外的#0
字符终止。因此,您只需循环直到遇到最后#0
个字符。例如:
procedure GetWinLanguages(aList: TStringList);
var
lCount, lSize: ULONG;
lChars: array of Char;
lStr: PChar;
begin
lSize := 0;
lChars := nil;
repeat
// unlike most Win32 APIs, GetUserPreferredUILanguages() returns TRUE when
// pwszLanguagesBuffer is nil and pcchLanguagesBuffer is set to 0 (unless a
// real error occurs!). This is not made clear in the documentation! The
// function only returns FALSE with an ERROR_INSUFFICENT_BUFFER error code
// when pwszLanguagesBuffer is not nil and pcchLanguagesBuffer is set too low...
if not GetUserPreferredUILanguages(MUI_LANGUAGE_NAME, @lCount, PChar(lChars), @lSize) then
begin
if GetLastError() <> ERROR_INSUFFICIENT_BUFFER then
RaiseLastOSError;
end
else if lChars <> nil then
Break;
SetLength(lChars, lSize);
until False;
lStr := PChar(lChars);
while (lStr^ <> #0) do
begin
aList.Add(lStr);
Inc(lStr, StrLen(lStr)+1);
end;
end;