PDA

Показать полную графическую версию : [решено] Кирилица в WIN32 GUI приложениях независимо от настроек в контрольной панели


Страниц : [1] 2

Drongo
14-07-2009, 12:46
Доброго всем здоровья. Нужна ваша помощь. :) Возникла необходимость написать программку, чтобы она работала на Windows XP и Widnwows Vista (если будет работать на Windows 7, будет вообще здорово, но проверить негде... Нет знакомых с семёркой). На ХР работает как часики, а на Vista не совсем. Не отображаются правильно русские символы. Скриншот приложу.

http://i028.radikal.ru/0907/a6/4600553ae59bt.jpg (http://radikal.ru/F/i028.radikal.ru/0907/a6/4600553ae59b.jpg.html)

Проверял на Windows Vista Home Premium (SP1). Версия русская.

Получается следующее, интерфейс на русском, и некоторые записи (описания в GroupBox) не отображают правильно кирилицу, а некоторые, на кнопках и переключателях нормально отображают, что сделать - не знаю совсем. Прошу помощи. Английский интерфейс это не вариант потому что там ещё будет ComboBox (при выборе локализации "русская Windows") в котором будет выбор текста на русском, по другому нельзя. Архив проекта прикрепляю, там находится также и исполнимый файл. Программная среда в которой разрабатывается приложение: Borland C++ Builder 6.0 Enterprise Suite

Dmitrijan
14-07-2009, 15:32
Drongo, Кое что могу подсказать. Я тоже как-то разрабатывл програмку (правда на Delphi)
и столкнулся с такой же проблемкой.Из под Виста-кракозябры, из под XP все гуд.Правда не все надписи.Оказалось надо было в свойствах шрифтов выставить CharSet: RUSSIAN_CHARSET.А те которые отображали кракозябры было (ANSI_CHARSET).Но это опять же Delphi, но думаю свойства шрифтов во всех языках одинаковы.
P.S. Глянул вашу програмку из под семерки все гуд (все на русском)! :)

Drongo
14-07-2009, 17:24
Оказалось надо было в свойствах шрифтов выставить CharSet: RUSSIAN_CHARSET.А те которые отображали кракозябры было (ANSI_CHARSET). »Сейчас проверим. :) Да, действительно, настройка есть, изменил, сейчас попробуем на Vista, отпишусь. А эти настройки не будут влиять на отображение символов в семёрке?
Глянул вашу програмку из под семерки все гуд (все на русском)! »А если не затруднит, посмотрите, в поле Edit появляется имя учётной записи?

Но это опять же Delphi, но думаю свойства шрифтов во всех языках одинаковы. »Всё верно. :yes:

http://i080.radikal.ru/0907/9c/3376fd0794a8t.jpg (http://radikal.ru/F/i080.radikal.ru/0907/9c/3376fd0794a8.png.html)

Dmitrijan
14-07-2009, 17:44
А эти настройки не будут влиять на отображение символов в семёрке? » Только что запустил семерку, проверил свою прогу все Ok :) Значит и из под Vista и из под Seven настройка работает одинаково - положительно.
А если не затруднит, посмотрите, в поле Edit появляется имя учётной записи? »
Все нормально, имя учетной записи есть (правда у меня учетная запись на англ. "Dmitrijan") :)

Drongo
14-07-2009, 18:04
(правда у меня учетная запись на англ. "Dmitrijan") »Проверили - русская учётка работает, определяется.
Протестировали на Vista, по вашему совету изменил в свойствах Font -> Charset - значение с DEFAULT_CHARSET на RUSSIAN_CHARSET и всё заработало правильно:

http://s41.radikal.ru/i091/0907/5a/5fa6bae23a9dt.jpg (http://radikal.ru/F/s41.radikal.ru/i091/0907/5a/5fa6bae23a9d.jpg.html)

Dmitrijan, Спасибо!!! :yahoo: :Beer: :up: :hi: Вопрос успешно решён.

P.S. А всё-таки, почему при значении - DEFAULT_CHARSET на семёрке всё ок, а на висте кривовато?

Dmitrijan
14-07-2009, 18:22
P.S. А всё-таки, почему при значении - DEFAULT_CHARSET на семёрке всё ок, а на висте кривовато? »
В принципе я не знаю почему так происходит, но думаю в Viste по дефолту стоит другая кодировка, отличающаяся от дефолтной Seven. Но это только мое мнение.
P.S. Очень рад, что у вас все получилось!!! :)

