Форум программистов, компьютерный форум, киберфорум
C++ Builder
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.58/50: Рейтинг темы: голосов - 50, средняя оценка - 4.58
Маэстро
Вирусоборец
 Аватар для Maestro
1244 / 365 / 40
Регистрация: 06.09.2009
Сообщений: 798

Кириллица в WIN32 GUI приложениях

04.10.2009, 11:59. Показов 10870. Ответов 13
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Всем привет. Снова опять к вам, вопрос у меня давний и наболевший, моими силами не решаемый. Ребята, буду благодарен и признателен. Просто уже не знаю, что куда приткнуть...

Я хочу чтобы моя программа работала в английской версии OS, независимо от выбора языка в панели управления - язык и региональные стандарты. Тоесть если по умолчанию у пользователя выставлено English, то чтобы моя программа показывала русский текст, а не знаки вопросов. Конечно, можно выбрать Russian, но хотелось бы иметь независимую версию от настроек.

Знаю, что Vista, не корректно работает с установками и если в Инспекторе объектов, в свойстве Font - Charset выбрать - Default_Charset, то даже на локализованой версии Vista, будут иероглифы, нужно выбирать значение Russian_Charset. В Windows XP, Windows 7, всё работает отлично не зависимо от настроек Charset. С этим я разобрался, вот осталось только "приручить" программу для английских версий OS'и.

Вот что я использую. Вместо версии WinMain попробовал использовать - wWinMain, но выходит ошибка компоновщика:

[Компоновщик Ошибка] Unresolved external 'WinMain' referenced from C:\PROGRAM FILES\BORLAND\CBUILDER6\LIB\C0W32.OBJ
Изменял значение передаваемых параметров в wWinMain с LPSTR - это в WinMain было, а в wWinMain - LPTSTR. Также поискав в гугле, нашёл множество решений, некоторые не сработали, а некоторые применить в своём примере, у меня на данный момент, не хватает знаний. Этот совет - Шаг 90 - Исправление ошибок, связанных с настройками проектов не помогает, так же. И в общем есть несколько вопросов:

1. Как устранить всё же эту ошибку компоновщика? (Поможет ли это устранение создать программу с корректным отображением кирилицы на англ. осях?)
2. Покажите на примере, что нужно добавить или дописать, чтобы программа корректно отображала кирилицу на английских операционных системах не зависимо от настроек?

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include <windows.h>
 
#ifndef UNICODE
#define UNICODE
#endif
 
#ifndef _UNICODE
#define _UNICODE
#endif
 
#if !(defined(_UNICODE) | defined(UNICODE))
#error no Unicode!
#endif
 
//---------------------------------------------------------------------------
USEFORM("Test1.cpp", Form1);
//---------------------------------------------------------------------------
extern "C" int WINAPI wWinMain(HINSTANCE, HINSTANCE, LPTSTR, int)
{
        try
        {
                 Application->Initialize();
                 Application->CreateForm(__classid(TForm1), &Form1);
                 Application->Run();
        }
        catch (Exception &exception)
        {
                 Application->ShowException(&exception);
        }
        catch (...)
        {
                 try
                 {
                         throw Exception("");
                 }
                 catch (Exception &exception)
                 {
                         Application->ShowException(&exception);
                 }
        }
        return 0;
}
//---------------------------------------------------------------------------
Проект прикрепляю. Программа состоит из метки Label1 на которой написан текст на русском, для тестового запуска и кнопки для выхода. При комплиляции сообщает об ошибке линковки, ошибка приведена выше. Среда разработки:
Borland C++ Builder 6.0 Enterprise Suite
Вложения
Тип файла: rar Test.rar (194.1 Кб, 40 просмотров)
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
04.10.2009, 11:59
Ответы с готовыми решениями:

Вывод нулей перед числом в приложениях GUI WIN32
Привет всем. :friends: Я немного запутался, нужна помощь. Вопрос такой: Есть несколько тысяч файлов с одинаковыми именами...

Кириллица WIN32 CA
Добрый вечер! прошу помощи - возникла проблема с кириллицей VS 2008 Win32 CA есть txt файл, из которого считываю строки. Для сортировки...

