У вас проблема с кодировкой Unicode или Windows ANSI.Исторически Windows использовала расширенный ASCII, который они называли ANSI.Это привело к необходимости кодовых страниц, потому что даже 8-битный символ не обеспечивает достаточного количества кодовых точек для представления всех европейских систем письма, не говоря уже об остальном мире.Когда был разработан Win32, они остановились на Юникоде в качестве предпочтительного набора символов.(На самом деле они остановились на кодировке UTF-16LE набора символов Unicode, но эта деталь сейчас не совсем актуальна.) Однако существовало слишком много существующего кода, чтобы рассмотреть необходимость переноса с Win16 на Win32.измените кодировку символов всех строк.
Их решение было умным (некоторые утверждали, что оно было слишком умным).Каждая точка входа Win32 API, которая принимает строку, имеет две разновидности.Первый вариант принимает строки ANSI и обрабатывает преобразование в UTF-16LE внутри.Второй (и теперь предпочтительный) аромат напрямую принимает строки UTF-16LE.Они также сговорились с командой Visual C, чтобы определить wchar_t
как 16-битный тип и обеспечить, чтобы строковые литералы L""
использовали отображение из текста ASCII в UTF-16LE.
Чтобы упростить портирование из существующего кода Win16, функция MessageBox
и любой другой Win32 API, принимающий строки, сопоставляются макросом во время компиляции с MessageBoxA
или MessageBoxW
в зависимости от того, действительно лисимвол препроцессора UNICODE
определен.
Это отображение не может исправить строковые литералы, поэтому они также ввели макрос для обозначения строковых литералов, которые должны быть либо узкими, либо широкими в зависимости от UNICODE
, исоответствующий typedef, чтобы можно было объявить переменные для хранения указателей на них.
Таким образом, для лучшей переносимости в и из Win16 вы должны #include <tchar.h>
использовать TCHAR
вместо char
или wchar_t
, оберните все текстовые строковые литералы в макросе _T()
и вызовите API-интерфейсы Win32 с именами без суффиксов, такими как MessageBox
.
Однако это не идеальное решение.В тот момент, когда ваш код должен манипулировать или вычислять строку, которая будет отображаться для пользователя, вы обнаруживаете, что трудно написать код, который идеально переносим в режиме TCHAR
.Существуют замены для всех стандартных строковых функций, которые манипулируют TCHAR
s, но с помощью автоматического тестирования трудно проверить, правильно ли вы их использовали, чтобы код компилировался и работал правильно как с определенным UNICODE
, так и без него.
Если вы пишете новый код Win32 сегодня, я бы посоветовал определить UNICODE в проекте, добавить проверку, что он действительно определен в общем заголовочном файле, и использовать строки L""
и разновидности W
все завернутые вызовы явно.
Наконец, все это эссе подсказывается вашим кодом, который отображает глиф отсутствующего символа (символ пустого квадратного прямоугольника - это глиф, который отображается, когда в шрифте отсутствует определенный символ).Это происходит потому, что ваши строковые литералы ASCII интерпретируются кодом Win32, как если бы они были UTF-16LE, так что строка «Выход» будет считаться двумя символами Unicode, U+7845
и U+7469
, которые обаЕдиные ханские иероглифы.Если у вас не установлены шрифты Han, оба вряд ли будут присутствовать в любом шрифте в вашей системе, поэтому вместо этого вы получите глиф отсутствующего символа.
Это происходит потому, что вы смешиваете макрос-обертку со строковым литералом ASCII,У вас есть:
AppendMenu(hSubMenu, MF_STRING, ID_FILE_EXIT, "Exit");
, но у вас должно быть одно из следующих:
AppendMenu(hSubMenu, MF_STRING, ID_FILE_EXIT, _T("Exit"));
AppendMenuA(hSubMenu, MF_STRING, ID_FILE_EXIT, "Exit");
AppendMenuW(hSubMenu, MF_STRING, ID_FILE_EXIT, L"Exit");
, где я предпочитаю рекомендовать последний пример.