Drongo
17-07-2009, 10:47
Здравствуйте, это снова я, но уже с несколько другим вопросом. Вот с русской Windows всё в порядке, а если эту же программу с русским интерфейсом запустить на английской версии? Мне кажется вместо русских символов будут знаки вопроса "?????". Я так понял, что нужно русские шрифты загрузить в проект в ресурсы и использовать шрифт из внутренних ресурсов программы? Но я не знаю как это сделать. Покажите на примере кому не трудно.

AddFontResource
int AddFontResource(LPCTSTR lpszFilename);
Возвращаемое значение
В случае успешного завершения функции возвращается количество добавленных шрифтов, в противном случае возвращается нулевое значение. В Windows NT более подробную информацию об ошибке можно получить, вызвав функцию GetLastError.
Аргументы
lpszFilename - указатель на заканчивающуюся нулем текстовую строку, содержащую корректное имя файла шрифта. Имя файла шрифта имеет расширение .fon для файлов ресурса шрифта, расширение .fnt для файлов шрифта, содержащих битовые образы символов, расширение ttf для файлов шрифтов TrueType и расширение .fot для файлов ресурсов шрифтов TrueType.


Описание Функция AddFontResource позволяет добавить ресурсы шрифта из указанного файла в системную таблицу шрифтов. После этого данный шрифт может быть использован для вывода текста любым приложением Win32. Любые приложения, добавляющие или удаляющие шрифты из системной таблицы шрифтов, извещают об этом другие приложения посылкой сообщения WM_FONTCHANGE всем окнам верхнего уровня в операционной системе. Для посылки этого сообщения приложение должно использовать функцию SendMessage, в аргументе hWnd которой должно стоять значение HWND_BROADCAST. Как только приложение перестает использовать ресурс шрифта, загруженный функцией AddFontResource, оно должно удалить его функцией RemoveFontResource.
Только я всё равно не пойму, как добавить, встроить? шрифт в программу.

Dmitrijan
17-07-2009, 17:49
Drongo, Возможно при установке значения шрифта RUSSIAN_CHARSET, шрифт включится в проект автоматически при компиляции.
В Delphi шрифты включал, помню как, а вот СИ++ извеняйте не работал в нем, могу написать как в Delphi если надо :)

Drongo
17-07-2009, 18:30
В Delphi шрифты включал, помню как, а вот СИ++ извеняйте не работал в нем, могу написать как в Delphi если надо »Конечно надо. :) Во всяком случае можно будет хоть попробовать понять. Если можно с комментариями.

Dmitrijan
17-07-2009, 19:35
Drongo, Вот я включал шрифт по такой инструкции:

Включение шрифта в ваш EXE:

Создайте в текстовом редакторе файл с расширением *.rc , описывающий шрифт:

MY_FONT ANYOL1 "Bauhs93.ttf"

Первые два параметра могут быть любыми. Они будут использоваться в программе
позже.

Затем для создания *.res файла используйте компилятор командной строки BRCC32.EXE, поставляемый с Delphi. Если ваш файл на этапе 1 был назван MyFont.rc, командная строка в сеансе DOS должна выглядеть так:

BRCC32 MyFont

Программа добавит в компилируемый файл созданный ресурс .rc и создаст файл с тем же именем, за исключением расширения, которое будет .res: MyFont.res

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

{$R MyFont.res}

Правильным будет разместить его в секции реализации после строчки {$R *.DFM}.

Добавьте процедуру создания файла из ресурса, делающим шрифт доступным для использования. Пример:

procedure TForm1.FormCreate(Sender: TObject);
var
Res : TResourceStream;
begin
Res := TResourceStream.Create(hInstance, 'MY_FONT', Pchar('ANYOL1'));
Res.SavetoFile('Bauhs93.ttf');
Res.Free;
AddFontResource(PChar('Bauhs93.ttf'));
SendMessage(HWND_BROADCAST,WM_FONTCHANGE,0,0);
end;

программное удаление шрифта:

procedure TForm1.FormDestroy(Sender: TObject);
begin
RemoveFontResource(PChar("Bauhs93.ttf"))
SendMessage(HWND_BROADCAST,WM_FONTCHANGE,0,0);
end;

Извените, но больше сегодня не смогу написать, конец рабочего дня

