Questa nota viene descritto come utilizzare le macro per la conversione di MBCS/Unicode che sono definiti in AFXPRIV.H. Queste macro sono più utile se la vostra applicazione si occupa direttamente con l'API OLE o per qualche motivo, spesso ha bisogno di convertire tra Unicode e MBCS.
Panoramica
In MFC 3. x, è stata usata una DLL speciale (MFCANS32.DLL) per convertire automaticamente tra Unicode e MBCS quando venivano chiamate interfacce OLE. Questa DLL è stata un livello quasi trasparente che ha permesso di applicazioni OLE deve essere scritto come fossero le interfacce e le API OLE MBCS, anche se sono sempre Unicode (tranne in Macintosh). Mentre questo strato era conveniente e ha permesso alle applicazioni di essere rapidamente convertito da Win16 per Win32 (MFC, Microsoft Word, Microsoft Excel e VBA, sono solo alcune delle applicazioni Microsoft che ha utilizzato questa tecnologia), aveva anche una performance a volte significativa ha colpito. Per questo motivo, MFC 4. x non utilizza questa DLL e invece comunica direttamente con le interfacce Unicode OLE. Per fare questo, ha bisogno di convertire in Unicode a MBCS quando si effettua una chiamata a un'interfaccia OLE MFC e spesso ha bisogno di convertire a MBCS da Unicode quando si implementa un'interfaccia OLE. Al fine di gestire questo in modo efficiente e rapido, una serie di macro sono stata creata per facilitare questa conversione.
Uno dei più grandi ostacoli della creazione di una serie di macro è l'allocazione della memoria. Perché le stringhe non possono essere convertite in luogo, nuova memoria per contenere i risultati convertiti deve essere allocata. Questo potrebbe sono stati fatti con codice simile al seguente:
/ / ci vo&gliono convertire una stringa di formato MBCS in lpszA
int nLen = MultiByteToWideChar (CP_ACP, 0, lpszA, -1, NULL, NULL);
LPWSTR lpszW = nuovo WCHAR [nLen];
MultiByteToWideChar (CP_ACP, 0, lpszA, -1, lpszW, nLen);
/ / utilizzato per chiamare OLE qui
pI-gt;SomeFunctionThatNeedsUnicode(lpszW);
/ / gratis la stringa
eliminare lpszW]
Questo approccio come una serie di problemi. Il problema principale è che è un sacco di codice da scrivere, testare ed eseguire il debug. Qualcosa che è stata chiamata a una funzione semplice, ora è molto più complessa. Inoltre, c'è un runtime notevole sovraccarico in tal modo. Memoria deve essere allocata nell'heap e liberato ogni volta che viene eseguita una conversione. Infine, il codice sopra avrebbe bisogno di avere adeguate #ifdefs aggiunto per compilazioni Unicode e Macintosh (che non richiedono questa conversione a prendere posto).
La soluzione che si avvicinò con è quello di creare alcune macro il codice sorgente di cui 1) maschera la differenza tra le varie piattaforme e 2) utilizzare uno schema di allocazione di memoria efficiente e 3) è facile inserire l'esistente. Ecco un esempio di una delle definizioni:
# define A2W(lpa) (\
nbsp; (Lpa (LPCSTR) = = &NULL)? NULL: (\
_convert = (strlen (lpa) + 1), \
AfxA2WHelper((LPWSTR) alloca(_convert*2), lpa, _convert) \
)\
)
Utilizzando questa macro anziché il codice qui sopra e le cose sono molto più semplici:
/ / utilizzato per chiamare OLE qui
USES_CONVERSION;
pI->SomeFunctionThatNeedsUnicode(T2OLE(lpszA))
Ci sono chiamate aggiuntive dove la conversione non è necessaria, ma utilizzando le macro è semplice ed efficace.
L'implementazione di ogni macro utilizza la funzione _alloca() per allocare memoria dallo stack invece di heap. Allocazione della memoria dallo stack è molto più veloce di allocazione della memoria nell'heap e la memoria viene liberata automaticamente quando la funzione è uscita. Inoltre, le macro evitare di chiamare MultiByteToWideChar (o WideCharToMultiByte) più di una volta. Questo viene fatto di allocazione della memoria un po ' più di quanto necessario. Sappiamo che un MBC convertirà in al massimo uno WCHAR e che per ogni WCHAR avremo un massimo di due byte MBC. Da allocare un po ' più del necessario, ma sempre per gestire la conversione la seconda chiamata seconda chiamata alla funzione di conversione è evitato. La chiamata alla funzione di supporto AfxA2Whelper riduce il numero di spinge argomento che deve essere fatto al fine di eseguire la conversione (questo si traduce in codice più piccole, rispetto a se chiamato MultiByteToWideChar direttamente).
Al fine di per le macro di avere spazio per memorizzare la lunghezza temporanea, è necessario dichiarare una variabile locale denominata _convert che fa questo in ogni funzione che utilizza la macro per la conversione. Questo viene fatto richiamando la macro USES_CONVERSION come visto sopra nell'esempio.
Ci sono sia macro per la conversione generico e le macro specifiche OLE. Questi due insiemi di diverse macro sono illustrati di seguito. Tutte le macro risiedono in AFXPRIV.H.
Generico macro per la conversione
La macro per la conversione generico formano il meccanismo sottostante. L'esempio di macro e implementazione illustrato nella sezione precedente, A2W, è una tale macro "generico". Ha alcuna relazione con OLE in modo specifico. L'insieme di macro generiche è elencato qui sotto:
A2CW (LPCSTR) - gt; (LPCWSTR)
A2W (LPCSTR) - > (LPWSTR)
W2CA (LPCWSTR) - > (LPCSTR)
W2A (LPCWSTR) - > (LPSTR)
Oltre a fare le conversioni testo, ci sono anche le macro e funzioni di supporto per la conversione di TEXTMETRIC, DEVMODE, BSTRe OLE stringhe allocate. Queste macro sono oltre la portata di questa discussione – riferirsi a AFXPRIV.H per ulteriori informazioni su tali macro.
OLE macro per la conversione
Le macro di conversione OLE sono progettate specificamente per la gestione delle funzioni che aspettano che i personaggi OLESTR . Se si esaminano le intestazioni OLE vedrete molti riferimenti alla LPCOLESTR e OLECHAR. Questi tipi vengono utilizzati per indicare il tipo di caratteri utilizzati nelle interfacce OLE in un modo che non è specifico per la piattaforma. OLECHAR esegue il mapping a char in piattaforme Win16 e Macintosh e WCHAR in Win32.
Al fine di mantenere il numero di direttive # ifdef nel codice MFC al minimo abbiamo una macro simile per ogni conversione che dove sono coinvolte le stringhe di OLE. Le seguenti macro sono più comunemente utilizzate:
T2COLE (LPCTSTR) - gt; (LPCOLESTR)
T2OLE (LPCTSTR) - > (LPOLESTR)
OLE2CT (LPCOLESTR) - > (LPCTSTR)
OLE2T (LPCOLESTR) - > (LPCSTR)
Ancora una volta ci sono macro simili per fare TEXTMETRIC, DEVMODE, BSTRe OLE stringhe allocate. Fare riferimento a AFXPRIV.H per ulteriori informazioni.
Altre considerazioni
Non utilizzare le macro in un loop stretto. Ad esempio, non volete scrivere il seguente tipo di codice:
public static void BadIterateCode(LPCTSTR lpsz)
{
USES_CONVERSION;
per (ii int = 0; ii lt; 10000; ii + +)
pI - > SomeMethod (ii, T2COLE(lpsz));
}
Il codice di cui sopra potrebbe tradursi i&n allocazione megabyte di memoria sullo stack a seconda di ciò che il contenuto della stringa lpsz è! nbsp; Ci vuole anche tempo per convertire la stringa per ogni iterazione del ciclo. Invece di spostare tali conversioni costante il ciclo:
public static void MuchBetterIterateCode(LPCTSTR lpsz)
{
USES_CONVERSION;
LPCOLESTR lpszT = T2COLE(lpsz);
per (ii int = 0; ii lt; 10000; ii + +)
pI - > SomeMethod (ii, lpszT);
}
Se la stringa non è costante, quindi incapsulare la chiamata al metodo in una funzione. Ciò permetterà il buffer di conversione essere liberati ogni volta. Ad esempio:
public static void CallSomeMethod (int ii, LPCTSTR lpsz)
{
USES_CONVERSION;
pI-gt;SomeMethod (ii, T2COLE(lpsz));
}
public static void MuchBetterIterateCode2 (LPCTSTR lpszArray)
{
per (ii int = 0; ii < 10000; ii + +)
CallSomeMethod (ii, lpszArray[ii]);
}
Non tornare mai più il risultato di una delle macro, a meno che il valore restituito implica una copia dei dati prima del ritorno. Ad esempio, questo codice è male:
LPTSTR BadConvert(ISomeInterface* pI)
{
USES_CONVERSION;
LPOLESTR lpsz = NULL;
pI-gt;GetFileName(&lpsz);
LPTSTR lpszT = OLE2T(lpsz);
CoMemFree(lpsz);
return lpszT; / / bad! restituzione di cucinarvi memoria
}
Il codice di cui sopra potrebbe essere risolto modificando il valore restituito a qualcosa che copia il valore:
CString BetterConvert(ISomeInterface* pI)
{
USES_CONVERSION;
LPOLESTR lpsz = NULL;
pI-gt;GetFileName(&lpsz);
LPTSTR lpszT = OLE2T(lpsz);
CoMemFree(lpsz);
return lpszT; / / CString fa copia
}
Le macro sono facili da usare e facile da inserire nel codice, ma come si può dire dalle avvertenze qui sopra, è necessario prestare molta attenzione durante il loro utilizzo.
&Note tecniche per numero |nbsp; Note tecniche per la categoria