Как вызвать EnumSystemLocales в Delphi? - PullRequest
9 голосов
/ 23 декабря 2011

Я пытаюсь позвонить EnumSystemLocales в Delphi. Например:

{ Called for each supported locale. }
function LocalesCallback(Name: PChar): BOOL; stdcall;
begin
   OutputDebugString(Name);
   Result := Bool(1); //True
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
   EnumSystemLocales(@LocalesCallback, LCID_SUPPORTED);
end;

Проблема в том, что обратный вызов вызывается только один раз.

Примечание: EnumSystemLocales равно , возвращая true, что указывает на успех.

Замечания EnumSystemLocales говорят, что мой обратный вызов должен возвращать true для продолжения перечисления (или, вернее, не должен возвращать false для продолжения перечисления):

Функция перечисляет локали, передавая идентификаторы локали, один в время до указанной прикладной функции обратного вызова. это продолжается до тех пор, пока все установленные или поддерживаемые идентификаторы локали были переданы в функцию обратного вызова или функцию обратного вызова возвращает FALSE.

В документации функции обратного вызова :

BOOL CALLBACK EnumLocalesProc(
  __in  LPTSTR lpLocaleString
);

у комментатора возникла проблема с определением «не ложно»:

Эта функция должна возвращать 1, а не (DWORD) -1, чтобы продолжить обработку

Это заставляет меня думать, что определение Дельфи

True: BOOL;

отличается от окна. (Вот почему я попытался вернуть значение BOOL(1) - что все еще не удается).

Дальше мне интересно, а не должно ли оно быть stdcall.

В любом случае, может кто-нибудь подсказать, как в Дельпи звонить EnumSystemLocales?


Редактировать : Также пробовал:

  • Result := BOOL(-1);
  • Result := BOOL($FFFFFFFF);
  • Result := BOOL(1);
  • Result := True;

Ответы [ 3 ]

9 голосов
/ 23 декабря 2011

попробуйте объявить функцию LocalesCallback следующим образом

function LocalesCallback(Name: PChar): Integer; stdcall;

проверьте этот образец

{$APPTYPE CONSOLE}

{$R *.res}

uses
  Windows,
  SysUtils;

function LocalesCallback(Name: PChar): Integer; stdcall;
begin
   Writeln(Name);
   Result := 1;
end;

begin
  try
    EnumSystemLocales(@LocalesCallback, LCID_SUPPORTED);
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
  Readln;
end.
4 голосов
/ 23 декабря 2011

Эта проблема возникает из-за ошибки WinAPI, наблюдаемой в Windows версии 5.1 Семейство функций WinNls EnumXXX (и, согласно комментариям, возможно, несколько других) распознает только (BOOL)1 как (BOOL)TRUE и остановит перечисление, если обратный вызов вернет любое другое returnValue != (BOOL)FALSE.

Вот самый семантический обходной путь, который я понял:

  LongWord(Result) := LongWord(True);     // WINBUG: WinNls functions will continue
                                          // enumeration only if exactly 1 was returned
                                          // from the callback
2 голосов
/ 23 декабря 2011

Если вы настаиваете на использовании типа BOOL для результата функции обратного вызова, используйте это:

function LocalesCallback(Name: PChar): BOOL; stdcall;
begin
   OutputDebugString(Name);
   LongWord(Result) := 1;
end;

потому что Bool(1) = $FFFFFFFF.

...