Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Delphi Новый топик    Ответить
Топик располагается на нескольких страницах: [1] 2 3 4 5 6 7   вперед  Ctrl      все
 Крякозябры вместо русских символов на Windows 10 - при включенной опции Юникод  [new]
Анна Петровна
Member

Откуда:
Сообщений: 68
Крякозябры вместо русских символов на Windows 10 - при включенной опции Бета-версия: Использовать Юникод (UTC-8) для поддержки языка во всем мире

Есть программный код на 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 - туда надо копать или в чем можем быть дело?



С уважением, Сидорова А. П.
6 апр 21, 11:14    [22304955]     Ответить | Цитировать Сообщить модератору
 Re: Крякозябры вместо русских символов на Windows 10 - при включенной опции Юникод  [new]
alekcvp
Member

Откуда:
Сообщений: 2792
Анна Петровна,

https://github.com/MahdiSafsafi/DDetours
6 апр 21, 11:22    [22304957]     Ответить | Цитировать Сообщить модератору
 Re: Крякозябры вместо русских символов на Windows 10 - при включенной опции Юникод  [new]
delphinotes
Member

Откуда: Санкт-Петербург
Сообщений: 379
Анна Петровна,

Ух, столько упорства, а обновиться на юникодную версию делфи - не предлагать? Там не так уж и сложно, на самом деле, тем более, если в основном компоненты стандартные.
Более того, в MS конечно молодцы, стараются обратную совместимость поддерживать по максимуму, но кто знает, что там будет в будущем.
P.S.: Указанная галка у меня _по_умолчанию_ выключена, сама не включалась.
P.S.2: может лучше в MS куда-нить и написать?
6 апр 21, 11:26    [22304958]     Ответить | Цитировать Сообщить модератору
 Re: Крякозябры вместо русских символов на Windows 10 - при включенной опции Юникод  [new]
avp_
Member

Откуда:
Сообщений: 100
А чем шрифт Arial лучше в плане кодировок чем MS Sans Serif ?
6 апр 21, 12:05    [22304973]     Ответить | Цитировать Сообщить модератору
 Re: Крякозябры вместо русских символов на Windows 10 - при включенной опции Юникод  [new]
Мимопроходящий
Member

Откуда: бурятский тундрюк, эсквайр
Сообщений: 32207

06.04.2021 12:05, avp_ пишет:
> А чем шрифт Arial лучше в плане кодировок чем MS Sans Serif ?

MS Sans Serif - изначально растровый.
в зависимости от версии Win и настроек FontSubstitutes в реестре,
он может мапироваться на TTF шрифт Microsoft Sans Serif,
но обычно нет.

Posted via ActualForum NNTP Server 1.5

6 апр 21, 12:09    [22304976]     Ответить | Цитировать Сообщить модератору
 Re: Крякозябры вместо русских символов на Windows 10 - при включенной опции Юникод  [new]
Анна Петровна
Member

Откуда:
Сообщений: 68
avp_,

да, Arial - однозначно лучше, с MS Sans Serif крякозябры будут во многих случаях, когда их не будет с Arial.

Программно отключать данную опцию в системе совсем не проблема. Пишем REG-файл, пишем пользователю, что нужно запустить этот файл, перезагрузить компьютер - но это всё лишние действия и неудобства - в этом и проблема. И вообще это всё костыли, хотелось бы нормального решения проблемы.

Переход с Delphi 7 на Delphi 2009 - как я понимаю, может решить вопрос (это самая ранняя версия Delphi с поддержкой Юникода и по идее, переписывать придётся меньше, чем если сразу переходить на Delphi XE 10). Но вопрос-то как раз именно в том - как решить проблему, оставаясь в рамках Delphi 7 (до этого подобные проблемы удавалось решать в рамках Delphi 7). Потому что переход на новую версию Delphi (даже 2009) - это всё равно необходимость переписывания кода, глюки, недовольства пользователей, бессонные ночи и нервозность во время отпусков.
6 апр 21, 12:27    [22304994]     Ответить | Цитировать Сообщить модератору
 Re: Крякозябры вместо русских символов на Windows 10 - при включенной опции Юникод  [new]
Fr0sT-Brutal
Member

Откуда:
Сообщений: 682
Наверно, можно перехватывать SetWindowText и в случае acp=utf8 конвертировать строки на лету.
А режим совместимости не помогает?
6 апр 21, 12:29    [22304998]     Ответить | Цитировать Сообщить модератору
 Re: Крякозябры вместо русских символов на Windows 10 - при включенной опции Юникод  [new]
