2010-12-13 3 views
1

В настоящее время я изучаю Win32, используя this tutorial, и мне нелегко показать отображаемые символы.Что не так с моим набором символов (Win32 API)

Возьмет, например, этот кусок кода, который добавляет в меню к окну при создании:

case WM_CREATE: { 
      HMENU hMenu, hSubMenu; 
      HICON hIcon, hIconSm; 

      hMenu = CreateMenu(); 
      hSubMenu = CreatePopupMenu(); 

      AppendMenu(hSubMenu, MF_STRING, ID_FILE_EXIT, "Exit"); 
      AppendMenu(hMenu, MF_STRING | MF_POPUP, (UINT)hSubMenu, "File"); 

      hSubMenu = CreatePopupMenu(); 
      AppendMenu(hSubMenu, MF_STRING, ID_STUFF_GO, "&GO"); 
      AppendMenu(hMenu, MF_STRING | MF_POPUP, (UINT)hSubMenu, "&Stuff"); 

      SetMenu(hwnd, hMenu); 

      hIcon = LoadImage(NULL, "Stuff.ico", IMAGE_ICON, 32, 32, LR_LOADFROMFILE); 

      if (hIcon) 
       SendMessage(hwnd, WM_SETICON, ICON_BIG, (LPARAM)hIcon); 
      else 
       MessageBox(hwnd, "Could not load large icon!", "Load Error", MB_OK | MB_ICONERROR); 

      hIconSm = LoadImage(NULL, "Stuff.ico", IMAGE_ICON, 16, 16, LR_LOADFROMFILE); 

      if(hIconSm) 
       SendMessage(hwnd, WM_SETICON, ICON_SMALL, (LPARAM)hIconSm); 
      else 
       MessageBox(hwnd, "Could not load small icon!", "Load Error", MB_OK | MB_ICONERROR); 
     } 
     break; 

То есть внутри switch блока внутри моей WndProc функции, которая обрабатывает сообщения Windows, полученные из цикла обработки сообщений.

Каждая строка, которая будет отображаться:

"Exit" 
"File" 
"&GO" 
"&Stuff" 

неразборчивое во время выполнения, как они отображаются в виде маленьких квадратиков, так же, как кодовая не был правильным или что-то подобное. Когда я запускаю учебник, все строки отображаются правильно. Я, как правило, придерживаюсь того, что говорит учебник, чтобы помочь мне правильно разобраться, и его педагогика хороша. ! Во всяком случае ...

Я использую:

  1. Microsoft Visual Studio 2008 Team System;
  2. Microsoft Windows Server 2003 с использованием RDP;
  3. Локальная ОС - Windows Vista Ultimate.

У кого-нибудь есть подсказка?

ответ

6

У вас возникла проблема с кодировкой символов Unicode и Windows ANSI. Исторически Windows использовала расширенный ASCII, который они неправильно назвали ANSI. Это привело к необходимости использования кодовых страниц, потому что даже 8-битный символ не предоставляет достаточного количества кодовых точек для представления всех европейских систем письменности, не говоря уже о остальном мире. Когда Win32 был разработан, они установили Unicode в качестве предпочтительного набора символов. (Фактически, они установили кодировку UTF-16LE набора символов Юникода, но эта деталь не совсем актуальна прямо сейчас.) Однако было слишком много существующего кода, чтобы подумать о том, что перенос с 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 с, но с автоматическим тестированием трудно проверить, что вы правильно их использовали, чтобы код скомпилировался и работал правильно как с UNICODE, так и без него.

Если написание нового кода Win32 сегодня, мой совет будет определять UNICODE в проекте, добавить проверку, что он действительно определен в общем файле заголовка, а также использовать L"" строки и W ароматы всех завернутых вызовов в явном виде.

Наконец, весь этот эссе предлагается вашим кодом, который отображает отсутствующий символ символа (пустой символ квадратного поля - это глиф, который отображается, когда шрифт пропускает определенный символ). Это происходит потому, что ваши строковые литералы ASCII интерпретируются кодом Win32, как если бы они были UTF-16LE, так что строка «Выход» принималась за два символа Unicode: U+7845 и U+7469, которые являются и идеологами Unified Han. Если у вас не установлены шрифты 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"); 

где я предпочитаю рекомендовать последний пример.

+0

+1 и принятый ответ, так как вы отвечаете на детали намного больше, чем требует клиент.Из-за вас я теперь знаю, каковы эти функции с ароматом 'A' и' W', поэтому я буду менять свой код, чтобы отразить эту ценную информацию. Большое спасибо! –

4

Со всей должной странностью относительно маленьких квадратов ваш код неверен. Это не соответствует Unicode. Вы должны префикс всех строк L (как в строке L ") и изменить параметры компиляции на Unicode (это делает функции Windows принятыми кодировкой UTF-16). Это внутренняя кодировка Windows, которая заключается в том, как текст должен был быть сделан для окон.

Альтернативный подход предполагает использование широких API-интерфейсов и преобразование в UTF-16 при вызове API. Он описан в http://utf8everywhere.org.

+0

Ну, я не понимаю, почему в учебнике будет отображаться плохой код? Кроме того, он отлично работает, за исключением кодировки. Я присмотрю за кодировкой, как вы упомянули. –

+0

Это работает, когда я пишу строку «L». –

+1

Судя по датам авторских прав на веб-страницах, этот учебник был написан до того, как Unicode был стандартным в приложениях Win32. Этот код все равно будет компилироваться, если для проекта установлено значение ANSI-набора символов (щелкните правой кнопкой мыши проект в VS, Properties, в разделе General). Причина, по которой код будет примерно работать как с ANSI, так и с Unicode, заключается в том, что AppendMenu #defined для AppendMenuA для ANSI и AppendMenuW для Unicode (широкие символы), переключение на основе этого параметра. Если вы посмотрите на объявления для функций -A и -W, вы увидите, что параметры одинаковы, за исключением строкового параметра. –

 Смежные вопросы

  • Нет связанных вопросов^_^