Графика в консольных приложениях WIN32
Всем привет))) Может тупой вопрос но оч надо узнать, как работать с простой графикой на новых версиях VC++. Я знаю что нужен graphic.h. Но...

13
Маэстро
Вирусоборец
 Аватар для Maestro
1244 / 365 / 40
Регистрация: 06.09.2009
Сообщений: 798
04.10.2009, 12:16  [ТС]
Забыл дописать, пробовал использовать следующий макрос:
C++
1
2
   Button1->Caption = TEXT("Кнопка Выхода");
   Label1->Caption = TEXT("Русский текст");
Работает частично, для GroupBox и RadioGroup отображается независимо от настроек контрольной панели, а для других элементов - нет.
0
Маэстро
Вирусоборец
 Аватар для Maestro
1244 / 365 / 40
Регистрация: 06.09.2009
Сообщений: 798
06.10.2009, 15:05  [ТС]
...Итак, поскольку ответ не был получен, я решил поспрашивать о своём вопросе ещё на других ресурсах, поскольку ссылки на другие ресурсы запрещены, то выкладываю ответ в форме цитаты:
Все дело в том, что в AnsiString ресурсах (которые Борланд 6 поддерживает) только 8 бит, а надо 16 - т.е. Unicode. Знаки вопроса - это символы, которые попадают в доп. область кодовой таблицы и заменяются (системой или Борландом) на 0xFF.
Вот такой нерадостный ответ был получен. Рекомендация перейти на C++ Builder 2009 помогла решить вопрос, пока что элементы управления корректно отображают кирилицу, потихоньку проверю "начинку" и весь код. После проверки и отладки отпишусь.

Резюмимрую: Вопрос формально решён, но в целом, полурешён. Если всё же можно что-то сделать с Borland C++ Builder 6.0, пишите, буду благодарен советам и помощи.
0
 Аватар для Otaka
1857 / 714 / 55
Регистрация: 11.12.2008
Сообщений: 1,019
06.10.2009, 22:34
Сел я с отладчиком смотреть как Винда преобразует Ansi в Unicode при вызове неюникодных функций. Кто не знает, то все функции типа TextOutA MessageBoxA есть просто переходниками к функциям TextOutW MessageBoxW с преобразованием 1 байтовых строк в 2 байтовые. Так вот, я хотел найти момент, где вызывается функция MultiByteToUnicode и может подменить параметр исходной кодировки(а она ACP) на, например 1251(win-cirilyc), так вот лазая по всем просторам забубенных вызовов, я увидел, что внутри там такая каша. ACP можно получить несколькими способами(а можно и не получать её вообще), в ntdll.dll есть еще куча функций, которые делают практически одно и тоже. Некоторые функции есть просто переходниками друг к другу. Где там корень? Думал подменивать значение которое получается из настроек nls в реестре на свои, так приложение их не читает. Странно это все. Даже и не знаю.
Надо копать глубже. Как будет свободное время надо будет еще раз пересмотреть.
1
Маэстро
Вирусоборец
 Аватар для Maestro
1244 / 365 / 40
Регистрация: 06.09.2009
Сообщений: 798
07.10.2009, 10:45  [ТС]
Otaka, Спасибо за неравнодушие к вопросу.
0
Маэстро
Вирусоборец
 Аватар для Maestro
1244 / 365 / 40
Регистрация: 06.09.2009
Сообщений: 798
09.10.2009, 16:04  [ТС]
Ребята, в общем, по этому вопросу у меня почти всё получилось, кирилический текст корректно отображается на элементах управления и уведомлениях MessageBox. Текстовые файлы с русским текстом сохранённые в кодировке UTF-8, (там ещё галочка BOM устанавливалась) корректно загружаются в Memo1 и отображаются. Проект решения прикреплю чуть позже, после окончательной отладки, возможно кому-то будет интересен.

Но вот с чем ещё столкнулся и как решить не умею. Программа запускается на английской системе, в Memo вводится русский текст, и файл сохраняется автоматом по нажатию на кнопку Сохранить:

