Rambler's Top100
"Knowledge itself is power"
F.Bacon
Поиск | Карта сайта | Помощь | О проекте | ТТХ  
 Круглый стол
  
Правила КС
>> Настройки

Фильтр вопросов
>> Новые вопросы
отслеживать по
>> Новые ответы

Избранное

Страница вопросов
Поиск по КС


Специальные проекты:
>> К л ю к в а
>> Г о л о в о л о м к и

Вопрос №

Задать вопрос
Off-topic вопросы

Помощь

 
 К н и г и
 
Книжная полка
 
 
Библиотека
 
  
  
 


Поиск
 
Поиск по КС
Поиск в статьях
Яndex© + Google©
Поиск книг

 
  
Тематический каталог
Все манускрипты

 
  
Карта VCL
ОШИБКИ
Сообщения системы

 
Форумы
 
Круглый стол
Новые вопросы

 
  
Базарная площадь
Городская площадь

 
   
С Л С

 
Летопись
 
Королевские Хроники
Рыцарский Зал
Глас народа!

 
  
ТТХ
Конкурсы
Королевская клюква

 
Разделы
 
Hello, World!
Лицей

Квинтана

 
  
Сокровищница
Подземелье Магов
Подводные камни
Свитки

 
  
Школа ОБЕРОНА

 
  
Арсенальная башня
Фолианты
Полигон

 
  
Книга Песка
Дальние земли

 
  
АРХИВЫ

 
 

Сейчас на сайте присутствуют:
 
  
 
Во Флориде и в Королевстве сейчас  06:35[Войти] | [Зарегистрироваться]
Ответ на вопрос № 36984

22-10-2005 17:12
Здравствуйте, уважаемые!

Прошу помочь. Дело вот в чём. Если в панели управления, язык и региональные стандарты на закладке региональные параметры выставлен не русский язык, то заголовки всех tgroupbox'ов превращаются в кракозябры! Ещё при выставлении языка программ не поддерживающих юникод отличным от русского также наблюдаются проблемы с отбражением некоторых символов. И опять таки в tgroupbox'ах! Так чего такого особенного в tgroupbox'е что не даёт ему нормально отображать текст? И как это исправить?

[+] Добавить в избранные вопросы

Отслеживать ответы на этот вопрос по RSS

Ответы:


Уважаемые авторы вопросов! Большая просьба сообщить о результатах решения проблемы на этой странице.
Иначе, следящие за обсуждением, возможно имеющие аналогичные проблемы, не получают ясного представления об их решении. А авторы ответов не получают обратной связи. Что можно расценивать, как проявление неуважения к отвечающим от автора вопроса.

30-07-2006 13:28
Вот что еще непонятно: почему вместо перехода "jz +$2d" (742D) вставляется "adc ch,bl" (12EB)?
Потому что я идиот, не только порядок байт перепутал, но и смещение не так посчитал, хотя самое интересное, что оно при этом всё равно работало :)
Прошу прощения, надо конечно $10EB, а не $EB12.

30-07-2006 10:30
Еще раз спасибо за подробное объяснение, потихоньку разбираюсь.
Вот что еще непонятно: почему вместо перехода "jz +$2d" (742D) вставляется "adc ch,bl" (12EB)? Почему именно такая команда?

