if (isParsing)
return;
break;
case WM_KEYDOWN:
if (открыто окно подсказки)
{
switch ((int) m.WParam)
{
case VK_DOWN:
if (в окне подсказки есть, что показывать)
// Изменяйте индекс выбранного элемента
return;
case VK_UP:
// Изменяйте индекс выбранного элемента
return;
case VK_RETURN:
case VK_SPACE: AcceptPrompt (); return;
case VK_ESCAPE: // Спрячьте окно подсказки return;
}
}
else if ((GetKeyState (VK_CONTROL) & 0x80) != 0)
{
switch ((int) m.WParam)
{
case VK_SPACE: CompleteWord (); return; // Ctrl+Space
case 0x5A: Undo (); return; // Ctrl+Z
case 0x59: Redo (); return; // Ctrl+Y
}
}
else
{
// Работа со стеками undo и redo
}
break;
case WM_CHAR:
switch ((int) m.WParam)
{
case VK_SPACE: // Ctrl+Space
if ((GetKeyState (VK_CONTROL) & 0x80) != 0)
return;
break;
case VK_RETURN: if (открыто окно подсказки) return;
break;
. . .
default:
. . .
}
break;
}
base.WndProc (ref m);
}
Перейдем к разработке методов класса SyntaxBox. Главная идея алгоритма разбора (метода Parse) состоит в том, что в процессе анализа текущего текста элемента SyntaxBox (его свойства Text), надо генерировать цветной (форматированный) текст (его же свойство Rtf). Для этого в классе SyntaxBox объявлена переменная rtf типа StringBuilder. В ней мы собираемся накопить форматированный текст (или текст разметки) и затем перенести его в RTF-документ. Перенос состоит в установке свойства Rtf. Схема метода Parse может выглядеть таким образом:
private void Parse ()
{
InitRtf (); // Установка RTF-заголовка
for (pos = 0; pos < TextLength; )// Объявление переменной pos (текущей позиции текста) удобно вынести в класс
{
AppendToken (); // Здесь выявляется и обрабатывается одно из ключевых слов
if (pos < TextLength) // Если после него что-то есть, то оно может быть комментарием
{
Comment com = FindComment (pos); // Здесь выявляются комментарии
if (найден)
// Здесь обрабатывается (форматируются) комментарий (Позиция pos сдвигается нужным образом)
else
{
AppendChar (); // Если ни ключевое слово, ни комментарий не найдены, вставляем простой текст
pos++;
}
}
}
Rtf = rtf.ToString (); // Накопленный в StringBuilder форматированный текст переносится в RTF-документ
}
Подскажу, как создать заголовок текста разметки RTF. Добавьте следующий метод в класс SyntaxBox.
private void InitRtf ()
{
rtf = new StringBuilder (150 + 2 * TextLength); // Это Capacity контейнера
rtf.Append (@"{\rtf1\fbidis\ansi\ansicpg1252\deff0\deflang1033{\fonttbl{"); // RTF header
rtf.Append (@"\f0\fnil\fcharset0" + Font.Name + ";}}\n"); // Установка шрифта
AppendColors (); // Добавьте таблицу цветов
// Этот фрагмент завершает заголовок RTF. После него можно вставлять наш форматированный текст.
rtf.Append (@"}\n\viewkind4\uc1\pard\ltrpar\cf" + colorTable[ForeColor] + " ");
}
Метод AppendColors добавляет в формат rtf таблицу цветов. Их надо взять из наших ключевых слов и комментариев, то есть из объектов вспомогательных классов (структур), которые вы разработали ранее. Как было сказано, все цвета надо пронумеровать. В процессе создания таблицы цветов (попутно) создим динамическую коллекцию Dictionary<Color, int> и используем ее в дальнейшем для окрашивания текста.
private void AppendColors ()
{
colorTable = new Dictionary<Color, int> ();
int id = 1;
colorTable.Add (ForeColor, id++); colorTable.Add (BackColor, id++);
rtf.Append (@"{\colortbl ;" +
@"\red" + ForeColor.R + @"\green" + ForeColor.G + @"\blue" + ForeColor.B + ";" +
@"\red" + BackColor.R + @"\green" + BackColor.G + @"\blue" + BackColor.B + ";");
foreach (для каждого ключевого слова в коллекции highlighter.Keywords)
{
if (такого цвета нет)
{
Color c = возьмите его из текущей структуры Keyword;
colorTable.Add (c, id++);
Уважаемый посетитель!
Чтобы распечатать файл, скачайте его (в формате Word).
Ссылка на скачивание - внизу страницы.