_Vasilisk_
Member

Откуда: Украина, Харьков
Сообщений: 12789
Анна Петровна
Как только пытаюсь перезаписать значение данной ячейки в 1251 - тут же появляется ошибка

Exception EAccessViolation in module KernelBase.dll at 000F69ED. Access violation at address 76D269ED in module 'KernelBase.dll'. Read of address 00000002.
Очень странное поведение. При записи возникает ошибка чтения. Да еще и по адресу 0000002

Анна Петровна
Переход с Delphi 7 на Delphi 2009 - как я понимаю, может решить вопрос (это самая ранняя версия Delphi с поддержкой Юникода и по идее, переписывать придётся меньше, чем если сразу переходить на Delphi XE 10)
Это ошибочное мнение.
1 D2009 была очень сырая и сама по себе содержала кучу ошибок.
2. Переход с 2009 на следующие версии практически незаметен (за исключением багов, которые появляются в конкретной версии Delphi)

Поэтому если надумаете переходить на юникодную версию - переходите сразу на последнюю
6 апр 21, 12:43    [22305005]     Ответить | Цитировать Сообщить модератору
 Re: Крякозябры вместо русских символов на Windows 10 - при включенной опции Юникод  [new]
_Vasilisk_
Member

Откуда: Украина, Харьков
Сообщений: 12789
Тынц
You can see it in ProcMon. It seems to set the REG_SZ values ACP, MACCP, and OEMCP in HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Nls\CodePage to 65001.
6 апр 21, 12:49    [22305007]     Ответить | Цитировать Сообщить модератору
 Re: Крякозябры вместо русских символов на Windows 10 - при включенной опции Юникод  [new]
Анна Петровна
Member

Откуда:
Сообщений: 68
_Vasilisk_,

Я так понимаю, проблема не при самой перезаписи возникает, а уже после. Например, при выводе ShowMessage - когда идут обращения к изменённой функции. В Windows 7 таким образом всё работает нормально, но в Windows 10 глючит.

С переходом на Delphi XE8 возникло множество проблем (были попытки еще в 2017 году) - собственно, поэтому и пришлось от этого отказаться. В конце концов, удалось скомпилировать на Delphi XE8 - программа запустилась - но с таким количеством глюков, что я испугалась и решила остаться на D7. На Delphi XE10 - даже скомпилировать не удалось. Поэтому и думаю - попытаться с Delphi 2009. Если же она очень глючная - возможно, стоит попробовать 2010 или XE/XE2.
6 апр 21, 13:14    [22305023]     Ответить | Цитировать Сообщить модератору
 Re: Крякозябры вместо русских символов на Windows 10 - при включенной опции Юникод  [new]
avp_
Member

Откуда:
Сообщений: 100
У меня тоже большой проект на древнем C++ Builder, перевод на свежее уже практически нереален.
6 апр 21, 13:38    [22305031]     Ответить | Цитировать Сообщить модератору
 Re: Крякозябры вместо русских символов на Windows 10 - при включенной опции Юникод  [new]
Fr0sT-Brutal
Member

Откуда:
Сообщений: 682
Интересно, а если в этом режиме внутри программы применять конвертацию в utf8 - сработает? Edit1.Text := AnsiToUtf8('блабла')
6 апр 21, 14:52    [22305075]     Ответить | Цитировать Сообщить модератору
 Re: Крякозябры вместо русских символов на Windows 10 - при включенной опции Юникод  [new]
Анна Петровна
Member

Откуда:
Сообщений: 68
Fr0sT-Brutal,

не знаю - сработает или нет - но думаю, определённо глюков будет еще больше чем при переходе на Delphi 2009/2010. Так как программа анализирует значения, которые вводятся в Edit и работает с ними как с обычными 1-байтовыми строками. хотелось бы чтобы значение в Text не менялось, менялся чтобы только алгоритм отрисовки - например, перехватывать метод отрисовки, конвертировать строку в UTF-8 и выводить как UTF-8. Но тут проблема тогда ещё - что делать в режиме редактирования строки - какие символы и как отрисовывать, как отрисовывать курсор и т. д.
6 апр 21, 16:50    [22305123]     Ответить | Цитировать Сообщить модератору
 Re: Крякозябры вместо русских символов на Windows 10 - при включенной опции Юникод  [new]
Dimitry Sibiryakov
Member

Откуда:
Сообщений: 52921

Замените их уже на TNT Controls и не парьте моск.

Posted via ActualForum NNTP Server 1.5