Drongo
18-07-2009, 16:52
Вот я включал шрифт по такой инструкции: »К сожалению, неполучилось... Хотя за попытку помочь, благодарю.
Вчера вечером почти весь вечер делал и почти пол ночи искал инфу, на Delphi\Pascal есть ( http://articles.org.ru/cn/showdetail.php?cid=6949), на C++ практически ничего внятного не нашёл или пропустил по незнанию.
Консольный компилятор есть bcc32.exe. Создавал я файл MyFont.rc, но в MyFont.res такой командой ничего не скомпилилось. bcc32.exe MyFont.rc

Возможно программисты на Cи помогут? Хотелось бы... :unsure:

ganselo
19-07-2009, 13:58
Drongo »
Я так понял, что у вас не получилось добавить шрифт в *.res файл? Если так, то:
берёте какой нибуть редактор ресурсов и с помощью его добавляете ваш шрифт в *.res файл программы и дальше пишите код приведённый Dmitrijan ».

Drongo
20-07-2009, 14:47
берёте какой нибуть редактор ресурсов и с помощью его добавляете ваш шрифт в *.res файл программы »Хорошо, у меня Restorator открыл в этой программе файл Project1.res. Создал ресурс "Шрифт", что выбирать дальше и как собственно добавлять сам шрифт? Хотелось бы подробное описание, а не общий совет...

http://i056.radikal.ru/0907/d9/73f04233b799.png

ganselo
20-07-2009, 15:55
Drongo
Берёте текстовый файлик . Пишите туда "MY_FONT ANYOL1 "Bauhs93.ttf" " и сохраняете как 1.rc, например . Далее в Builder'e: Проект->Добавить к проекту->выбираете тип файла *.rc->находите файл 1.rc и компилите проект. Файл Bauhs93.ttf должен лежать вместе с 1.rc. Ну и пишите код приведённый Dmitrijan.

Drongo
20-07-2009, 18:11
ganselo, Вооот! Другое дело :yes: Что-то получается, только некоторые части не могу перевести с Delphi на C++.

Delphi
procedure TForm1.FormCreate(Sender: TObject);
var
Res : TResourceStream;
begin
Res := TResourceStream.Create(hInstance, 'MY_FONT', Pchar('ANYOL1'));
Res.SavetoFile('Bauhs93.ttf');
Res.Free;
AddFontResource(PChar('Bauhs93.ttf'));
SendMessage(HWND_BROADCAST,WM_FONTCHANGE,0,0);
end;
C++ как и что у меня получилось (потом, когда и если всё получится, детально опишу последовательность действий). Не могу эту часть правильно перевести. Переменная TResourceStream Res; вроде бы создаю, а потом присвоить ей что-то я не пойму как? По ходу нужно использовать оператор new, но на простых типах умею, а вот на таких не приходилось. Думаю с кодом после begin разобрался бы, мне только правильно перевести эту строку - Res : TResourceStream;
// Для своего использования шрифта - Delphi
// Res : TResourceStream; // Объявляем переменную
// begin
// Res := TResourceStream.Create(hInstance, 'MY_FONT', Pchar('ANYOL1'));
// Res.SavetoFile('Bauhs93.ttf');
// Res.Free; // освобождение ресурсов - деструктор.
// Работает только эта часть-----------------------------
AddFontResourceA("verdana.ttf");
SendMessage(HWND_BROADCAST,WM_FONTCHANGE,0,0);

Проект с включенным в него ресурсом для шрифта скомпилился, только без тех строк, что закоментированы. В FormCreate

ganselo
23-07-2009, 14:22
Drongo
Я с Dephi тоже мало знаком... кажись должно быть так:

TResourceStream *res = new TResourceStream(Application->Handle, "MY_FONT", "ANYOL1");
res->SaveToFile("Bauhs93.ttf");

AddFontResourceA("Bauhs93.ttf");
SendMessage(HWND_BROADCAST, WM_FONTCHANGE, 0, 0);

Но я не тестил...

Drongo
23-07-2009, 16:46
Немного не скомпилилось, ошибка в этой строкеTResourceStream *res = new TResourceStream(Application->Handle, "MY_FONT", "ANYOL1"); »
[C++ Ошибка] Unit1.cpp(40): E2285 Could not find a match for 'TResourceStream::TResourceStream(void *,char *,char *)'

Но я тут поискал в гугле правильный синтаксис TResourceStream(void *,char *,char *). Нашёл в первых строках гугла ссылку 1 (http://www.cyberforum.ru/cpp-builder/thread33061.html) и ссылку 2 (http://www.cyberforum.ru/cpp-builder/thread35963.html). Изменил на такой вариант:

...
void __fastcall TForm1::FormCreate(TObject *Sender)
{
TResourceStream *res = new TResourceStream((int)HInstance, "MY_FONT", "ANYOL1");
res->SaveToFile("verdana.ttf");

AddFontResourceA("verdana.ttf");
SendMessage(HWND_BROADCAST, WM_FONTCHANGE, 0, 0);
}...Скомпилилось без проблем. Теперь нужно проверить на английской версии Windows. :) Как проверю, сразу же отпишусь, у меня правда знакомых нет с английской Windows, придётся диск у друга брать. Так что некоторое время займёт.

ganselo, Спасибо за помощь. :up:

Drongo
28-07-2009, 17:35
Проверил на английской Windows, к сожалению с таким кодом ничего не получилось
...
void __fastcall TForm1::FormCreate(TObject *Sender)
{
TResourceStream *res = new TResourceStream((int)HInstance, "MY_FONT", "ANYOL1");
res->SaveToFile("verdana.ttf");

AddFontResourceA("verdana.ttf");
SendMessage(HWND_BROADCAST, WM_FONTCHANGE, 0, 0);
}
...всё равно русские символы выводит вопросительными знаками. Как же всё-таки включить русский шрифт в программу? Что я не так делаю или пропускаю? :dont-know

Admiral
01-10-2009, 22:02
В ходе личной переписки выяснили, версия ОС не причём.
Автору был дал совет использовать Юникод в программе. Однако как выяснилось, мой пример оказался не до конца Юникодным, по этому, его корректное отображение зависело от того, что указанно в Контрольной панели в Региональных настройках. Как оказалось, мало использовать wchar_t вместо char, нужно и саму функцию входа в программу использовать соответственную: вместо WinMain - wWinMain.
К сожалению для консольных версий прог использование wmain вместо main не даёт независимость от того что установлено в Контрольной панели в Региональных настройках. Консоль не использует Юникод вывод.


Вместо того что б предлагать выбор по определению языковой версии, лучше её определять. Например считывая атрибуты файла kernel32.dll проверять что там написано: Корпорация Мискрософт или Microsoft Corporation.
Не исключаю, что патчи, которые сообщают что они "не предназначены для данной языковой версии", проверяют это как-то по-другому, в этом случаи APIMonitor поможет определить как именно.

Drongo
02-10-2009, 12:49
Admiral, Спасибо за помощь и проявленный интерес к проблеме.нужно и саму функцию входа в программу использовать соответственную: вместо WinMain - wWinMain. »Я сравнивал ваш исходник для MultiBoot Configurator'a, но как использовать эту функцию в своей, не имею представления, там ведь проект .bpr. Функции WinMain вроде как только в файле - Project1.cpp - коммент 15 (http://forum.oszone.net/post-1172925-15.html).

Я добавил перед функцией WinMain - символ - wWinMain. Попробовал откомпилировать, ошибка компоновщика. Что WinMain ссылается на COW32.OBJ
[Компоновщик Ошибка] Unresolved external 'WinMain' referenced from C:\PROGRAM FILES\BORLAND\CBUILDER6\LIB\C0W32.OBJ

//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
//---------------------------------------------------------------------------
USEFORM("Unit1.cpp", Form1);
//---------------------------------------------------------------------------
WINAPI wWinMain(HINSTANCE, HINSTANCE, LPSTR, 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;
}
//---------------------------------------------------------------------------
По wWinMain нашёл статью - Точка входа в программу (http://www.cyberguru.ru/programming/cpp/application-downsizing-page3.html), но мне ничего это не дало.
[hr]
Вместо того что б предлагать выбор по определению языковой версии, лучше её определять. »Я тоже об этом думал. :yes:
Например считывая атрибуты файла kernel32.dll проверять что там написано: Корпорация Мискрософт или Microsoft Corporation. »Так?
FileGetAttr(C:\\windows\\system32\\kernel32.dll)Установить атрибуты могу: Архивный, сктрытый и т.д.

Ещё поискал в гугле, подумал, может нужно эту функцию использовать - GetFileAttributesW ? Хотя никогда использовать её не приходилось.




© OSzone.net 2001-2012