2012-09-09 16 views
6

mia app è un'applicazione non Unicode scritto in Delphi 7.WideString di conversione di stringhe in Delphi 7

vorrei convertire le stringhe Unicode a ANSI con questa funzione:

function convertU(ws : widestring) : string; 
begin 
    result := string(ws); 
end; 

io uso anche questo codice per impostare la codepage corretta da convertire.

initialization 
    SetThreadLocale(GetSystemDefaultLCID); 
    GetFormatSettings; 

E le grandi opere nel thread principale VCL ma non in un TThread, dove ho alcune domande marchi '?' come risultato della funzione convertU.

Perché non in un TThread?

+0

Per prima cosa, non è necessaria una funzione o typecast per farlo; un semplice 'stringaVar: = wideStringVar;' funzionerà. In secondo luogo, il problema è che non tutte le WideChar sono direttamente convertibili in AnsiString; alcuni hanno più di un carattere in larghezza e alcuni hanno valori di carattere che non sono rappresentabili in un AnsiChar e alcuni tipi di carattere non contengono tutti i possibili valori Unicode. Se stai * vedendo * '?', Significa che li stai visualizzando, il che potrebbe essere il terzo problema: i thread non dovrebbero accedere ai controlli della GUI senza usare 'Sychronize'. Dal momento che non hai inserito il codice di visualizzazione, è difficile dire se è così. –

+0

La domanda è: perché ottengo punti interrogativi quando viene utilizzato in TThread? – user382591

+2

Ripeto: ** Se vedi '?', Stai visualizzando il testo. ** Hai fornito ** codice zero o informazioni ** riguardo a come lo stai visualizzando. –

risposta

5

La chiamata di SetThreadLocale() all'interno di un blocco initialization non ha alcun effetto su TThread. Se si desidera impostare le impostazioni locali di un thread, è necessario chiamare SetThreadLocale() all'interno del metodo TThread.Execute().

Un'opzione migliore è quella di non fare affidamento su SetThreadLocale(). Effettua direttamente la conversione chiamando lo WideCharToMultiByte() in modo da poter specificare la particolare codepage Ansi da convertire.

+0

Grazie per il vostro aiuto. Funziona !!! – user382591

+0

Se sei l'autore di tutto il codice nella tua app, le chiamate esplicite a WideCharToMultiByte sono un'opzione valida. Se includi codice di terze parti, l'impostazione a livello di thread delle impostazioni internazionali potrebbe essere il miglior compromesso. –

+0

sì. Grazie. Ora utilizzo un mix di entrambi: WideCharToMultiByte AND SetThreadLocale() – user382591

6

AFAIK SetThreadLocale non modifica il sistema attuale codice pagina, quindi non influenzerà la conversione widestring a ansistring in Delphi 7, che si basano sulla GetACP chiamata API, cioè il sistema di tabella codici.

La pagina Codice sistema è impostata ad es. in Windows 7 nel Pannello di controllo, quindi Lingua della regione/scheda Amministratore/Pagina codice per applicazioni non Unicode. Questo ha bisogno di un riavvio del sistema.

Delphi 7 utilizza questa pagina di codice del sistema, fornendo 0 a tutte le chiamate dell'API di conversione. Pertanto, AFAIR SetThreadLocale non influirà sulla conversione da widestring a ansistring in Delphi 7. Cambierà le impostazioni internazionali (ad esempio data/ora e formattazione valuta), non la tabella codici utilizzata dal sistema per la sua conversione Ansi < -> Unicode.

Le versioni più recenti di Delphi hanno una funzione SetMultiByteConversionCodePage(), in grado di impostare la tabella codici da utilizzare per tutta la gestione dello AnsiString.

Ma chiamate API (cioè tutte ....A() funzioni Windows.pas che sono mappati da ...() in Delphi 7) utilizzeranno questa tabella codici di sistema. Quindi dovrai chiamare l'API wide ...W() dopo una conversione in Unicode se vuoi gestire un'altra pagina di codice. Cioè, Delphi 7 VCL funzionerà solo con la tabella codici di sistema, non con il valore specificato da SetThreadLocale.

Sotto Delphi 7, il mio consiglio è:

  • Usa WideString ovunque, e le chiamate alle API specifiche "Wide" - ci sono diversi set di componenti per Delphi 7, che gestisce WideString;
  • Utilizza i tuoi tipi, con un set di caratteri dedicato, ma avrai bisogno di una conversione esplicita prima di utilizzare le chiamate API VCL/RTL o "Ansi", ad es. MyString = type AnsiString (questo è ciò che facciamo in mORMot, definendo un tipo personalizzato RawUTF8 per il processo UTF-8 interno).

questo è molto meglio gestita con Delphi 2009 e, dal momento che è possibile specificare una pagina di codice ad ogni tipo AnsiString, e gestire correttamente la conversione da/per Unicode, per le chiamate API o processo VCL.

+0

+1 Credo che sia corretto. –

+0

Voglio solo gestire la codepage di sistema predefinita. Quello che ho notato, è che per la conversione Ansi Unicode <->, la codepage utilizzata è la LCID dell'utente PREDEFINITO e non la LCID del sistema DEFAULT e questo è un problema. – user382591

Problemi correlati