Sources
Delphi Russian Knowledge Base
DRKB - база знаний по Дельфи в рунете, составленная Виталием Невзоровым

Работа с казахскими шрифтами

01.01.2007
ASTER_X aster_x@inbox.ru

Здравствуйте, Уважаемые Господа Програмисты.

Моя небольшая статья будет, скорее всего, интересна програмистам из региона - КАЗАХСТАН. Так как програмисты, проживающиее и работающие в этом регионе, чаще всего встречаются с проблемой вывода нестандартных КАЗАХСКИХ ШРИФТОВ.

Вместо введения...

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

Программисты Казахстана знают, какая это довольно-таки серьезная проблема - "Нестандартные казахские символы". Так как я сейчас активно занимаюсь "писаниной" - пишу прогу, которая должна "понимать" КАЗАХСКИЙ ЯЗЫК от и до (Если так можно сказать).

Писал, писал, и вдруг случилось... Оказывается, ни один элемент управления не хочит ни "писать", ни "читать" по КАЗАХСКИ.

Решил перелопатить инфу, которая была, и локальную и "ИНЕТСКУЮ". Как выяснилось, инфы типа "КАК СДЕЛАТЬ СУПЕР TButton" - огромное количество. А по шрифтам... "увольте" :(

Приступим.

Первое, что надо сделать, чтобы работать с казахскими шрифтами это... Разместить их в системной таблице шрифтов.

Есть два способа: закидываете файл со шрифтом в каталог \Windows\Fonts\/ Или же, размещаете файл рядом с программой и вызываете AddFontResource('you_font.xxx');

Я пошел по первому пути (Так проще, хотя второй я тоже практиковал).

Ну, предположим, что мы разобрались с методом регистрации шрифта в системе.

Я использовал шрифт "Times/Kazakh" и вам советую. (Во всяком случае все примеры основанны именно на этом шрифте). Но при определенном навыке, или же когда освоитесь с этим шрифтом, вы сможете перейти на любой другой шрифт.

ВАЖНО

Второе, в чем часто путаются программеры, это - чтобы работать со шрифтами по принципу "ОТ ОКНА К ОКНУ". Надо чтобы на всех окнах, в которых подразумевается использование казахского шрифта, было установленно одинаковое имя шрифта (Times/Kazakh). Тогда вы спокойно сможете пользоваться буфером обмена и оператором присваивания (EditX.Text:=EditY.text;).

Это же относится и ко всем TCanvas, на которых подразумевается вывод КАЗАХСКОГО ШРИФТА.

Основная проблема заключается в том, что даже после установки казахской раскладки и казахского шрифта окна (даже окна редактирования TEdit.Tmemo) все равно не хотят выводить текст, даже с клавиатуры.

И тут приходится "хитрить" - дело в том, что нестандартные КАЗАХСКИЕ СИМВОЛЫ (CHAR) лежат в диапазоне 176-191 (Большие и маленькие). Поэтому я сделал так - во время ввода, если выбранна КАЗАХСКАЯ раскладка клавиатуры, перехватывать VIRT_KEY в событии OnKeyDown. И транслировать их в Казахские ЧАР'ы.

Уже готовый текст вы можете сохранить в файл и потом открыть. Без всяких излишеств. Либо скопировать в буфер обмена. Но учтите, при вставке в другое окно или приложение (NOTEPAD), обязательно убедитесь в том, что там установлен такой же шрифт, как и у вас в программе.

//Дополнительные Переменные и функции

Const KZ_KBRD = $043f043f;//Дескриптор Казахской раскладки 
                          //В системе

//Функция Определяющая какой регистр использовать
//Данные обрабатываются в соответствии
//С состояниями клавиш от  клавиатуры
Function IsLow:Boolean;
var SHF,CPS_L : Boolean;
begin
  REsult:=false;
  SHF:= HiWord(GetAsyncKeyState(VK_SHIFT))>0;       //Зажат ли ШИФТ
  CPS_L:=  0 <> (GetKeyState(VK_CAPITAL) and $01);  //Состояние CAPS_LOCK
  if (SHF and CPS_L) then Result:=true;             //пропись если ЗАЖАТЫ ОБЕ КЛАВИШИ
  if (not SHF and  not CPS_L) then Result :=true;   //Или наоборт
end;

//Функция конвертирующая КЛАВИШУ в СИМВОЛ
Function KeyToKZChar(Key:Integer;lowKey:boolean):Char;
Begin
  result:=#0;           {Мальнькие }          {Большие}
  case key of           {Символы}             {Символы}
    50:  if LowKey then result:=chr(184) else Result:= chr(176);
    51:  if lowkey then result:=chr(105) else Result:= chr(73);
    52:  if lowkey then result:=chr(187) else Result:= Chr(179);
    53:  if lowkey then Result:=chr(185) else Result:= Chr(177);
    54:  if lowkey then result:=chr(190) else Result:= Chr(182);
    55:  if lowkey then result:=chr(189) else Result:= Chr(181);
    48:  if lowkey then result:=chr(186) else Result:= Chr(178);
    189:if lowkey then result:=chr(188) else Result:= Chr(180);
    187:if lowkey then result:=chr(191) else Result:= Chr(183);
  end;
end;


{XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX}
{XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX}

var LastKey :integer;       //Для хранения Последней клавиши
    LowKey :Boolean = true; //Верхний или нижний регистр.

//Проверяем как прога пишет на Казахском языке

//Вылавливаем клавишу для дальнейшей обработки
procedure TForm1.Edit3KeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
  LastKey := Key;
  LowKey:=IsLow; //Сразу (на месте) определяем и сохраняем  регистр.
end;

procedure TForm1.Edit3KeyPress(Sender: TObject; var Key: Char);
Var tmpKey :char;
begin
  if GetKeyboardLayout(0)=KZ_KBRD then //Если казахская раскладка то..
  Begin
    tmpKey:=KeyToKZChar(LastKey,LowKey);// Получаем нужный символ
    if not(tmpKey = #0) then //Если  не стандартный символ то...
    Begin  
      Key:=tmpKey;   // Указываем окну наш символ
      exit;   
    end;
  end;
end;

//Дальше тоже самое только для компонента TMEMO

procedure TForm1.Memo1KeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
   LastKey:=key;
   LowKey:=IsLow;
end;

procedure TForm1.Memo1KeyPress(Sender: TObject; var Key: Char);
var tmpKey : char;
begin
  if GetKeyboardLayout(0)=KZ_KBRD then
  Begin
    tmpKey:=KeyToKZChar(LastKey,LowKey);
    if not(tmpKey = #0) then
    Begin
      Key:=tmpKey;
      exit;
    end;
  end;
end;

//Можем сохранить наше творение в файл.
procedure TForm1.Button4Click(Sender: TObject);
begin
  Memo1.Lines.SaveToFile('A.txt');
end;

//Или же наоборот загрузить из файла.
procedure TForm1.Button5Click(Sender: TObject);
begin
  Memo1.Lines.LoadFromFile('A.txt');
end;

//Проба вывода на канвас разными методами.
procedure TForm1.Button3Click(Sender: TObject);
begin
  pb.Canvas.Font.Name:='Times/Kazakh';
  pb.Canvas.Font.Color:=clRed;
  pb.Canvas.Font.Size:=14;
  pb.Canvas.TextOut(10,10,Edit1.Text);
  TextOut(PB.Canvas.Handle,30,30,Pchar(Edit1.Text),10);
end;

//Текст На компоненты
Edit3.Text:=Memo1.Text; 
Button2.Caption:=Edit3.Text;

На этом моя задача исчерпала сама себя.

Конечно, в приведенном примере еще много белых пятен. К примеру возникают сложности при вставке текста, скопированного в другом приложении (Блокнот). Но это уже другие проблемы, другие вопросы, другие задачи. Даже на основе этого "скелета" можно приступать к "написанию" программ на "Казахском языке", либо же разрабатывать на его основе свои "скелеты".

Буду очень признателен, если кто нибудь оттранслирует статью под С++ (Со ссылкой на автора)

Если будут какие-нибудь вопросы то...
Я всегда буду рад на них ответить.

Из-за того, что фичь есть, но юзать его простым смертным не дано....

С ГЛУБОКИМ УВАЖЕНИЕМ ASTER_X

Previous page:
Список шрифтов, совместимых одновременно с экраном и с принтером
Top:
DRKB
Next page:
Вывод шрифтов в списке в виде самих шрифтов