|
|
Регистрация | << Правила форума >> | FAQ | Пользователи | Календарь | Поиск | Сообщения за сегодня | Все разделы прочитаны |
|
Опции темы | Поиск в этой теме | Опции просмотра |
#1
|
|||
|
|||
Крякозябры вместо русских символов в Windows 10 - при опции Использовать Юникод
Здравствуйте!
Есть программный код на Delphi 7, нормально работает под Windows XP/Vista/7/8/8.1 и до определенных пор на Windows 10. Работает практически при любых языковых настройках - т. к. для борьбы с крякозябрами на англоязычных XP/7 использовала SetThreadLocale(1049) RUSSIAN_CHARSET - в кодировке компонентов, шрифт Arial вместо стандартного MS Sans Serif и прочие ухищрения, что нашла в Сети - таким образом, добилась того, что всё нормально работает практически под любой Windows - при любых языковых настройках (даже если англоязычная Windows и основной язык - французский) Однако, в последних версиях Windows 10 в языковых настройках появилась опция "Бета-версия: Использовать Юникод (UTC-8) для поддержки языка во всем мире"/"Use Unicode UTF-8 for worldwide language support" - которая в некоторых случаях включена по умолчанию (кроме того, после её отключения - чтобы изменения вступили в силу - компьютер нужно перезагружать). Если эта опция включена - в программе вместо русских букв отображаются крякозябры и никакие ухищрения не помогают это исправить - кроме отключения данной галочки. Мне нужно - чтобы программа нормально отображала русские буквы - независимо от состояния данной галочки. Как я понимаю (возможно, ошибаюсь) - нужно как-то перехватывать WinAPI-метод из Kernel32.dll GetACP. В нормальном состоянии эта функция должна возвращать 1251. Она и возвращает 1251 в том числе на Windows 10 - при отключении этой галочки. При включении галочки данная функция возвращает 65001 и программа отображается с крякозябрами. Что пробовала: 1) Перехват функции GetACP - с помощью сплайсинга. Запускаю программу под отладчиком, нахожу адрес процедуры GetACP - в начало этого кода ставлю jmp на свою, правильную функцию, которая возвращает требуемое значение 1251. Результат такой - всё хорошо, функция GetACP теперь возвращает правильное значение 1251 (вместо 65001) - однако, в программе вообще ничего не меняется. Всё равно всё отображается с крякозябрами. 2) Пыталась использовать недокументированную функцию SetCPGlobal(1251); После этого GetACP возвращает правильное значение. Проблема только в том, что работает эта недокументированная функция только на Windows XP - но на XP и без неё всё нормально работает. На Windows 7 и Windows 10 - при попытке использовать данную функцию - при запуске программы выходит сообщение Точка входа в процедуру SetCPGlobal не найдена в библиотеке Kernel32.dll и программа завершает свою работу 3) Пыталась найти - где же функция GetACP получает значение 65001 - чтобы прописать по этому адресу 1251 (как говорят на форумах, это адрес переменной gAnsiCodePage в модуле KernelBase.dll). Нашла адрес - область, откуда берётся это значение, там как раз записано значение 65001. Перезаписываю данную область памяти в значение 1251 с помощью ассемблерной вставки - после этого функция GetACP возвращает значение 1251. На Windows 7: .............................. MyGetACP := GetProcAddressInDll('KernelBase.dll', 'GetACP'); z := ReadMemoryDword(1+integer(Addr(MyGetACP))); WriteMemoryDword(z, 1251); //rewrite value of variable - where keeping GetACP ShowMessage('GetACP: '+inttostr(GetACP)) //на Windows 7 работает .............................. На Windows 10 же (где и требуется решить вопрос с крякозябрами) получается совсем по-другому. Как только пытаюсь перезаписать значение данной ячейки в 1251 - тут же появляется ошибка Exception EAccessViolation in module KernelBase.dll at 000F69ED. Access violation at address 76D269ED in module 'KernelBase.dll'. Read of address 00000002. и программа вылетает. При этом перезапись ячейки памяти делаю как полагается - перед перезаписью устанавливаю признак PAGE_EXECUTE_READWRITE для перезаписываемой области памяти: VirtualProtect(pointer(a), 16, PAGE_EXECUTE_READWRITE, OldProtect) Пробовала в качестве экспериментов записывать в эту ячейку значения 1252, 65001 (то есть исходное значение) и даже 9999 - всё отрабатывает нормально (но потом в ходе работы программы возникают ошибки). Если же записать 1251 - программа вылетает сразу. Возникает вопрос - что делать, чтобы программа работала на Windows 10 без крякозябр вместо русских букв при включенной опции "Бета-версия: Использовать Юникод (UTC-8) для поддержки языка во всем мире". Варианты перейти с Delphi 7 на другую, более новую версию - не предлагать (очень много старого кода придётся переписывать, который при переписывании может начать глючить и т. д.) Варианты с TntComponents и JEDI тоже не подойдут - т. к. программа содержит гигантское количество старого программного кода - где используются стандартные компоненты TLabel, TButton, TEdit - даже если новый код писать на JEDI - надо чтобы старый код и старые формы работали без крякозябр. Как правильно перехватить GetACP, чтобы она всегда возвращала значение 1251? Как заставить программу работать без крякозябр? Дело ведь в GetACP - туда надо копать или в чем можем быть дело? С уважением, Сидорова А. П. Последний раз редактировалось anna_sidorova, 06.04.2021 в 11:03. |
#2
|
|||
|
|||
А попробовать скомпилить на более новой версии Delphi, которая изначально поддерживает юникод, нельзя? Просто в рамках эксперимента...
ЗЫ. Можно бесплатно скачать Community Edition с сайта Абракадабры, это аналог Professional. |
#3
|
|||
|
|||
Цитата:
Похоже, придётся, хотя очень не хочется. Сначала думаю с Delphi 7 перейти на Delphi 2010 (первая из Unicode-версия, не считая 2009 - но 2009 судя по тому, что пишут в Сети - очень глючная). А потом уже, возможно переходить на XE10 или просто остаться на Delphi 2010. Сразу перейти на XE10 не получается - даже не компилируется, на XE8 после долгих мучений удалось скомпилировать еще в 2017 - но увидев количество глюков испугалась и решила остаться на Delphi 7. Хотелось бы, конечно, вообще остаться на Delphi 7 - т. к. полагаю, что даже переход на 2010 чреват большим количеством глюков, недовольств пользователей и бессонных ночей ... |
#4
|
|||
|
|||
А пробовали вариант изменить язык не Юникод приложений через панель управления на русский (Панель управления->Региональные стандарты->Дополнительно->Язык программ не поддерживающий Юникод)?
Если и этот вариант не помог, то можно попробовать сменить кодировку через реестр. Так как в правилах форума явно не указан запрет на ссылки внешних сайтов, то на свой страх и возможность получить предупреждение, дам вам ссылку на статью https://remontka.pro/fix-cyrillic-windows-10/ . Вдруг вам поможет. |
#5
|
|||
|
|||
Цитата:
Вероятно, Вы не поняли вопрос. В описании вопроса как раз и указано - что при изменении галочки указанным способом всё работает. Через реестр тоже работает (если написать REG-файл). В обоих случаях для вступления изменений в силу требуется перезагрузка компьютера. Но задача именно в том - чтобы программа работала корректно без изменения системных настроек. И тем более более без необходимости перезагрузки компьютера. Чтобы пользователь с Windows, в котором проблемная галочка включена - устанавливал программу, запускал и видел нормальный текст вместо крякозябр. |
#6
|
|||
|
|||
Цитата:
Бери последнюю (ну не самую, а ту, которая Comunity Ed), там, вроде, особо глюков не замечено (есть, конечно, но не критично/редко встречается). |