29-07-2006 07:12
Понять бы, как все это работает (в частности, почему такие структуры
Поставьте BreakPoint в initialization секции System.pas и после остановки нажмите на Ctrl+Alt+C, появится дебагер в котором видны соответствующие операции и их коды. А процедура просто делает как можно больше проверок чтобы случайно не пропатчить не тот код, так как блоки ассмблерных комманд имеют тенденцию повторяться по многу раз. А изменения вносятся следующие: в "DefaultUserCodePage := 3" меняется 3, на нашу константу и первый подходящий Jump ("if GetVersion and $80000000 <> $80000000 then") меняется так чтобы всегда срабатывала ветка "DefaultUserCodePage := 3".
что есть @TObject.Free
Так как System.dcu может находиться в пакете (BPL), а не в EXE-шнике, то надо знать в каком конкретно сегменте кода искать нужный нам кусок кода. Можно было взять адрес любого объекта (функция, метод) находящегося в System.pas, я выбрал @TObject.Free. А PImportStub нужен опять таки для пакетов, так как вызов функции из другого модуля (DLL,BPL) требует создания (на этапе компиляции) специального переходника (одна команда JMP [ProcAddr]) позволяющего загружать модули по произвольным, а не фиксированным адресам.

28-07-2006 19:32
Андрей, большое спасибо!!!

Я просто восхищен. Все отлично сработало (проверял на AVTlab Small CD-Writer 1.33, другие программы там тоже надо патчить - The Bee, например) - больше нет никаких вопросительных знаков. Да, до такого уровня мне еще далеко.

Понять бы, как все это работает (в частности, почему такие структуры и, в первом решении для IDE, что есть @TObject.Free)...

28-07-2006 15:37 | Комментарий к предыдущим ответам
А если не универсально патчить, а только для русского языка? Т.е. прямо прописать в код значение только значение "419" (русская user locale) вместо значения, возвращаемого теми функциями?
Вы правы можно и так, а вместо $419 по идее нолик должен работать (как в старых версиях Delphi).
Получилась вот такая функция:

function FixDefaultUserCodePageBug(Image:Pointer;Size:Integer;CodePage:Integer):Boolean;
type
  TRelMov=packed record
    MovOp:Word;//mov [xxxxxxxx],xxxxxxxx
    VarAddr:DWORD;//DefaultUserCodePage
    Value:DWORD;//3
  end;
  TCode=packed record
    CallOpA:Byte;//$E8
    OffsetA:Integer;//GetThreadLocale
    CallOpB:Byte;//$E8
    OffsetB:Integer;//LCIDToCodePage
    MovOp:Byte;//$A3
    VarAddr:DWORD;//DefaultUserCodePage
  end;
  TCodes=packed record
    JMP:Word;//jz +$2d ($2d74)
    Code:array[0..15] of Byte;//GetVersion check
    RelMov:TRelMov;//DefaultUserCodePage := 3
    JMP2:Word;//Short jump
    Code1:TCode;//NT4
    JMP3:Word;//Short jump
    Code2:TCode;//Win95/98/ME
  end;
var
  Code:^TCodes;
  MemInfo:TMemoryBasicInformation;
  P:Pointer;
begin
  Result:=False;
  Code:=Image;
  while Size>SizeOf(TCodes) do begin
    with Code^ do
      if (JMP=$2D74)and(RelMov.MovOp=$05C7)and(RelMov.Value=3)
        and(Code1.CallOpA=$E8)and(Code1.CallOpB=$E8)and(Code1.MovOp=$A3)
        and(Code2.CallOpA=$E8)and(Code2.CallOpB=$E8)and(Code2.MovOp=$A3)
        and(Code1.OffsetA-Code1.OffsetB=Code2.OffsetA-Code2.OffsetB)
        and(Code1.VarAddr=Code2.VarAddr)and(Code1.VarAddr=RelMov.VarAddr) then begin
        RelMov.Value:=CodePage;
        JMP:=$EB12;
        Result:=True;
        Break;
      end;
    Inc(PByte(Code));
    Dec(Size);
  end;
end;

//И как-то так используем
  with TMemoryStream.Create do try
    LoadFromFile('Project1.exe');
    if FixDefaultUserCodePageBug(Memory,Size,1251) then
      SaveToFile('Patched.exe')
    else
      ShowMessage('Not patched');
  finally
    Free;
  end;

Патчить можно не только EXE-шник, но и rtl70.bpl или System.dcu

28-07-2006 12:12
А если не универсально патчить, а только для русского языка? Т.е. прямо прописать в код значение только значение "419" (русская user locale) вместо значения, возвращаемого теми функциями?

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

28-07-2006 08:55
По идее, там нужно подменить API-функцию, чтобы возвращала значение "system locale", а не "user locale".
Нет, там нужно заменить весь блок кода (TCode) на вызов GetACP + присвоение переменной. Это реализуемо, но довольно сложно, так как надо анализировать PE файл, искать в импорте GetACP и определять адрес переходника. Ещё можно написать DLL-ку, которая определяет что EXE-шник от седьмой версии и подменяет в нём функции MultiByteToWideChar и WideCharToMultiByte на свои (у Рихтера это было описано), тогда и патчить ничего не надо будет, просто запихнёте эту библиотеку в HKEY_LOCAL_MACHINE\Software\Microsoft\Windows_NT\CurrentVersion\Windows\AppImt_DLLs и все программы "исправятся".

28-07-2006 07:15 | Вопрос к автору: запрос дополнительной информации
Никто не пробовал в даном случае патчить уже готовую программу, если доступа к исходникам нет? По идее, там нужно подменить API-функцию, чтобы возвращала значение "system locale", а не "user locale".

20-03-2006 11:18 | Комментарий к предыдущим ответам
Кстати, Вы не знаете, как дела в Delphi8, Delphi2005?
Ошибка о которой тут идёт речь имеется ТОЛЬКО в Delphi7.
Как теперь мне в этой форме "использовать юникод"?
Уже никак.
Чтобы на всех компьютерах отображалось правильно?
Поставить что-то вроде этого http://www.tntware.com/delphicontrols/unicode/

Зачем вам нужно "на всех компьютерах"? Ситуации когда требуется показывать текст не на языке системы крайне редки. Если человек в настройках указал "Китайский", то не думаю, что ему интересно будет читать, что-то на русском, так же как мне совершенно наплевать как у меня отображаются иероглифы, я их всё равно не различаю.

20-03-2006 00:52
>> Ошибка о которой тут идёт речь имеется ТОЛЬКО в Delphi7.

Кстати, Вы не знаете, как дела в Delphi8, Delphi2005?

>> Правильность работа с русским в Delphi зависит от кодовой
>> страницы для не юникод программ, если она поставлена
>> не в "Русский" (это под 2000/XP, что в 9x я не в курсе),
>> то правильного текста вы не получите. ЕДИНСТВЕННЫЙ способ
>> нормально отображать всё и везде это использовать юникод
>> и возможно даже шрифты с собой таскать придётся.

Заранее извиняюсь за дилетанство...
Есть форма Form1, на ней компонент Label1, в свойство Caption
заполняем (в инспекторе объектов): Вася+Петя=Сережа*Sqrt(Pi).
Как теперь мне в этой форме "использовать юникод"?
Чтобы на всех компьютерах отображалось правильно?

19-03-2006 05:19 | Комментарий к предыдущим ответам
Если пользоваться Delphi 4,5 или 6,
с отображением русского все нормально?

Ошибка о которой тут идёт речь имеется ТОЛЬКО в Delphi7.
и на любом компьютере в любой стране будет отображаться 'Вася+Петя'?
Правильность работа с русским в Delphi зависит от кодовой страницы для не юникод программ, если она поставлена не в "Русский" (это под 2000/XP, что в 9x я не в курсе), то правильного текста вы не получите. ЕДИНСТВЕННЫЙ способ нормально отображать всё и везде это использовать юникод и возможно даже шрифты с собой таскать придётся.

18-03-2006 18:28 | Комментарий к предыдущим ответам
Вопрос to DRON

Если пользоваться Delphi 4,5 или 6,
с отображением русского все нормально?
Можно в DesignTime задавать Caption='Вася+Петя',
проверять, что при этом CHARSET=RUSSIAN_CHARSET,
и на любом компьютере в любой стране будет отображаться 'Вася+Петя'?

03-11-2005 07:13 | Комментарий к предыдущим ответам
to DRON

Там и звук есть? Извини, не знал.

03-11-2005 06:43 | Комментарий к предыдущим ответам
Дорогой kkk ТЫ БЫ ХОТЬ ПРЕДУПРЕЖДАЛ ДАВАЯ ССЫЛКУ НА СТРАНИЦУ СО ЗВУКОМ (не будем уточнять каким именно).

03-11-2005 06:22 | Комментарий к предыдущим ответам
>>>Delphi (только седьмая) и Windows выбирают разные кодировки

Это потому, что Delphi 7 лучше. В ней есть мошный инструмент многоязыковой поддержки Translation Tools. С его помощью можно легко (действительно легко) создать ресурсные DLL Project1.RUS, Project1.KAZ и т.д. Нужную DLL программа выберет сама (а как же иначе?) - заглянув в Regional options/Standart and formats!!!!!! Если нужной DLL нет, Delphi все равно запомнит, что там было написано.

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

DRON прибил ручку этих граблей к полу. Пользоваться ими стало невозможно, но ходить  спокойнее.

Пакет CodePageFix в свой проект вставлять не обязательно. Он нужен в IDE потому что Delphi и компиллирует в зависимости от установок Standart and formats.

Очень хотелось бы, что бы авторы инструмента хотя бы раз побывали на http://lleo.aha.ru/na/

03-11-2005 05:19 | Комментарий к предыдущим ответам
Проблема не в Charset, а в кодировке. Один и тот же Charset может иметь множество кодировок. В данном случае проблема в том, что Delphi (только седьмая) и Windows выбирают разные кодировки для прозрачной конвертации Unicode<>Ansi.

02-11-2005 22:25
А что свойство Charset=RUSSIAN_CHARSET не помогает?

02-11-2005 16:46 | Комментарий к предыдущим ответам
to DRON

Красиво. Окончательный ответ на вопрос, который обсуждался здесь много раз. Текст заслуживает помещения в "Сокровищницу" :)