6 апр 21, 18:19    [22305156]     Ответить | Цитировать Сообщить модератору
 Re: Крякозябры вместо русских символов на Windows 10 - при включенной опции Юникод  [new]
delphinotes
Member

Откуда: Санкт-Петербург
Сообщений: 379
Конвертация большого проекта D2007 в юникод и переход на новую версию Delphi
6 апр 21, 19:25    [22305179]     Ответить | Цитировать Сообщить модератору
 Re: Крякозябры вместо русских символов на Windows 10 - при включенной опции Юникод  [new]
white_nigger
Member

Откуда: Тула
Сообщений: 2520
Если какая-то программа попытается поменять мне системные настройки, то моментально и она и её аффтор пойдут в эротическое пешее путешествие. Была помнится тулзня от мелкомягких AppLocale. С её помощью можно запускать приложение в нужной для неё локали
6 апр 21, 22:15    [22305202]     Ответить | Цитировать Сообщить модератору
 Re: Крякозябры вместо русских символов на Windows 10 - при включенной опции Юникод  [new]
Анна Петровна
Member

Откуда:
Сообщений: 68
white_nigger,

А я уже подумываю над этим - чтобы так сделать. Но боюсь - если при получении GetACP=65001 требовать запуск от имени администратора, патчить реестр ветку HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Nls\CodePage и перезапускать компьютер после этого - программа может попасть в базы антивирусов.

Как минимум, надо спрашивать пользователя перед выполнением данных действий. Например, выдавать сообщение, что обнаружены неверные языковые настройки - изменить да/нет, перед перезапуском компьютера тоже спросить. Но проблема в том -что если пользователю предоставлять такой выбор - пользователь ведь может отказаться и выбрать "Нет", увидеть страшные крякозябры и вместо перезапуска компьютера просто отказаться от программы.

Поэтому как ни крути - хоть выполняй данные действия (патчить реестр и перезапускать компьютер), не спрашивая пользователя - хоть спрашивай - любой из этих вариантов так или иначе ведёт к потере части пользователей ...

Поэтому да - были бы интересны решения без изменения системных настроек. Или с изменением данных настроек только для запускаемой программы. Например, запускать программу специальным bat-файлом, в котором перед запуском самой программы что-то прописано для задания правильных языковых настроек конкретно для запускаемой программы ...
6 апр 21, 23:18    [22305220]     Ответить | Цитировать Сообщить модератору
 Re: Крякозябры вместо русских символов на Windows 10 - при включенной опции Юникод  [new]
white_nigger
Member

Откуда: Тула
Сообщений: 2520
Анна Петровна
Поэтому да - были бы интересны решения без изменения системных настроек. Или с изменением данных настроек только для запускаемой программы. Например, запускать программу специальным bat-файлом, в котором перед запуском самой программы что-то прописано для задания правильных языковых настроек конкретно для запускаемой программы ...
Так что с AppLocale?
6 апр 21, 23:40    [22305222]     Ответить | Цитировать Сообщить модератору
 Re: Крякозябры вместо русских символов на Windows 10 - при включенной опции Юникод  [new]
Анна Петровна
Member

Откуда:
Сообщений: 68
white_nigger,

Увы, AppLocale - не вариант под Windows 10.

Под его аналогом NTLEA программа запускается, все русские надписи отображаются как нужно. Но ввод русских букв в Edit и в другие элементы невозможен.

Locale.Emulator.2.4.1.0 - программа запускается, русские буквы точно также как в NTLEA отображаются корректно. Но при вводе русских букв в Edit или в Memo - вводятся крякозябры.

SBAppLocale - вообще толком не работает.
7 апр 21, 00:11    [22305228]     Ответить | Цитировать Сообщить модератору
 Re: Крякозябры вместо русских символов на Windows 10 - при включенной опции Юникод  [new]
Fr0sT-Brutal
Member

Откуда:
Сообщений: 682
Анна Петровна
Fr0sT-Brutal,

не знаю - сработает или нет - но думаю, определённо глюков будет еще больше чем при переходе на Delphi 2009/2010. Так как программа анализирует значения, которые вводятся в Edit и работает с ними как с обычными 1-байтовыми строками. хотелось бы чтобы значение в Text не менялось, менялся чтобы только алгоритм отрисовки - например, перехватывать метод отрисовки, конвертировать строку в UTF-8 и выводить как UTF-8. Но тут проблема тогда ещё - что делать в режиме редактирования строки - какие символы и как отрисовывать, как отрисовывать курсор и т. д.

