Работа с КАЗАХСКИМИ ШРИФТАМИ

=== Работа с КАЗАХСКИМИ ШРИФТАМИ ===
Работа с КАЗАХСКИМИ ШРИФТАМИ. Здравствуйте Уважаемые Господа Программисты. Моя небольшая статья будет, скорее всего, интересна программистам из региона - КАЗАХСТАН. Так как программисты проживающие и работающие в этом регионе чаще всего встречаются с проблемой вывода нестандартных КАЗАХСКИХ ШРИФТОВ.
==== Вместо введения... ====
Как всегда, передо мною, выросла проблема и, как всегда, я решил приложить максимум усилий чтобы разобраться самому. (Вы меня простите но я не любитель напрягать форумы своими проблемами). Программисты Казахстана знают, какая это, довольно таки серьезная проблема, "Нестандартные казахские символы". Так как я сейчас активно занимаюсь "писаниной" - пишу прогу, которая должна "понимать" КАЗАХСКИЙ ЯЗЫК от и до (Если так можно сказать). Писал, писал, и вдруг случилось... Оказывается, не один элемент управления не хочет ни "писать", ни "читать" по-КАЗАХСКИ. Решил перелопатить инфу, которая была и локальную и "ИНЕТСКУЮ". Как выяснилось, инфы типа "КАК СДЕЛАТЬ СУПЕР _TButton_" огромное количество. А по шрифтам... "увольте".
==== Приступим. ====
Первое что надо сделать чтобы работать с казахскими шрифтами это... Разместить их в системной таблице шрифтов. Есть два способа - закидываете файл со шрифтом в каталог \Windows\Fonts\ Или же, ложите файл рядом с программой и вызываете AddFontResource('you_font.xxx');
Я пошел по первому пути (Так проще, хотя второй я тоже практиковал). Ну предположим, что мы разобрались с методом регистрации шрифта в системе. Я использовал шрифт "Times/Kazakh" и вам советую. (Во всяком случае все примеры основаны именно на этом шрифте). Но при определенном навыке, или же когда освоитесь с этим шрифтом, Вы сможете перейти на любой другой шрифт.
==== ВАЖНО ====
Второе, в чем часто путаются программеры, это - чтобы работать со шрифтами по принципу "ОТ ОКНА К ОКНУ" надо чтобы на всех окнах, в которых подразумевается использование казахского шрифта, было установлено одинаковое имя шрифта (Times/Kazakh). Тогда вы спокойно сможете пользоваться буфером обмена и оператором присваивания (EditX.Text := EditY.text;). Это же относится и ко всем TCanvas на которых подразумевается вывод КАЗ_ШРИФТА. Основная проблема заключается в том, что даже после установки казахской раскладки и казахского шрифта, окна (даже окна редактирования TEdit. Tmemo) все равно не хотят выводить текст, даже с клавиатуры. И тут приходиться "хитрить" - дело в том, что нестандартные КАЗАХСКИЕ СИМВОЛЫ (CHAR) лежат в диапазоне 176-191 (Большие и маленькие). Поэтому я сделал так - во время ввода, если выбрана КАЗАХСКАЯ раскладка клавиатуры, перехватывать VIRT_KEY в событии OnKeyDown. И транслировать их в Казахские CHAR'ы. Уже готовый текст вы можете сохранить в файл и потом открыть. Без всяких излишеств. Либо скопировать в буфер обмена. Но учтите, при вставке в другое окно или приложение (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@inbox.ru
Из за того что фич есть но юзать его простым смертным не дано.... С ГЛУБОКИМ УВАЖЕНИЕМ ASTER_X 
Author: ASTER_X
Source: Взято из http://forum.sources.ru
ID: 01931