Жаль, что я не прочитал это пару лет назад, но все равно, огромное СПАСИБО!

23-10-2005 06:55 | Сообщение от автора вопроса
СПАСИБО !!! Помогло!

22-10-2005 17:53
Скорее всего дело в этом
http://www.delphikingdom.com/asp/answer.asp?IDAnswer=35406
В том вопросе код с ошибкой, вот нормальный (надеюсь):
CPFix.pas надо подключить к вашему проекту.

unit CPFix;
interface

{$IFNDEF VER150}
{$IF Trunc(RTLVersion) <> 15}
{$MESSAGE ERROR 'This unit for Delphi 7 only.'}
{$IFEND}
{$ENDIF}

function FixDefaultUserCodePage:Boolean;

implementation
uses
  Windows;

function FixDefaultUserCodePage:Boolean;
type
  TCode=packed record
    CallOpA:Byte;//$E8
    OffsetA:Integer;//GetThreadLocale
    CallOpB:Byte;//$E8
    OffsetB:Integer;//LCIDToCodePage
    MovOp:Byte;//$A3
    VarAddr:PInteger;//DefaultUserCodePage
  end;
  TCodes=packed record
    Code1:TCode;//NT4
    JMP:Word;//Short jump
    Code2:TCode;//Win95/98/ME
  end;
  PImportStub=^TImportStub;
  TImportStub=packed record
    JMP:Word;//$25ff
    Addr:PPointer;//Real addr
  end;