Почему бы не попробовать? По идее, RTL фиолетово, что там за строки, ansi или utf8 - главное, чтобы не utf16 (иначе будут проблемы с #0). А контролы крутятся внутри winapi, у них там utf16. В/из utf8 перегоняется при вызовах S/GetWindowTextA, как я понимаю.
7 апр 21, 10:36    [22305294]     Ответить | Цитировать Сообщить модератору
 Re: Крякозябры вместо русских символов на Windows 10 - при включенной опции Юникод  [new]
avp_
Member

Откуда:
Сообщений: 100
Не понятно почему просто не сделали возможность каждому процессу иметь свою собственную ANSI кодировку. Добавили бы функцию SetACP и всё.
7 апр 21, 12:34    [22305357]     Ответить | Цитировать Сообщить модератору
 Re: Крякозябры вместо русских символов на Windows 10 - при включенной опции Юникод  [new]
Fr0sT-Brutal
Member

Откуда:
Сообщений: 682
avp_
Не понятно почему просто не сделали возможность каждому процессу иметь свою собственную ANSI кодировку. Добавили бы функцию SetACP и всё.

Видимо, сложнее, да и не нужно особо никому. ACP должны умереть.
7 апр 21, 12:41    [22305362]     Ответить | Цитировать Сообщить модератору
 Re: Крякозябры вместо русских символов на Windows 10 - при включенной опции Юникод  [new]
avp_
Member

Откуда:
Сообщений: 100
Fr0sT-Brutal
ACP должны умереть.

К чему такой фашизм? Горы софта написано который работает и делает своё дело.
7 апр 21, 13:50    [22305401]     Ответить | Цитировать Сообщить модератору
 Re: Крякозябры вместо русских символов на Windows 10 - при включенной опции Юникод  [new]
Анна Петровна
Member

Откуда:
Сообщений: 68
С переходом на Delphi 2010 возникают проблемы. В программе много хаков, быдлокода и говнокода, который на D2010 нормально не переносится.

Как пример, в каждом модуле в секции USES используется конструкция

USES {$I AllVcl.pas};

В AllVcl.pas прописано

DBTables, ComCtrls, DBCtrls, ComObj, IBTable, Mask, OleCtrls, SHDocVw,
Windows, tlhelp32, Buttons, ImgList, ActnList, Classes, Graphics, Controls, Forms,
Dialogs, IBStoredProc, StdCtrls, DB, IBDatabase,
IBCustomDataSet, IBQuery, Grids, DBGrids, Menus, ExtCtrls, TeeProcs, TeEngine, Chart,
shellapi, Registry, ShlObj, ADODB, IBSQL, ActiveX,

При компиляции проекта Delphi среда зачнем-то добавляет свой код, получается в итоге лажа

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs;
USES {$I AllVcl.pas};

и программа не компилируется. Зачем Delphi 2010 добавляет свою секцию USES перед тем что уже прописано - непонятно - ведь там в AllVcl.pas и так уже прописаны все необходимые модули. Delphi 7 такую ерунду не делал. Как отучить Delphi 2010 модифицировать файл с кодом при сохранении (Save) и перед запуском (F9)?

Что же теперь - вместо

USES {$I AllVcl.pas};

надо писать

DBTables, ComCtrls, DBCtrls, ComObj, IBTable, Mask, OleCtrls, SHDocVw,
Windows, tlhelp32, Buttons, ImgList, ActnList, Classes, Graphics, Controls, Forms,
Dialogs, IBStoredProc, StdCtrls, DB, IBDatabase,
IBCustomDataSet, IBQuery, Grids, DBGrids, Menus, ExtCtrls, TeeProcs, TeEngine, Chart,
shellapi, Registry, ShlObj, ADODB, IBSQL, ActiveX,

в каждом модуле и переписывать все старые модули?
7 апр 21, 13:56    [22305407]     Ответить | Цитировать Сообщить модератору
 Re: Крякозябры вместо русских символов на Windows 10 - при включенной опции Юникод  [new]
Анна Петровна
Member

Откуда:
Сообщений: 68
Ну а по поводу хаков - в проекте в папке с программой лежат модифицированные

DBGrids.pas Forms.pas IB.pas и другие модули VCL

А в Delphi 2010 - проблема такая, что модули VCL идут вообще без исходного кода. Так что непонятно как их модифицировать чтобы сохранить все хаки,сделанные в Delphi 7.
7 апр 21, 13:58    [22305408]     Ответить | Цитировать Сообщить модератору
Топик располагается на нескольких страницах: [1] 2 3 4 5 6 7   вперед  Ctrl      все
Все форумы / Delphi Ответить