En VC, se debe prestar atención a la configuración del juego de caracteres VC
VC es realmente una herramienta muy estúpida y hostil. Digámoslo de esta manera, VC (MFC) es la más popular ahora. ¡Net framework java es como la edad de piedra en comparación con la era industrial!
He estado en contacto con MFC durante varios años. He trabajado horas extras, me quedé despierto hasta tarde e incluso me quedé despierto toda la noche. El código debería ser decenas de miles, si no cientos de miles. Pero MFC es tan asombroso que no solo asusta a los principiantes, sino que a menudo también hace tropezar a los ingenieros de software experimentados. Recientemente, pasé mucho tiempo debido a un pequeño problema de configuración del entorno. Esto está relacionado con el cambio repentino de VC2005 a VC6, pero el punto clave es que VC es demasiado estúpido y me permitió ganar dos veces. ¡una fila!
La primera vez que me engañaron fue así, fue muy simple:
No sabía que la configuración predeterminada del proyecto de VC.net2005 usa el “Conjunto de caracteres Unicode”. Cuando usé proyectos VC6 en el pasado, el valor predeterminado era "Juego de caracteres de varios bytes". Nunca antes había usado VC.net2005, siempre pensé. net se utiliza para programar en el marco. No es necesario abrir un programa enorme al programar en MFC. net2005, hace que la máquina parezca un buey tirando de un carro.
Declaré un CString y le asigné un valor según lo planeado, así:
CString s;
s.Format("count = d", count );
Según la experiencia, esto definitivamente no estará mal, pero lo siento, hay un error de compilación, porque este es el conjunto de caracteres Unicode adoptado por mi entorno y la función de formato que le di a CString es " "Juego de caracteres" múltiple (Multi-Byte), por lo que la compilación no pasa. Debe saber que MessageBox ("ddd") se usa bajo esta configuración, la compilación no pasa porque el sistema llama a MessageBoxW, la función de Unicode; amplio conjunto de caracteres.
Afortunadamente, cambié s.Format ("count = d", count); a s.Format (_T ("count = d", count); de acuerdo con las indicaciones del compilador, y ya estaba hecho. _T representa una macro, lo que significa convertir una cadena en una representación de caracteres amplios. De manera similar, MessageBox("ddd" puede ser MessageBox(_T("ddd"));
Pero también hay uno. El problema es que todas las cosas que se muestran en el formulario son caracteres anchos. Por ejemplo, a tiene dos bytes a en la memoria. El primer byte va seguido de a. debe ir seguido de Al interactuar con otras plataformas, como la transmisión de red a una máquina remota.
Si no se utiliza el juego de caracteres Unicode allí, habrá problemas. Para que la interfaz y la transmisión en segundo plano sean consistentes, tenemos que convertir los caracteres anchos en una representación de juego de múltiples caracteres:
CString strWideChar;
strWideChar.Format(_T("Este es un byte ancho"));
char buf[20];
memset(buf, 0, 20) ;
p>
WideCharToMultiByte( //Convertir Unicode a Ansi
CP_ACP,
WC_COMPOSITECHECK | WC_DEFAULTCHAR,
strWideChar,
strWideChar .GetLength(),
(char *)buf, //Convertir a búfer
20, //Bytes máximos
0,
0);
De manera similar, si desea que la cadena que recibe se muestre normalmente en la interfaz, debe convertirla en una representación de bytes amplios:
char chBytes[8];
memcpy(chBytes, "aaaaaaa", 8);
WCHAR wch[9];
n = MultiByteToWideChar ( // Convertir Unicode a Ansi
CP_ACP,
0,
chBytes,
8,
wch, //Convertir a buffer
8 //Número máximo de bytes);
wch[n] = '';
De esta manera, cada momento en que se recupera de la interfaz Tanto los datos como la visualización de los datos en la interfaz deben procesarse primero, pero también puede configurar el entorno de compilación en "Conjunto de caracteres de varios bytes" para evitar tales conversiones (desafortunadamente, cuando descubrí el código está casi terminado). Simplemente en "Propiedades de configuración del proyecto-General-Conjunto de caracteres, seleccione "Usar juego de caracteres Unicode" para usar el juego de caracteres Uncode, seleccione "Usar juego de caracteres de varios bytes" para usar el juego de caracteres de varios bytes.
Capítulo Me atraparon dos veces, Dios. Me tomó mucho tiempo encontrar el problema:
Encontré un código fuente escrito por un extranjero muy amable en CodeProject que heredó la clase de formulario CDialog CResizableDialog. class La función es permitir que los controles en el formulario se coloquen (Auchor) cuando el formulario MFC se amplía o reduce. No subestimes esta pequeña función que se usa todos los días. Es realmente problemático implementarla con MFC. Admiro mucho a ese extranjero por haber escrito tanto código (por supuesto que tiene algo que ver con sus condiciones. Los trabajadores en los países capitalistas pueden simplemente encontrar un trabajo y tener suficiente comida y ropa. El gobierno se hará cargo de ellos cuando estén enfermos). Estamos "pateados" y vivimos como trabajadores inmigrantes. Por supuesto, no tenemos ese tiempo libre. No tengo ningún deseo de escribir un código tan bueno para que otros lo usen de forma gratuita, lo cual es una digresión. > Tomé ese proyecto ya hecho y hice referencia directa a su proyecto en mi proyecto.
Todo funciona perfecto. Hasta que publiqué el proyecto como Lanzamiento, no pasó nada después de hacer doble clic para ejecutarlo. Más tarde, usé MessageBox para imprimir el mensaje y descubrí que no aparecía después de ejecutarlo en la función DoModal, ¡y el programa salió directamente! ¡No obtendrás ningún error al usar try o catch! Debido a que mi formulario hereda la clase de formulario escrita por un extranjero, originalmente era bueno heredar CDialog. El problema debe estar en su proyecto, pero no hay ningún problema con el programa de muestra que me dio. MFC es muy crítico cuando algo sale mal. No le dará ningún aviso, ¡simplemente no funcionará!
Tomé otro programa de prueba anterior y lo dejé heredar de CResizableDialog, y no hubo ningún problema.
Estoy abrumado y sin palabras. No sé dónde está el problema. La versión no se puede depurar como Debug. Después de reproducir un montón de cuadros de mensajes, todavía no sé dónde está el problema. Según la experiencia, podemos saber que puede haber un error fatal, como el acceso fuera de los límites a la memoria en el programa, lo que hará que el programa se cierre "silenciosamente", pero ¿qué salió mal exactamente?
Justo cuando estaba perdido, descubrí que llamar a la función miembro EnableSaveRestore de CResizableDialog provocaría un error de enlace: "Símbolo externo no definido, no habría ningún error si no hacía referencia a él". no habría errores si el programa de prueba hiciera referencia a él. Generalmente este error ocurre porque la función de referencia está activa. h archivo, pero en. Tampoco hay una definición en cpp. definición de archivo cpp y. Los parámetros en h no coinciden. Pero no puede ser este error en este momento porque no hay ningún error en el programa de prueba. La intuición me dice que esta es la clave para resolver el problema de "el programa sale directamente después del lanzamiento". Tal vez el problema de esta llamada a función esté resuelto y el problema del lanzamiento también esté resuelto.
MFC es realmente poderoso no sólo es "como un laberinto, con monstruos dentro, nunca podrás salir si ingresas accidentalmente", sino que también te permite avisarte siempre cuando lo hagas. Te encuentras con un monstruo con un poco de luz de las estrellas, mientras no te rindas, aparecerán milagros y lograrás una magia incomparable. Esto es similar a las novelas de artes marciales. Cada vez que el protagonista llega a un momento crítico de vida o muerte, ocurrirá un milagro y se convertirá en un maestro invencible. Mira cómo encontré la solución, muy complicada.
Dado que se produjo un error al llamar a EnableSaveRestore que no debería haber ocurrido, comience a buscarlo desde esta función. Esta función es así:
declaración de archivo .h
void EnableSaveRestore(LPCTSTR pszSection, BOOL bRectOnly = FALSE);
definición de archivo .cpp
void CResizableDialog::EnableSaveRestore(LPCTSTR pszSection, BOOL bRectOnly/* = FALSE */)
{
m_sSection = pszSection;
m_bEnableSaveRestore = TRUE;
m_bRectOnly = bRectOnly;
// restaurar inmediatamente
LoadWindowRect(pszSection, bRectOnly);
}
El código anterior no tiene ningún error. Dado que no hay errores, debe utilizar los siguientes métodos para encontrarlos:
1. Reescribir una función para CResizableDialog. Llámalo y descubre que no hay errores, parece que hay algún problema con los parámetros.
2. Dado que no hay ningún error en una función sin parámetros, simplemente elimine los parámetros de la función problemática y no habrá ningún error. El problema debe estar en los parámetros.
3. Elimine uno de los parámetros y la prueba encontró que es un problema con LPCTSTR pszSection, no con BOOL bRectOnly.
4. En este caso, cambiemos la expresión, reemplacemos LPCTSTR pszSection con WCHAR* pszSection, ejecútelo y no habrá ningún error. Si abre la definición de macro MFC, encontrará que LPCTSTR y WCHAR * son en realidad lo mismo que MFC.
5. Sin embargo, la función de esta función todavía no es normal. Cuando entro en la función, encuentro que la cadena pasada tiene solo un carácter. como carácter corto, el segundo byte se considera como el carácter de corte de la cadena, es decir, esta función utiliza caracteres cortos (Multi Byte) para procesar.
6. Mi proyecto utiliza un conjunto de caracteres amplio (Unicode Char). Resulta que el extranjero se compiló con VC6. El valor predeterminado es utilizar un conjunto de caracteres múltiples (Multi Byte). VC es realmente estúpido, dos proyectos con configuraciones completamente diferentes en una solución ni siquiera tienen indicaciones, ¡simplemente me mató!
7. Cambie el proyecto de referencia para usar el juego de caracteres Unicode y restaure la función EnableSaveRestore WCHAR* pszSection a su estado original, ¡listo! Como era de esperar, ¡no hay ningún problema con Release! Utilicé el antiguo programa de prueba para configurarlo en Multi Byte justo antes, por lo que no hubo errores, ¡Maldita sea!
Es solo una configuración. Si el mensaje de error de VC es mejor, al menos sería más fácil de usar si el conjunto de caracteres no coincide y no lo llama "símbolo externo indefinido". ¡Y ahora más personas usan VC menos!
Nota: En términos generales, VC no se refiere al uso. NET framework, que es muy simple y no requiere administración de memoria, generalmente se refiere a VC no administrado.