var
  Code:^TCodes;
  Count:Integer;
  MemInfo:TMemoryBasicInformation;
  P:Pointer;
begin
  Result:=False;
  P:=@TObject.Free;
  if PImportStub(P).JMP=$25FF then P:=PImportStub(P).Addr^;
  if (VirtualQuery(P,MemInfo,SizeOf(MemInfo))<SizeOf(MemInfo))
    or(MemInfo.State<>MEM_COMMIT) then Exit;
  Code:=MemInfo.BaseAddress;
  Count:=MemInfo.RegionSize;
  while Count>SizeOf(TCodes) do begin
    with Code^ do
      if (Code1.CallOpA=$E8)and(Code1.CallOpB=$E8)and(Code1.MovOp=$A3)
        and(Code2.CallOpA=$E8)and(Code2.CallOpB=$E8)and(Code2.MovOp=$A3)
        and(Code1.OffsetA-Code1.OffsetB=Code2.OffsetA-Code2.OffsetB)
        and(Code1.VarAddr=Code2.VarAddr) then begin
        Code1.VarAddr^:=GetACP;
        Result:=True;
        Break;
      end;
    Inc(PByte(Code));
    Dec(Count);
  end;
end;

initialization
  FixDefaultUserCodePage;
end.


А CodePageFix.dpk установить в IDE.

