Логический шрифт

Исправляем некорректное отображение кириллицы
  1. Оффлайн

    Автор темы

    Leserg

    Звание: Эксперт

    Команда сайта.

    Сообщений: 581

    Создано тем: 72

    Рейтинг: 7

    Репа: (109|109|0)

    Логический шрифт
    Исправляем некорректное отображение кириллицы


    Итак, вы сделали перевод любимой программы на русский язык, создали локализованный файл, запустили приложение и, вдруг, вместо знакомых символов видите какую-то несуразицу, типа "Ïðèâåò, ìû êðàêîçÿáëèêè!". Блин, что делать?Самое простое решение — выполнить замену кодовых страниц в операционной системе и добавить в реестр параметры подмены шрифтов. К сожалению, такое решение является грубым и будет работать только на вашей системе. Другие пользователи, воспользовавшись вашей работой, вместо текста на русском увидят эту несуразицу и им также придется вносить изменения в свою систему. Это в свою очередь может быть чревато негативными последствиями для других приложений. Впрочем я не буду останавливаться на этом подробно, а предлагаю вам решить проблему отображения символов кириллицы более изящно — в самом файле приложения. Конечно для этого нужны умение работы с отладчиком, знание API-функций и понимание ассемблерных инструкций. Решение не из простых и потребует от вас определенных навыков. Надеюсь, что это небольшое руководство поможет вам самостоятельно справиться с этой проблемой.

    Надеюсь, что это небольшое руководство поможет вам самостоятельно справиться с этой проблемой.

    В данном руководстве рассматриваются API-функции CreateFont и CreateFontIndirect, которые используются для создания логического шрифта. Этот шрифт впоследствии также может использоваться приложением для вывода текстовой и другой информации.



    Читаем здесь
    Сообщение отредактировал WYLEK 26 апреля 2018 - 16:02

    Кто ищет, тот всегда найдет!

    12 мая 2015 - 11:24 / #1
  2. Оффлайн

    Автор темы

    Leserg

    Звание: Эксперт

    Команда сайта.

    Сообщений: 581

    Создано тем: 72

    Рейтинг: 7

    Репа: (109|109|0)

    Цитата: Nexus;16333
    вот как раз по CreateFontIndirect есть интересный экземпляр... Попробуй, получится ли у тебя догадаться в чем загвоздка...



    Логический шрифт
    Сообщение отредактировал WYLEK 29 июля 2018 - 18:18

    Кто ищет, тот всегда найдет!

    28 мая 2015 - 22:28 / #2
  3. Оффлайн

    Nexus

    Звание: Бывалый

    Администраторы

    Сообщений: 371

    Создано тем: 18

    Рейтинг: 6

    Репа: (24|24|0)

    Leserg, значит все таки обратил внимание какую подлянку делает команда REP STOS DWORD PTR [EDI] biggrin
    29 мая 2015 - 00:10 / #3
  4. Оффлайн

    Автор темы

    Leserg

    Звание: Эксперт

    Команда сайта.

    Сообщений: 581

    Создано тем: 72

    Рейтинг: 7

    Репа: (109|109|0)

    Цитата: Nexus;16401
    все таки обратил внимание какую подлянку делает команда REP STOS DWORD PTR [EDI]

    Почему подлянку?! Как раз наоборот, подготавливает область памяти под массив с характеристиками шрифта. Все логично. Многие свойства шрифта по умолчанию имеют значения 0 (ноль), поэтому нет смысла их задавать по отдельности. Правда в своей практике я с таким случаем сталкиваюсь впервые. Однозначно в копилку знаний.biggrin

    Кто ищет, тот всегда найдет!

    30 мая 2015 - 00:26 / #4
  5. Оффлайн

    Nexus

    Звание: Бывалый

    Администраторы

    Сообщений: 371

    Создано тем: 18

    Рейтинг: 6

    Репа: (24|24|0)

    Цитата: Leserg;16408
    Почему подлянку?! Как раз наоборот, подготавливает область памяти под массив с характеристиками шрифта. Все логично.

    Потому что из-за этой команды приходится переносить фрагмент кода в конец файла, некуда здесь втиснуть команду MOV DWORD PTR [ESP+93], 1. Это хорошо что здесь в конце секции кода имеется резерв куда можно примостить свой кусочек кода, в этом файле нужно подправить аж пять таких проблемных мест. А не редко мне попадались файлы, где такой резерв в конце попросту отсутствовал. Приходилось или удлинять секцию кода, или же впихивать свои наработки в промежутки между функциямипроцедурами, там где встречается последовательность байт CCCCCCCC... или 9090909090...
    И вообще, я лично вместо MOV DWORD PTR [ESP+93], 1 вбил MOV DWORD PTR [ESP+90],CC000000, вдруг у конечного пользователя будет не русская локаль, и тогда будут крякозябли. А так надежнее, все для пользователя, его родимого biggrin
    30 мая 2015 - 23:08 / #5
  6. Оффлайн

    Автор темы

    Leserg

    Звание: Эксперт

    Команда сайта.

    Сообщений: 581

    Создано тем: 72

    Рейтинг: 7

    Репа: (109|109|0)

    Nexus, подожди, не кипятись. Обрати внимание, я вместо инструкции MOV DWORD PTR [ESP+93],1, использую инструкцию MOV BYTE PTR [ESP+93],1. Она на три байта короче предыдущей за счет указания другого типа данных. Тип DWORD нуждается в 4-х байтах, а BYTE - всего лишь в одном байте. С таким же успехом можно задать набор символов RUSSIAN_CHARSET, записав вместо 1h значение CCh: MOV BYTE PTR [ESP+93],0СС. Нет нужды использовать тип данных "двойное слово", если нужно изменить всего лишь один байт. Экономия в три байта это вполне существенно, особенно при не хватке или отсутствии достаточно свободного места. Мне тоже попадались программы, где свободного места в конце секции кода не было вообще, и, конечно, приходилось выкручиваться описанными тобой способами.

    В данном конкретном случае можно обойтись без переноса кода. Нужно всего лишь немного подумать. Смотрим код:

    Логический шрифт

    По адресу 00404026 находится инструкция MOV DWORD PTR [ESP+7С],0Е. Её можно изменить на MOV BYTE PTR [ESP+7С],0Е, т.к. ранее область памяти под характеристики шрифта была очищена (заполнена нулями). Таким образом получим выигрыш в три байта. Далее, по адресам 00404010 - 00404020 идет побайтовая запись строки с названием шрифта. Это все можно заменить двумя инструкциями. В итоге код программы примет следующий вид:



    Как видишь, по адресу 00404038 у нас еще один байт лишний остался. Но полученный код делает все тоже самое, что и оригинальный, но кроме него добавлена еще одна инструкция по установке набора символов (по адресу 00404030). Если нужна кириллица, то замени в ней значение 1h на CCh. Еще раз посмотри: мы ничего и никуда не переносили, только переделали участок кода.
    Сообщение отредактировал WYLEK 29 июля 2018 - 18:19

    Кто ищет, тот всегда найдет!

    31 мая 2015 - 11:26 / #6
  7. Оффлайн

    Nexus

    Звание: Бывалый

    Администраторы

    Сообщений: 371

    Создано тем: 18

    Рейтинг: 6

    Репа: (24|24|0)

    Leserg, ты допустил ошибку что похерил цикл побайтовой записи строки с названием шрифта Arial. Теперь программа не воспринимает название шрифта и выдает на экран тот, который стоит по умолчанию в системе пользователя. Попробуй после своей модификации поменять название шрифта Arial на Arial Black. В результате ничего не поменяется. А в оригинальном файле текст в окне About будет написан жирным шрифтом. В чем же причина? Причина в том, что на стек нужно запсывать собственно название шрифта, а после твоей правки на стек записывается адрес, где лежит название шрифта. В результате API функция CreateFont считывает какую-то белиберду вместо названия шрифта, ищет его в системе, естественно не находит и выставляет систеный шрифт по умолчанию, смотря у кого какой установлен.
    Единственное место где можно подоптимизировать - это поменять MOV DWORD PTR [ESP+8C], 320 на MOV WORD PTR [ESP+8C], 320. Выигрыш будет еще в один байт. Дело в том, что DWORD - это 4 байта, а число 320 - это два байта, поэтому поставим WORD,т.е. двухбайтовое выражение. Только толку от такой оптимизации все равно никакой...
    Цитата: gazon01;16419
    Leserg, Nexus,  это уже высшая математика, нам простым смертным да такого очень далеко

    Фигней страдаем biggrin
    1 июня 2015 - 00:07 / #7
  8. Оффлайн

    Автор темы

    Leserg

    Звание: Эксперт

    Команда сайта.

    Сообщений: 581

    Создано тем: 72

    Рейтинг: 7

    Репа: (109|109|0)

    Цитата: Nexus;16429
    Leserg, ты допустил ошибку


    Твоя правда. Тогда можно сделать так:

    Логический шрифт


    В этом случае тоже, ничего и никуда переносить не нужно. ::002::
    Для адресации используем адрес из регистра ECX, который в текущий момент там находится. Тогда смещение будет меньше значения 7F, что уменьшит длину инструкций. Также не забываем оперировать типами данных (BYTE, WORD, DWORD).

    Цитата: Nexus;16429
    Фигней страдаем


    Ага, и не говори. Он даже gazon01'у стало интересно, чем это мы тут занимаемся. Там гляди народ потянется и больше не будет проблемы под названием "кракозябры". Надо почаще такие диспуты устраивать. biggrin_mini2

    Цитата: dinis124;16428
    А программой Topo v1.2 можно решать такие проблемы?

    Я не знаю, никогда такой программой не пользовался. Вообще весь мой опыт по удлинению секций сводился к дописыванию нулевых байтиков в конце файла при помощи НЕХ-редактора.
    Сообщение отредактировал WYLEK 29 июля 2018 - 18:20

    Кто ищет, тот всегда найдет!

    2 июня 2015 - 00:43 / #8
  9. Оффлайн

    Горыныч

    Участники

    Сообщений: 2

    Создано тем: 0

    Репа: 0

    Цитата: Kopejkin;16275
    Позвольте с вами не согласиться! Читают! Другое дело -  откликов нет/мало. Причина, как мне кажется, в серьезности материала, требующего осмысления, попыток практического применения, изучения дополнительных материалов и т.п.
    Например, для меня  - это пока не очень понятно и довольно-таки сложно. И не потому, что плохо написано. Как раз, наоборот - это мне не хватает знаний!
    Ваш материал уникален и он будет востребован. Поэтому, не поддавайтесь сомнениям и продолжайте.
    Спасибо!
    Присоединяюсь полностью, долго не мог разобраться с кодировкой..., по инструкции - на раз..
    Ребята... ваша работа реально нужна    СПАСИБО !!
    18 января 2016 - 18:30 / #9

Статистика форума, пользователей онлайн: 0 (за последние 20 минут)

---
Создано тем
861
Всего сообщений
7519
Пользователей
14561
Новый участник
Виктор Павлов