C++
1
2
3
4
void __fastcall TForm1::Button1Click(TObject *Sender)
{
   Memo1->Lines->SaveToFile("SaveFile.txt");
}
Но! Сохраняется он хоть и в UTF-8, но при открытии снова, отображается содержимое вопросительными знаками, для проверки я открыл его в AkelPad, вижу, кодировка UTF-8, но галочка BOM снята. Вопрос вот в чём:

Как правильно сохранить файл .txt, чтобы он сохранялся правильно, а при загрузке обратно, отображал не вопросительные знаки, а нормальный русский текст.

С функциями перекодирования работать не умею, в гугле искал, но там большая часть на примеры Delphi, я в нём не понимаю, если не сложно покажите на примере.
0
 Аватар для Otaka
1857 / 714 / 55
Регистрация: 11.12.2008
Сообщений: 1,019
09.10.2009, 20:10
Я не знаю, но у меня в 6 билдере при использовании стандартных компонентов никакой UTF-8 не работает. Но прекрасно работает юникод при использовании TMS component pack(UNICODE). А перекодировка - WideCharToMultiByte, почитай справку по функции.
0
Маэстро
Вирусоборец
 Аватар для Maestro
1244 / 365 / 40
Регистрация: 06.09.2009
Сообщений: 798
09.10.2009, 20:36  [ТС]
Цитата Сообщение от Otaka Посмотреть сообщение
но у меня в 6 билдере при использовании стандартных компонентов никакой UTF-8 не работает
Дело в том, что этот проект я уже собираю с помощью C++ Builder 2009
0
Маэстро
Вирусоборец
 Аватар для Maestro
1244 / 365 / 40
Регистрация: 06.09.2009
Сообщений: 798
11.10.2009, 14:11  [ТС]
Цитата Сообщение от Otaka Посмотреть сообщение
Но прекрасно работает юникод при использовании TMS component pack(UNICODE).
Скачал - C++Builder 2009 (879.54 KB), установил, но как работать с ним, так и не понял.

Цитата Сообщение от Otaka Посмотреть сообщение
WideCharToMultiByte, почитай справку по функции.
Справку читал, хоть пришлось долго ждать пока страница откроется. Но по честному понял мало чего.
Code
1
2
3
4
5
6
7
8
9
10
int WideCharToMultiByte(
  UINT CodePage, 
  DWORD dwFlags, 
  LPCWSTR lpWideCharStr, 
  int cchWideChar, 
  LPSTR lpMultiByteStr, 
  int cbMultiByte, 
  LPCSTR lpDefaultChar, 
  LPBOOL lpUsedDefaultChar 
);
По описанию сигнатуры понял, что нужно первый параметр писать CP_UTF8, второй, наверное - WC_DEFAULTCHAR, а дальше темнота.
Пробовал делать так, но это неправильно.
C++
1
2
3
4
5
6
7
...
void __fastcall TForm1::Button4Click(TObject *Sender)
{
   WideCharToMultiByte(CP_UTF8, 0, Memo1->Lines->GetText(), -1, Memo1->Lines->Add(Memo1->Text), -1, NULL, NULL);
   Memo1->Lines->SaveToFile("SaveFile.txt");
}
...
Но тут ошибка в строке Memo1->Lines->Add(Memo1->Text), неправильно использую параметр, нужно число, какое только, не могу сообразить.

Мне бы на примере показать, на живом коде...
0
 Аватар для Otaka
