2011-12-23 11 views
8

sto provando a chiamare EnumSystemLocales in Delfi. For example:Come chiamare EnumSystemLocales in 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; 

Il problema è che il callback viene solo richiamato una volta.

Nota:EnumSystemLocalesè restituendo vero, il successo indica.

Le osservazioni di EnumSystemLocales dice che la mia callback deve restituire vero continuare enumerazione (o più correttamente, non deve restituire falso continuare enumerazione):

La funzione enumera locali passando identificatori di impostazioni internazionali , uno a un orario, alla funzione di callback definita dall'applicazione specificata. Questo continua finché non sono stati passati tutti gli identificatori internazionali installati o supportati alla funzione di richiamata o la funzione di richiamata restituisce FALSE.

Sul documentation of the callback function:

BOOL CALLBACK EnumLocalesProc(
    __in LPTSTR lpLocaleString 
); 

un commentatore ha incontrato un problema con la definizione di "non false":

Questa funzione deve restituire 1, non (DWORD) - 1 per continuare l'elaborazione

Questo mi fa pensare che la definizione delphi di

True: BOOL; 

è diverso da quello di Windows. (Ecco perché ho provato un valore di ritorno di BOOL(1) - che non riesce ancora).

Successivamente mi chiedo se non è nemmeno supposto essere stdcall.

In entrambi i casi, qualcuno può suggerire come, in Delpi, chiamare EnumSystemLocales?


Edit: cercato anche:

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

Il problema sembra essere concentrata sul modo di scrivere la funzione di callback, piuttosto che chiamare EnumSystemLocales. Ho ragione? – menjaraz

+0

versione di Windows? – OnTheFly

+0

@menjaraz Molto bene potrebbe essere - ma non voglio scartare alcuna possibilità. –

risposta

8

provare declarating la funzione LocalesCallback come questo controllo

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

questo campione

{$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. 
+0

Eccellente, hai vinto! –

+0

Possiamo chiamare una soluzione alternativa? – menjaraz

+3

@menjaraz - È una soluzione alternativa per il tipo di dati mancante/incompatibile nella lingua. Vedere http://qc.embarcadero.com/wc/qcmain.aspx?d=72852 –

2

Se ti ostini a usare BOOL tipo per risultato funzione di callback, utilizzare questo:

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

perché Bool(1) = $FFFFFFFF.

+0

È una soluzione alternativa o c'è un problema con il compilatore durante il casting su BOOL? – menjaraz

+0

AFAIK nel vecchio C il tipo BOOL era di tipo Integer e true =! False; poiché false = 0, ciò significa vero = non 0 = $ FFFFFFFF (assumendo sizeof (bool) = 4). Questa è la mia ipotesi, potrei sbagliarmi. – kludg

+0

C non ha alcun tipo booleano fino a C99. INT (Interi) può essere testato senza == però, e quindi la semantica che il tuo nome è valido (false = 0 true =! False). Ma le API hanno diverse convenzioni. GTK GBoolean è lo stesso. In realtà sono più vicini al tipo booleano Pascal, ma esiste in Delphi solo come variante a 8 bit. –

3

Questo problema si verifica a causa di bug WinAPI, osservata in versione per Windows 5.1 WinNls EnumXXX famiglia funzione (e, secondo i commenti, probabilmente molti altri) è riconoscere solo esattamente (BOOL)1 come (BOOL)TRUE e interromperà l'enumerazione se richiamata restituisce qualsiasi altra returnValue != (BOOL)FALSE .

Ecco una soluzione più semantica ho capito:

LongWord(Result) := LongWord(True);  // WINBUG: WinNls functions will continue 
              // enumeration only if exactly 1 was returned 
              // from the callback 
+1

Il problema è che ci sono così tanti booleani tra cui scegliere (http://blogs.msdn.com/b/oldnewthing/archive/2004/12/22/329884.aspx) –

+1

@IanBoyd, non proprio, la nostra [fonte di documentazione primaria ] (http://msdn.microsoft.com/en-us/library/windows/desktop/dd317822%28v=vs.85%29.aspx) indica chiaramente quale tipo noi (sviluppatori client) dobbiamo usare. Il problema è ciò che il sottosistema NLS non segue le proprie regole. E che sig. Chen, controvoglia, conferma nel suo diario: è ciò che i project manager di MS non hanno coordinato lo stile comune tra i team, consentendo al tipo * zoo * descritto di diffondersi sul codice base. – OnTheFly

+0

zoo ungherese con prefisso tipo. –