package CodePageFix;

{$R *.res}
{$ALIGN 8}
{$ASSERTIONS OFF}
{$BOOLEVAL OFF}
{$DEBUGINFO OFF}
{$EXTENDEDSYNTAX ON}
{$IMPORTEDDATA ON}
{$IOCHECKS OFF}
{$LOCALSYMBOLS OFF}
{$LONGSTRINGS ON}
{$OPENSTRINGS ON}
{$OPTIMIZATION ON}
{$OVERFLOWCHECKS OFF}
{$RANGECHECKS OFF}
{$REFERENCEINFO OFF}
{$SAFEDIVIDE OFF}
{$STACKFRAMES OFF}
{$TYPEDADDRESS OFF}
{$VARSTRINGCHECKS ON}
{$WRITEABLECONST ON}
{$MINENUMSIZE 1}
{$IMAGEBASE $400000}
{$DESCRIPTION 'UserCodePage IDE fixer'}
{$DESIGNONLY}
{$IMPLICITBUILD OFF}

requires
  rtl;

contains
  CPFix in 'CPFix.pas';

end.


Добавьте свое cообщение

Вашe имя:  [Войти]
Ваш адрес (e-mail):На Королевстве все адреса защищаются от спам-роботов
контрольный вопрос:
Однажды, в студеную зимнюю пору я из лесу вышел, был сильный ЧТО?
в качестве ответа на вопрос или загадку следует давать только одно слово в именительном падеже и именно в такой форме, как оно используется в оригинале.
Надоело отвечать на странные вопросы? Зарегистрируйтесь на сайте.
Тип сообщения:
Текст:
Жирный шрифт  Наклонный шрифт  Подчеркнутый шрифт  Выравнивание по центру  Список  Заголовок  Разделительная линия  Код  Маленький шрифт  Крупный шрифт  Цитирование блока текста  Строчное цитирование
  • вопрос Круглого стола № XXX

  • вопрос № YYY в тесте № XXX Рыцарской Квинтаны

  • сообщение № YYY в теме № XXX Базарной площади
  • обсуждение темы № YYY Базарной площади
  •  
     Правила оформления сообщений на Королевстве

    Страница избранных вопросов Круглого стола.
      
    Время на сайте: GMT минус 5 часов

    Если вы заметили орфографическую ошибку на этой странице, просто выделите ошибку мышью и нажмите Ctrl+Enter.
    Функция может не работать в некоторых версиях броузеров.

    Web hosting for this web site provided by DotNetPark (ASP.NET, SharePoint, MS SQL hosting)  
    Software for IIS, Hyper-V, MS SQL. Tools for Windows server administrators. Server migration utilities  

     
    © При использовании любых материалов «Королевства Delphi» необходимо указывать источник информации. Перепечатка авторских статей возможна только при согласии всех авторов и администрации сайта.
    Все используемые на сайте торговые марки являются собственностью их производителей.

    Яндекс цитирования