1857 / 714 / 55
Регистрация: 11.12.2008
Сообщений: 1,019
11.10.2009, 17:17
Если у тебя билдер 2009, то никакие TMS тебе не нужны. Все и так юникодное. А как пример преобразования скидываю код, которым я всегда пользуюсь.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
wchar_t * utf8_to_unicode(char *utf8_string)
{
    int err;
    wchar_t * res;
    int res_len = MultiByteToWideChar(
        CP_UTF8,            // Code page
        0,                  // No flags
        utf8_string,        // Multibyte characters string
        -1,                 // The string is NULL terminated
        NULL,               // No buffer yet, allocate it later
        0                   // No buffer
        );
    if (res_len == 0) 
    {
        return NULL;
    }
    res = (wchar_t*)calloc(sizeof(wchar_t), res_len);
    if (res == NULL) 
    {
        return NULL;
    }
    err = MultiByteToWideChar(
        CP_UTF8,            // Code page
        0,                  // No flags
        utf8_string,        // Multibyte characters string
        -1,                 // The string is NULL terminated
        res,                // Output buffer
        res_len             // buffer size
        );
    if (err == 0)
    {
        free(res);
        return NULL;
    }
    return res;
}
char * unicode_to_1251(wchar_t *unicode_string)
{
    int err;
    char * res;
    int res_len = WideCharToMultiByte(
        1251,               // Code page
        0,                  // Default replacement of illegal chars
        unicode_string,     // Multibyte characters string
        -1,                 // Number of unicode chars is not known
        NULL,               // No buffer yet, allocate it later
        0,                  // No buffer
        NULL,               // Use system default
        NULL                // We are not interested whether the default char was used
        );
    if (res_len == 0) 
    {
        return NULL;
    }
    res = (char*)calloc(sizeof(char), res_len);
    if (res == NULL) 
    {
        return NULL;
    }
    err = WideCharToMultiByte(
        1251,               // Code page
        0,                  // Default replacement of illegal chars
        unicode_string,     // Multibyte characters string
        -1,                 // Number of unicode chars is not known
        res,                // Output buffer
        res_len,            // buffer size
        NULL,               // Use system default
        NULL                // We are not interested whether the default char was used
        );
    if (err == 0)
    {
        free(res);
        return NULL;
    }
    return res;
}
1
Маэстро
Вирусоборец
 Аватар для Maestro
1244 / 365 / 40
Регистрация: 06.09.2009
Сообщений: 798
11.10.2009, 17:54  [ТС]
Otaka, Спасибо, подобный код через гугл находил, но я не знаю, как прикрутить этот код к кнопке Button. Весь текст находится в Memo, как его передать функции?
Файл .h
Code
1
2
3
4
...
    void __fastcall Button4Click(TObject *Sender);
    wchar_t* __fastcall utf8_to_unicode(char *utf8_string);  // Объявил эту функцию тут.
...
Файл .cpp

Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
//---------------------------------------------------------------------------
wchar_t* __fastcall TForm1::utf8_to_unicode(char *utf8_string)
{
        int err;
        wchar_t * res;
        int res_len = MultiByteToWideChar(
                CP_UTF8,                        // Code page
                0,                                      // No flags
                utf8_string,            // Multibyte characters string
                -1,                                     // The string is NULL terminated
                NULL,                           // No buffer yet, allocate it later
                0                                       // No buffer
                );
        if (res_len == 0)
        {
                return NULL;
        }
        res = (wchar_t*)calloc(sizeof(wchar_t), res_len);
        if (res == NULL)
        {
                return NULL;
        }
        err = MultiByteToWideChar(
                CP_UTF8,                        // Code page
                0,                                      // No flags
                utf8_string,            // Multibyte characters string
                -1,                                     // The string is NULL terminated
                res,                            // Output buffer
                res_len                         // buffer size
                );
        if (err == 0)
        {
                free(res);
                return NULL;
        }
        return res;
}
//-----------
0
 Аватар для Otaka
1857 / 714 / 55
Регистрация: 11.12.2008
Сообщений: 1,019
11.10.2009, 18:34
Ты знаешь, я так подумал, этот код не поможет.
Ты скажи лучше, в Билдере 2009 там у Memo->Lines какой там внутри тип, AnsiString или WideString?
0
Маэстро
Вирусоборец
 Аватар для Maestro
1244 / 365 / 40
Регистрация: 06.09.2009
Сообщений: 798
11.10.2009, 19:14  [ТС]
Цитата Сообщение от Otaka Посмотреть сообщение
в Билдере 2009 там у Memo->Lines какой там внутри тип, AnsiString или WideString?
Файл SaveFile.txt сохраняется в ANSI, значит AnsiString.
0
Маэстро
Вирусоборец
 Аватар для Maestro
1244 / 365 / 40
Регистрация: 06.09.2009
Сообщений: 798
14.10.2009, 12:34  [ТС]
Otaka, Мне помогли решить вопрос. Цитату привожу.
метод SaveToFile имеет второй параметр, и если он не указан, то содержимое мемо сохраняется в текущей кодировке мммм... винды.
соответственно можно указывать желаемую кодировочку:
- TEncoding::Unicode
- TEncoding::UTF8
- TEncoding::Default
- TEncoding::ASCII
Всё решается просто. Добавляем второй параметр, который нам нужен:

C++
1
2
3
4
void __fastcall TForm1::Button4Click(TObject *Sender)
{
   Memo1->Lines->SaveToFile("SaveFile.txt", TEncoding::Unicode);
}
Вопрос успешно решён.
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
14.10.2009, 12:34
Помогаю со студенческими работами здесь

Не выводится консоль в Win32 приложениях
собственно такая проблема. когда запускаешь проект в visual studio 2010 (любой, даже только что созданый, т.е. пустой) не выводится консоль...

Использование графических ресурсов в приложениях Win32
Помогите исправить ошибку:error C2664: LoadCursorW: невозможно преобразовать параметр 2 из &quot;int&quot; в &quot;LPCWSTR&quot; 1&gt; ...

Интерфейс (GUI) в приложениях WinAPI
Собственно, вопросов несколько. Читал МСДН, в целом ясен принцип разработки на WinAPI, к тому же было проще, когда юзал всякие...

Scilab и кириллица при создании GUI оболочки
Всем здраствуйте! Помогите пожалуйста с проблемой русской кодировки для gui приложения. Вместо букв - квадраты. Как бороться? Файл...

GUI HTML Win32
Собственно стоит такая задача: программа Win32 App, MVS2012 и должно все это дело(окна) быть красивым, не в стиле 98-х... более того -...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
14
Ответ Создать тему
Новые блоги и статьи
SDL3 для Web (WebAssembly): сборка C/C++ проекта из консоли
8Observer8 30.01.2026
Содержание блога Если вы откроете примеры для начинающих на официальном репозитории SDL3 в папке: examples, то вы увидите, что все примеры используют следующие четыре обязательные функции, а. . .
Установка Emscripten SDK (emsdk) и CMake на Windows для сборки C и C++ приложений в WebAssembly (Wasm)
8Observer8 30.01.2026
Чтобы скачать Emscripten SDK (emsdk) необходимо сначало скачать и уставить Git: Install for Windows. Следуйте стандартной процедуре установки Git через установщик. Система контроля версиями Git. . .
Подключение Box2D v3 к SDL3 для Android: физика и отрисовка коллайдеров
8Observer8 29.01.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами. Версия v3 была полностью переписана на Си, в. . .
Инструменты COM: Сохранение данный из VARIANT в файл и загрузка из файла в VARIANT
bedvit 28.01.2026
Сохранение базовых типов COM и массивов (одномерных или двухмерных) любой вложенности (деревья) в файл, с возможностью выбора алгоритмов сжатия и шифрования. Часть библиотеки BedvitCOM Использованы. . .
Загрузка PNG с альфа-каналом на SDL3 для Android: с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 28.01.2026
Содержание блога SDL3 имеет собственные средства для загрузки и отображения PNG-файлов с альфа-каналом и базовой работы с ними. В этой инструкции используется функция SDL_LoadPNG(), которая. . .
Загрузка PNG с альфа-каналом на SDL3 для Android: с помощью SDL3_image
8Observer8 27.01.2026
Содержание блога SDL3_image - это библиотека для загрузки и работы с изображениями. Эта пошаговая инструкция покажет, как загрузить и вывести на экран смартфона картинку с альфа-каналом, то есть с. . .
Влияние грибов на сукцессию
anaschu 26.01.2026
Бифуркационные изменения массы гриба происходят тогда, когда мы уменьшаем массу компоста в 10 раз, а скорость прироста биомассы уменьшаем в три раза. Скорость прироста биомассы может уменьшаться за. . .
Воспроизведение звукового файла с помощью SDL3_mixer при касании экрана Android
8Observer8 26.01.2026
Содержание блога SDL3_mixer - это библиотека я для воспроизведения аудио. В отличие от инструкции по добавлению текста код по проигрыванию звука уже содержится в шаблоне примера. Нужно только. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru