Создание Windows-приложений на основе Visual C#

Справочные материалы. перевод приложений. специальные возможности

Разбить на страницы
Показывать лекцию целиком
Для работы с данной лекцией используйте примеры.

Создание справки

Справка — непременный атрибут любой, даже самой небольшой программы. Хорошо написанная справка дает пользователям возможность быстро освоить основы работы с программой, практически не прибегая к помощи дополнительных учебников. Ее содержание может быть совсем маленьким — таким как справка к блокноту Windows, или огромным — таким как MSDN (библиотека, представляющая собой, по сути, гигантскую справочную систему).

Файл справки представляет собой совокупность HTML-страниц, скомпилированных в одно приложение формата *.chm или *.hlp. Иерархическая структура образуется системой гиперссылок между страницами и их древовидным расположением. В папке C:\WINDOWS\Help находятся справочные файлы большинства приложений операционной системы Windows.

В качестве приложения, к которому мы будем составлять справку, возьмем Notepad C#, разработанный нами во второй лекции. Поскольку программа включает в себя простейшие и всем известные операции с текстом, мы не будем их описывать, а в качестве материала воспользуемся их кодом (рис. 8.1).

(рис 8.1) Готовая справка приложения Notepad C#

Подготовка HTML-страниц

Исходные страницы справки лучше всего создавать в одном из пакетов верстки web-страниц, например, Microsoft Front Page. Справка будет состоять из 36 страниц, связанных между собой. В качестве фонового цвета на всех страницах я выбрал светло-голубой (Тег <body bgcolor="#66CCFF">). Для копирования кода я свернул все методы и обработчики в проекте в блоки, а при вставке в документ они автоматически разворачивались (рис. 8.2):

(рис 8.2) Копирование блоков кода

Таблица 8.1 содержит данные о страницах справки. Желательно самим создать HTML-страницы со всеми ссылками, указанными в этой таблице.

Исходные HTML — страницы справки
Название файлаЗаголовок страницыСодержание страницы
AboutForm.htm Свойства формы About

Свойства формы About:

Форма About, свойство Значение
Name About
FormBorderStyle FixedSingle
MaximizeBox False
MinimizeBox False
Size 318; 214
Text About Notepad C#

Внешний вид формы в режиме дизайна:

Полный листинг формы About. (ссылка на FullCodeAbout.htm)

AboutProgram.htm Обработчик пункта меню About Program

Обработчик пункта меню About Program..., форма frmmain (ссылка на frmmain.htm):

private void mnuAbout_Click(object sender, 
           System.EventArgs e)
{
//Создаем новый экземпляр формы About
About frm = new About();
frm.Show();
}

При выборе этого пункта меню появляется форма About (ссылка на AboutForm).

ArrangeIcons.htm Обработчик пункта меню Arrange Icons

Обработчик пункта меню Arrange Icons, форма frmmain (ссылка на frmmain.htm):

private void mnuArrangeIcons_Click(object sender, 
           System.EventArgs e)
{
this.LayoutMdi(MdiLayout.ArrangeIcons);
}
blank.htm Свойства формы blank

Свойства формы blank:

Форма blank, свойство Значение
Name blank
Text blank
WindowState Maximized

Внешний вид формы в режиме дизайна:

При выборе этого пункта меню появляется форма About (ссылка на AboutForm).

blank.htm Свойства формы blank

Свойства формы blank:

Форма blank, свойство Значение
Name blank
Text blank
WindowState Maximized

Внешний вид формы в режиме дизайна:

Полный листинг формы blank. (ссылка на FullCodeblank.htm)

blankCopy.htm Метод Copy формы blank

Метод Copy формы blank (ссылка на blank.htm):

public void Copy()
{
this.BufferText = richTextBox1.SelectedText;
}
blankCut.htm Метод Cut формы blank

Метод Cut формы blank (ссылка на blank.htm):

public void Cut()
{
this.BufferText = richTextBox1.SelectedText;
richTextBox1.SelectedText = "";
}
blankDelete.htm Метод Delete формы blank

Метод Delete формы blank (ссылка на blank.htm):

public void Delete()
{
richTextBox1.SelectedText = ""; 
this.BufferText = "";
}
blankOpen.htm Метод Open формы blank

Метод Open формы blank (ссылка на blank.htm):

public void Open(string OpenFileName)
{
///Вставьте сюда код из проекта
}
blankPaste.htm Метод Paste формы blank

Метод Paste формы blank (ссылка на blank.htm):

public void Paste()
{
richTextBox1.SelectedText = this.BufferText;
}
blankSave.htm Метод Save формы blank

Метод Save формы blank (ссылка на blank.htm):

public void Save(string SaveFileName)
{
///Вставьте сюда код из проекта
}
blankSelectAll.htm Метод Select All формы blank

Метод Select All формы blank (ссылка на blank.htm):

public void SelectAll()
{
richTextBox1.SelectAll(); 
}
Cascade.htm Обработчик пункта меню Cascade

Обработчик пункта меню Cascade, форма frmmain (ссылка на frmmain.htm):

private void mnuCascade_Click(object sender, 
           System.EventArgs e)
{
this.LayoutMdi(MdiLayout.Cascade);
}
Color.htm Обработчик пункта меню Color

Обработчик пункта меню Color, форма frmmain (ссылка на frmmain.htm):

private void mnuColor_Click(object sender, 
           System.EventArgs e)
{
///Вставьте сюда код из проекта
}
Copy.htm Обработчик пункта меню Copy

Обработчик пункта меню Copy, форма frmmain (ссылка на frmmain.htm):

private void mnuCopy_Click(object sender, 
           System.EventArgs e)
{
blank frm = (blank)this.ActiveMdiChild;
frm.Copy();
}

В коде вызывается метод Copy (ссылка на blankCopy.htm) формы blank (ссылка на blank.htm)

Cut.htm Обработчик пункта меню Cut

Обработчик пункта меню Cut, форма frmmain (ссылка на frmmain.htm):

private void mnuCut_Click(object sender, 
           System.EventArgs e)
{
blank frm = (blank)this.ActiveMdiChild;
frm.Cut();
}

В коде вызывается метод Cut (ссылка на blankCut.htm.htm) формы blank (ссылка на blank.htm)

Delete.htm Обработчик пункта меню Delete

Обработчик пункта меню Delete, форма frmmain (ссылка на frmmain.htm):

private void mnuDelete_Click(object sender, 
           System.EventArgs e)
{
blank frm = (blank)this.ActiveMdiChild;
frm.Delete();
}

В коде вызывается метод Delete (ссылка на blankDelete.htm) формы blank (ссылка на blank.htm)

Exit.htm Обработчик пункта меню Exit

Обработчик пункта меню Exit, форма frmmain (ссылка на frmmain.htm):

private void mnuExit_Click(object sender, 
           System.EventArgs e)
{
this.Close();
}
Find.htm Обработчик пункта меню Find

Обработчик пункта меню Find, форма frmmain (ссылка на frmmain.htm):

private void mnuFind_Click(object sender, 
           System.EventArgs e)
{
///Вставьте сюда код из проекта
}

При выборе этого пункта меню появляется форма FindForm (ссылка на FindForm.htm).

FindForm.htm Свойства формы FindForm

Свойства формы FindForm:

Форма FindForm, свойствоЗначение
Name FindForm
FormBorderStyle FixedToolWindow
Size 328; 112
Text Find

Внешний вид формы в режиме дизайна:

Полный листинг формы FindForm. (Ссылка на FullCodeFindForm.htm)

Font.htm Обработчик пункта меню Font

Обработчик пункта меню Font, форма frmmain (ссылка на frmmain.htm):

private void mnuFont_Click(object sender, 
           System.EventArgs e)
{
///Вставьте сюда код из проекта
}
frmmain.htm Свойства формы frmmain

Свойства формы frmmain:

Form1, форма, свойствоЗначение
Name frmmain
Icon Code\Glava2\NotepadCSharp\Icon\README.ICO
IsMdiContainer True
Menu mainMenu1
Text Notepad C#
WindowState Maximized
Внешний вид формы в режиме дизайна:

Полный листинг формы frmmain. (Ссылка на FullCodefrmmain.htm)

FullCodeAbout.htm Полный листинг формы About

Полный листинг формы About:

///Вставьте сюда код из проекта

FullCodeblank.htm Полный листинг формы blank

Полный листинг формы blank:

///Вставьте сюда код из проекта

FullCodeFindForm.htm Полный листинг формы FindForm

Полный листинг формы FindForm:

///Вставьте сюда код из проекта

FullCodefrmmain.htm Полный листинг формы frmmain

Полный листинг формы frmmain:

///Вставьте сюда код из проекта

index.htm Введение

Программа Notepad C# была сделана в ходе изучения элементов программирования на языке C# для Windows. По своей функциональности она напоминает что-то среднее между блокнотом и текстовым редактором WordPad. Некоторые фрагменты кода были приведены в чистом виде, без блоков обработки исключений. В результате при выборе неподходящих действий — например, операций работы с текстом при отсутствии бланка, — возможны ошибки. Поскольку исходный код программы прилагается, Вы можете добавить соответствующие блоки. Также, используя свойство Enabled и Visible элементов, можно получить недоступность или невидимость элементов, работа с которыми в определенные моменты вызывает исключения

New.htm Обработчик пункта меню New

Обработчик пункта меню New, форма frmmain (ссылка на frmmain.htm):

private void mnuNew_Click(object sender, 
           System.EventArgs e)
{
///Вставьте сюда код из проекта 
}
Notepadhelp.htm Обработчик пункта меню Notepad C# Help

Обработчик пункта меню Notepad C# Help, форма frmmain (ссылка на frmmain.htm):

private void mnunotepadhelp_Click(object sender, 
           System.EventArgs e)
{
try
{
Process SysInfo = new Process();
SysInfo.StartInfo.ErrorDialog = true;
SysInfo.StartInfo.FileName = "notepadhelp.chm";
SysInfo.Start();
}
catch (Exception ex)
{
MessageBox.Show (ex.Message);
}
}
Open.htm Обработчик пункта меню Open

Обработчик пункта меню Open, форма frmmain (ссылка на frmmain.htm):

private void mnuOpen_Click(object sender, 
           System.EventArgs e)
{
///Вставьте сюда код из проекта 
}

В коде вызывается метод Open (ссылка на blankOpen.htm) формы blank (ссылка на blank.htm)

Paste.htm Обработчик пункта меню Paste

Обработчик пункта меню Paste, форма frmmain (ссылка на frmmain.htm):

private void mnuPaste_Click(object sender, 
           System.EventArgs e)
{
blank frm = (blank)this.ActiveMdiChild;
frm.Paste();
}

В коде вызывается метод Paste (ссылка на blankPaste.htm) формы blank (ссылка на blank.htm)

Save.htm Обработчик пункта меню Save

Обработчик пункта меню Save, форма frmmain (ссылка на frmmain.htm):

private void mnuSave_Click(object sender, 
           System.EventArgs e)
{
//Переключаем фокус на данную форму.
blank frm = (blank)this.ActiveMdiChild;
//Вызываем метод Save формы blank
frm.Save(frm.DocName);
frm.IsSaved = true;
}

В коде вызывается метод Save (ссылка на blankSave.htm) формы blank (ссылка на blank.htm)

SaveAs.htm Обработчик пункта меню Save As

Обработчик пункта меню Save As, форма frmmain (ссылка на frmmain.htm):

private void mnuSaveAs_Click(object sender, 
           System.EventArgs e)
{
///Вставьте сюда код из проекта 
}
SelectAll.htm Обработчик пункта меню Select All

Обработчик пункта меню Select All, форма frmmain (ссылка на frmmain.htm):

private void mnuSelectAll_Click(object sender, 
           System.EventArgs e)
{
blank frm = (blank)this.ActiveMdiChild;
frm.SelectAll();
}

В коде вызывается метод Select All (ссылка на blankSelectAll.htm) формы blank (ссылка на blank.htm)

structure.htm Структура программы

Все возможности программы собраны в нескольких пунктах главного меню:

В пункте File собраны основные операции открытия и сохранения документа ( New (ссылка на New.htm), Open (ссылка на Open.htm), Save (ссылка на Save.htm), Save As (ссылка на SaveAs.htm), Exit (ссылка на Exit.htm)):

В пункте Edit расположены операции работы с текстом (Cut (ссылка на Cut.htm), Copy (ссылка на Copy.htm), Paste (ссылка на Paste.htm), Delete (ссылка на Delete.htm), Select All (ссылка на SelectAll.htm), Find (ссылка на Find.htm)):

Пункт Format позволяет задать свойства шрифта, такие как цвет, размер, стиль (Font (ссылка на Font.htm), Color (ссылка на Color.htm)) :

Для упорядочивание нескольких открытых документов используется пункт меню Window (Arrange Icons (ссылка на ArrangeIcons.htm), Cascade (ссылка на Cascade.htm), Tile Horizontal (ссылка на TileHorizontal.htm), Tile Vertical (ссылка на TileVertical.htm)):

В последнем пункте "?" содержатся пункты вызова этой справки и окно с информацией о программе (Notepad C# Help (ссылка на Notepadhelp.htm), About Program... (ссылка на AboutProgram.htm)):

TileHorizontal.htm Обработчик пункта меню Tile Horizontal

Обработчик пункта меню Tile Horizontal, форма frmmain (ссылка на frmmain.htm):

private void mnuTileHorizontal_Click(object sender, 
           System.EventArgs e)
{
this.LayoutMdi(MdiLayout.TileHorizontal);
}
TileVertical.htm Обработчик пункта меню Tile Vertical

Обработчик пункта меню Tile Vertical, форма frmmain (ссылка на frmmain.htm):

private void mnuTileVertical_Click(object sender, 
           System.EventArgs e)
{
this.LayoutMdi(MdiLayout.TileVertical);
}

Итак, в результате у нас получились 36 HTML-файлов. На главной странице — structure.htm — размещены ссылки на ключевые страницы всей группы.

На диске, прилагаемом к книге, вы найдете папку HelpPages с готовыми файлами (Code\Glava8\HELP\HelpPages).

Создание проекта в программе HTML Help Workshop

Приступим теперь к разработке файла справки, состоящего из подготовленных страниц. При установке Microsoft Visual Studio .NET на компьютер также устанавливается программа для создания справок — HTML Help Workshop. Для ее запуска переходим в меню Пуск\Все программы\папка HTML Help Workshop\ HTML Help Workshop. Подобно Visual Studio .NET, для работы с этой программой требуется создать проект. В меню File выбираем New\Project, в появившемся Мастере New Project нажимаем кнопку "Далее", указываем расположение проекта и его название (notepadhelp.hhp), в шаге New Project —> Existing Files снова нажимаем "Далее" и завершаем работу Мастера. В результате главное окно программы примет следующий вид (рис. 8.3):

Добавляем в проект html-страницы, на боковой панели инструментов щелкаем на кнопке(рис 8.3) Кнопка(Add/Remove topic files…), в появившемся окне нажимаем на кнопку Add и выбираем папку, содержащую страницы (рис. 8.4).

В результате в окне Project под заголовком [Files] появится список добавленных страниц. Можно просмотреть HTML-код каждой страницы, нажав кнопку(рис 8.4) Кнопка(View HTML Source). Обратите внимание на заголовки страниц: названия должны быть видны на русском языке, т. е. быть в кодировке Windows — 1251 или 1252 (рис. 8.5). Если заголовки представлены в другой кодировке, исправьте их — они понадобятся нам в дальнейшем.

(рис 8.5) Заголовки читаются (содержимое между <title> Обработчик пункта меню About Program</title>), сам текст может быть в другой кодировке (содержимое <font size = "2"> </font>)

Создание содержания

После того как в проект были включены исходные страницы, можно приступать к созданию содержания. Щелкаем на вкладку Contents, при этом появляется окно — "Таблица содержания не определена" (Table Contents Not Specified) — при создании проекта мы пропустили шаг Мастера с созданием файла содержания. Сделаем это теперь – выбираем пункт Create new contents file, указываем директорию для сохранения (желательно сохранять файл содержания там же, где расположен файл проекта notepadhelp.hhp) и называем его ContentsNhelp.hhc. Щелкаем на кнопке добавления страницы(Insert a page), в поле Entry title вводим название заголовка, которое будет отображаться в содержании, щелкаем на кнопке Add/Edit… и выбираем аналогичный заголовок HTML-страницы из файла проекта (рис. 8.6).

Добавляем таким же образом страницу "Структура программы". Изменяем порядок расположения заголовков в содержании, щелкая на кнопках со стрелками(рис 8.6) Кнопкаина панели инструментов. На рис. 8.1 замечаем, что заголовок "Главная форма frmmain" представляет собой папку, содержащую заголовок "Полный листинг главной формы", и папки c названиями пунктов меню, которые, в свою очередь, тоже содержат вложенные заголовки. Для вставки заголовка-папки нажимаем на кнопку(Insert a heading), появляется уже знакомое окно Table of Contents Entry. Вводим название заголовка и связываем с ним страницу frmmain.htm. Добавляем под ним еще один обычный заголовок "Полный листинг главной формы" (связанный со страницей FullCodefrmmain.htm), и он автоматически устанавливается с отступом от края окна. Расположение заголовка можно изменять, выделив его и нажимая на кнопки(Move selection right) и(Move selection left) (рис. 8.7).

(рис 8.7) Заголовки с отступом (слева) превращаются во вложенные заголовки в готовой справке (справа)

Заголовки-папки могут быть связанными с HTML-страницей или просто быть контейнером для других страниц (рис. 8.8).

(рис 8.8) Папка-заголовок "Главная форма frmmain" связана со страницей frmmain.htm, папка-заголовок "Меню File" представляет собой просто контейнер для других страниц

В результате должна получиться следующая иерархическая структура содержания (рис. 8.9):

Скомпилируем готовый файл справки — нажимаем на кнопку(рис 8.9) Кнопка(Compile HTML file) на панели инструментов Toolbar или выбираем пункт меню File/Compile… . Появляется диалоговое окно Create a compiled file, в котором дополнительно ставим галочку Save all files before compiling (сохранить все файлы перед компиляцией). После компиляции выводится отладочная информация в окне HTML Help Workshop, а в указанной директории появляется файл notepadhelp.chm (рис. 8.10).

(рис 8.10) Скомпилированный файл справки

Создание указателя

На рис. 8.1 располагается также вкладка "Указатель", при переключении на которую появляется возможность просматривать содержимое справки по ключевым словам (рис. 8.11).

Для создания указателя в проекте notepadhelp.hhp щелкаем на вкладке Index. Появляется окно "Указатель не определен" (Index Not Specified), аналогичное окну, с которым мы сталкивались при создании содержания. Выбираем создание нового файла-индекса (Create a new index file), называем его NotepadIndex.hhk. Для добавления ключевого слова нажимаем на кнопку(рис 8.11) Кнопка(Insert a keyword), в появившемся окне вводим ключевое слово и связываем с ним HTML-страницу (рис. 8.12).

Добавьте все ключевые слова, указанные на рис. 8.11. Для расположения элементов используйте стрелки(рис 8.12) Кнопкаина панели инструментов. При создании списка предоставляется возможность иерархического упорядочивания слов с помощью кнопоки— для больших списков это необходимо использовать. После завершения работы проведите сортировку слов, нажав на кнопку(Sort keywords alphabetically), и скомпилируйте проект.

Создание поиска

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

(рис 8.13) Поиск по ключевому слову по всей справке

В окне "Выберите раздел для вывода" отображаются страницы по их HTML-заголовкам, поэтому здесь очень важна правильная кодировка.

Для создания поиска в проекте notepadhelp.hhp переключаемся на вкладку Project и нажимаем на кнопку(Change project options). В появившемся окне на вкладке Compiler ставим галочку в чекбоксе Compile full-text search information. Теперь при компиляции будет создаваться база слов для поиска. На этой же вкладке Project нажимаем на кнопку(Add/Modify window definition) и в появившемся окне на вкладке General в поле Window type указываем название вкладки поиска (рис. 8.14).

(рис 8.14) Создание вкладки "Поиск"

В поле Title bar text также можно указать заголовок справки. Компилируем проект, открываем готовый файл notepad.chm — теперь появилась дополнительная вкладка с поиском.

Создание вкладки "Избранное"

При работе с большой справочной системой удобно организовывать собственную мини-справку, добавляя страницы в "Избранное" (рис. 8.15).

Для добавления этой возможности в проекте notepadhelp.hhp переходим на вкладку Project и нажимаем на кнопку(рис 8.15) Кнопка(Add/Modify window definition). В появившемся окне переходим на вкладку Navigation Pane, в группе Tabs ставим галочку в чекбоксе Favorites tab (рис. 8.16).

(рис 8.16) Добавление вкладки "Избранное"

Закрываем окно свойств и снова компилируем проект.

Тестирование и отладка справки

В конце работы мы должны получить один скомпилированный файл .chm, содержащий в себе все HTML-страницы, рисунки на них и ссылки. При компиляции проекта следует обращать внимание на окно отладки, в котором выводится результаты компиляции. Если процесс прошел успешно, выводится следующая информация:

Microsoft HTML Help Compiler 4.74.8702

Compiling d:\Uchebnik\Code\Glava8\HELP\notepadhelp.chm


Compile time: 0 minutes, 2 seconds
38  Topics
184  Local links
0  Internet links
1  Graphic


Created d:\Uchebnik\Code\Glava8\HELP\notepadhelp.chm, 77,290 bytes
Compression decreased file by 1,321,411 bytes.

Если программа сталкивается с ошибкойПодробнее о предупреждениях и ошибках см. в следующем разделе справки HTML Help Workshop: Creating Help/Compile and Test Help/Compile a Help Project/Compiler messages. — например, с отсутствием части страниц, — она продолжит компиляцию и в конце выведет соответствующий отчет:

Microsoft HTML Help Compiler 4.74.8702

Compiling d:\Uchebnik\Code\Glava8\HELP\notepadhelp.chm

HHC5003: Error: Compilation failed while compiling HelpPages\Paste.htm.
HHC5003: Error: Compilation failed while compiling HelpPages\Save.htm.
HHC5003: Error: Compilation failed while compiling HelpPages\SaveAs.htm.

The following files were not compiled:
HelpPages\Paste.htm
HelpPages\Save.htm
HelpPages\SaveAs.htm

При компиляции большой справочной системы желательно сохранять отладочные сообщения в виде файлов (рис. 8.17).

(рис 8.17) Сохранение отладочного сообщения в виде файла Test1.log

Если по разным причинам вам не удается скомпилировать проект, лучше всего восстановить его заново — при наличии файла содержания .hhc и файла указателя .hhk сделать это достаточно просто.

На диске, прилагаемом к книге, вы найдете файлы notepadhelp.chm, notepadhelp.hhp, ContentsNhelp.hhc, notepadhelp.hhk и Test1.log в каталоге Code\Glava8\HELP.

Добавление готового файла справки к приложению

Теперь, когда у нас есть готовый файл справки, нам остается только добавить его к приложению Notepad C#. Скопируем файл notepadhelp.chm в папку bin/Debug приложения. В главном меню формы frmmain добавляем новый пункт, устанавливая следующие свойства:

Свойство Значение
Name mnunotepadhelp
Shortcut F1
Text Notepad C# Help

Во второй лекции мы проходили запуск программ из приложения. Здесь внешней программой будет файл notepadhelp.chm; переходим в код формы и подключаем соответствующее пространство имен:

using System.Diagnostics;

Создаем обработчик пункта меню mnunotepadhelp:

private void mnunotepadhelp_Click(object sender, System.EventArgs e)
  {
    
    try
    {
      Process SysInfo = new Process();
      SysInfo.StartInfo.ErrorDialog = true;
      SysInfo.StartInfo.FileName = "notepadhelp.chm";
      SysInfo.Start();
    }
    catch (Exception ex)
    {
      MessageBox.Show (ex.Message);
    }
  }

Запускаем приложение. Справка вызывается при выборе пункта меню Notepad C# Help или нажатии клавиши F1.

Декомпиляция готовых файлов справки формата chm

Программа HTML Help Workshop позволяет разбирать готовые файлы в формате chm на составляющие страницы. Запускаем программу, в меню File выбираем Decompile, в поле Destination folder указываем путь к папке, в которую будут помещаться извлеченные HTML-файлы, в поле Compiled help file — путь к файлу chm.

(рис 8.18) Окно Decompile

После декомпиляции в указанной папке появятся файлы содержания hhc, указателя hhk и исходная папка с HTML-страницами (рис. 8.19).

(рис 8.19)

Создание интерактивной справки. Элемент управления Help Provider

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

(рис 8.20) При создании нового подключения в программе HyperTerminal, щелкнув на кнопку с вопросом можно получить краткое описание элемента

Создадим подобную функциональность на форме FindForm проекта NotepadCSharp. Открываем проект и перетаскиваем на форму FindForm элемент управления HelpProvider из окна Toolbox. Добавляем к имеющимся следующие свойства формы:

FindForm, свойствоЗначение
FormBorderStyle FixedDialog
HelpButton True
MaximizeBox False
MinimizeBox False

Заголовок формы изменился — на нем появилась кнопка с вопросительным знаком. На форме расположены пять видимых элементов управления — текстовое поле, две кнопки и два чекбокса. В свойстве ShowHelp on helpProvider1 каждого из этих элементов устанавливаем значение True. Текст, введенный в поле свойства HelpString on helpProvider1, будет появляться в качестве описания элемента. Установим следующие значения этого свойства:

Элемент Описание
txtFind Введите текст для поиска
cbMatchCase Найти с учетом регистра
cbMatchWhole Найти по целому слову
btnOK Выделить слово и закрыть форму
btnCancel Закрыть форму

Запускаем приложение. При щелчке на выбранном элементе появляется его описание (рис. 8.21).

(рис 8.21) Описание элемента

Всплывающие подсказки. Элемент управления ToolTip

C всплывающими подсказками мы уже сталкивались в лекции 2 в приложении NotepadCSharp — свойство ToolTipText кнопок панели инструментов toolBarMain позволяло устанавливать всплывающие подсказки. Это же свойство есть у панелей строки состояния StatusBar — мы выводили в него текущую дату. Для добавления всплывающих подсказок ко всем прочим объектам используется элемент управления ToolTip. Перетаскиваем его из окна ToolBox на форму FindForm. В окне Properties расположенных на форме элементов и в самой форме появилось свойство ToolTip on toolTip1. Устанавливаем следующие значения этого свойства:

Элемент Описание
txtFind Текст для поиска
cbMatchCase Поиск с учетом регистра
cbMatchWhole Поиск по целому слову
btnOK Найти слово
btnCancel Закрыть форму

Запускаем приложение. При наведении курсора на элемент управления появляется его подсказка (рис. 8.22).

(рис 8.22) Всплывающая подсказка элементов управления

Для появления подсказки необходимо, чтобы курсор оставался неподвижным на элементе в течение определенного промежутка времени. По умолчанию это время равно полсекунде. Для его изменения в окне Properties самого элемента toolTip1 устанавливаем нужное значение в миллисекундах в свойстве IntitialDelay.

Перевод приложений

При распространении приложения приходится задумываться о переводе пользовательского интерфейса на другие языки. При переводе больших пакетов, как правило, создается локальная версия целиком на одном языке. Это самый простой способ перевода программ. Другие программы, такие как Total Commander или Alcohol 120%, содержат многоязычный интерфейс, позволяющий менять оформление приложения непосредственно в ходе работы. Далее мы рассмотрим оба этих способа.

Автоматический выбор языка

В ходе установки операционной системы Windows при определении региональных параметров пользователю предлагается выбрать язык стандартов и форматов. Выбранное значение доступно для изменения в дальнейшем — в меню "Пуск" выбираем "Панель управления\Язык" и региональные параметры, вкладка "Региональные параметры" (рис. 8.23).

(рис 8.23) Инструмент "Язык и региональные параметры" Панели управления

Сделаем приложение, которое автоматически будет определять установленный язык стандартов и выводить соответствующий пользовательский интерфейс. Создаем новый Windows-проект, называем его SimpleCulture. Добавляем на форму кнопку и главное меню, устанавливаем следующие значения свойства Text этих элементов (рис. 8.24).

(рис 8.24) Приложение SimpleCulture. Размер формы — 300х128 пикселей

Значения свойств Name изменять не будем — наш проект достаточно прост, чтобы тратить на это время. Для кнопки устанавливаем обработчик, закрывающий форму:

private void button1_Click(object sender, System.EventArgs e)
  {
    this.Close();
  }

Итак, у нас получилась версия программы с интерфейсом на английском языке. В окне Properties формы устанавливаем свойству Localizable значение True. Это свойство разрешает поддержку многоязычного интерфейса. В свойстве Language выбираем значение English (United States). В выпадающем списке этого свойства доступны практически все языки мира с учетом региона; так, английскому языку соответствует 14 значений. Компилируем приложение. В свойстве Language выбираем Russian (Russia). Изменяем свойство Text элементов, просто удаляя названия на английском языке (рис. 8.25).

(рис 8.25) Приложение SimpleCulture с интерфейсом на русском языке. Размер формы — 264х208 пикселей

При изменении значения свойства Language форма теперь меняет пользовательский интерфейс. Обратите внимание на то, что значение Default этого свойства не является тождественным значению English (United States)! В этом можно убедиться, изменив размер формы или текст на кнопке в локальной версии, а затем переключившись на Default. Более того, при разработке интерфейса на нескольких языках следует выполнить основную функциональность приложения в значении Default, а затем заняться его локализацией — при переключении на другие языки интерфейс наследуется только от Default!

Переходим в код формы. Подключаем пространство имен Threading:

using System.Threading;

В конструкторе формы до (!) InitializeComponent устанавливаем культуру пользовательского интерфейса равной текущей культуре:

public Form1()
    
{
  Thread.CurrentThread.CurrentUICulture = 
  Thread.CurrentThread.CurrentCulture;
  InitializeComponent();
  }

Под культурой понимается язык и регион, под текущей культурой — соответствующие настройки инструмента "Язык и региональные параметры". Запускаем приложение. Среда CLR проверяет установленный язык и выводит приложение с русским интерфейсом. Закрываем его, переходим в "Панель управления" и устанавливаем язык "Английский (США)" на вкладке "Региональные параметры" в настройках инструмента "Язык и региональные параметры". Снова запускаем приложение. Теперь интерфейс приложения — на английском языке.

При локализации приложения среда Visual Studio .NET создает сборку, в которой хранятся все данные о приложении. В окне Solution Explorer нажимаем на кнопку (Show All Files) для просмотра добавленных файлов (рис. 8.26).

(рис 8.26) Добавление сборок при локализации приложения

Названия файлов-ресурсов (Form1. en-US и Form1.ru-RU) содержат в себе указание на язык (первая часть – en или ru) и регион (вторая часть US или RU). При создании собственных файлов-ресурсов следует придерживаться этого правила.

Область Windows Form Designer generated code также изменяется — теперь в ней содержатся свойства элементов, извлекаемые из сборок.

На диске, прилагаемом к книге, вы найдете приложение SimpleCulture (Code\Glava8\SimpleCulture).

Пользовательский выбор языка. Перевод сообщений приложения

В рассмотренном примере меняется пользовательский интерфейс, представляющий собой значения свойства Text элементов управления. Между тем в приложениях используются текстовые сообщения, определяемые в коде, например, в лекции 2 в приложении Notepad C# при попытке закрыть измененный документ появлялось окно-предупреждение Do you want save changes in NameDocument?. Рассмотрим перевод сообщений приложения и пользовательское изменение интерфейса. Скопируем проект TextEditor из лекции 2. В классе формы добавляем переменные для сохранения документа:

public bool IsSaved = false;
public string fileName;

Создаем метод Save, в который вставляем вырезанный обработчик пункта меню mnuSave:

public void Save(object sender, System.EventArgs e)
  {
    //Показываем диалог выбора файла
    saveFileDialog1.ShowDialog();
    // В качестве имени сохраняемого файла устанавливаем переменную fileName
     fileName=saveFileDialog1.FileName;
    //Создаем поток fs и открываем файл для записи.
    FileStream filestream = File.Open(fileName, FileMode.Create, FileAccess.Write);
    //Проверяем,  открыт ли поток,  и если открыт, выполняем условие
    if(filestream != null)
    {
      //Создаем объект streamwriter и связываем его с потоком filestream
      StreamWriter streamwriter = new StreamWriter(filestream);
      //Записываем данные из TextBox в файл
      streamwriter.Write(txtBox.Text);
      //Переносим данные из потока в файл
      streamwriter.Flush();
      //Закрываем поток
      filestream.Close();
      IsSaved = true;
    }
  }

В обработчике меню mnuSave вызываем этот метод:

private void mnuSave_Click(object sender, System.EventArgs e)
  {
    this.Save( fileName, e);
  }

Добавляем обработчик события Closing формы:

private void Form1_Closing(object sender, System.ComponentModel.CancelEventArgs e)
  {
    //Если переменная IsSaved имеет значение true, т. е. документ новый документ 
  //был сохранен (Save As) или в открытом документе были сохранены изменения (Save), 
  то выполняется условие
    if(IsSaved ==true)
      //Появляется диалоговое окно, предлагающее сохранить документ.
      if  (MessageBox.Show("Do you want to save changes in this document?", 
        "Message", MessageBoxButtons.YesNo, 
        MessageBoxIcon.Question) == DialogResult.Yes)
        //Если была нажата  кнопка Yes, вызываем метод Save
      {
        this.Save( fileName, e);
      }  
  }

Запускаем приложение. Теперь при попытке закрыть измененный документ появляется окно-предупреждение. Закрываем приложение, переключаемся в режим дизайна и добавляем следующие пункты меню (рис. 8.27):

Name Text
mnuLanguage Language
mnuEnglish English
mnuRussian Русский
(рис 8.27) Пункт главного меню Language

Устанавливаем свойству Localizable формы значение True, в свойстве Language выбираем язык English (United States). Компилируем приложение, в свойстве Language выбираем язык Russian (Russia). Переводим пункты меню на русский язык:

Name Text
mnuFile Файл
mnuOpen Открыть
mnuSave Сохранить
mnuLanguage Язык
mnuEnglish English
mnuRussian Русский

В окне Solution Explorer щелкаем правой кнопкой на названии проекта TextEditor и добавляем новый файл — Add/Add New Item… . В появившемся окне выбираем шаблон Assembly Resource File и называем его ClosingText.en-US.resx (рис. 8.28).

(рис 8.28) Файл Assembly Resource File

Проделаем эту операцию еще раз, новый шаблон назовем ClosingText.ru-RU.resx. Мы добавили эти файлы для хранения в них текстовых переменных, используемых приложением для различных локализаций. Откроем ресурс ClosingText.en-US.resx и введем переменную MessageText, в значении value которой укажем текст Do you want to save changes in this document?, выводимый приложением при закрытии (рис. 8.29).

(рис 8.29) Переменная MessageText в ресурсе ClosingText.en-US.resx

Аналогично, в ресурсе ClosingText.ru-RU.resx создадим такую же переменную, в значении которой укажем текст на русском языке: "Вы хотите сохранить изменения в документе?" (рис. 8.30).

(рис 8.30) Переменная MessageText в ресурсе ClosingText.ru-RU.resx

Переходим в код формы, подключаем следующие пространства имен:

//Пространство имен, используемое для определения культуры
//приложения и операционной системы
using System.Globalization;
//Пространство, используемое для работы с файлами ресурсов .resx,
//такими как ClosingText.en-US.resx, ClosingText.ru-RU.resx.
using System.Resources;
//Пространство для работы со сборками, более подробно о них см. лекцию 9.
using System.Reflection;
using System.Threading;

В классе формы объявляем следующие переменные и объекты:

//Переменная выбора, необходимая для определения культуры 
public string CultureDefine;
//Переменная для хранения английской культуры
private  string EnglishCulture;
//Переменная для русской культуры.
private  string RussianCulture;

Для управления ресурсами используется класс ResourceManager, который позволяет извлекать значения переменных, созданных в файле-ресурсе. Общая схема использования этого класса:

ResourceManager resourceManager = new  ResourceManager
("ПространствоИмен.НазваниеРесурса", Assembly.GetExecutingAssembly());

Для использования извлекаемой строковой переменной обращаемся к ее имени в ресурсе:

MessageBox.Show(resourceManager.GetString("ИмяПеременнойвРесурсе");

Возвращаемся к нашему листингу:

//Создаем экземпляр resourceManager класса ResourceManager
 ResourceManager resourceManager;

В конструкторе формы извлекается текстовая переменная из заданного ресурса:

public Form1()
 {
    
 InitializeComponent();
 //Инициализируем переменные
 EnglishCulture = "en-US";
 RussianCulture = "ru-RU";
 // Перменной CultureDefine присваиваем значение культуры, установленной на компьютере, 
 //используя свойство класса ResourceManager
 CultureDefine = CultureInfo.InstalledUICulture.ToString();
 // Создаем новый объект resourceManager, извлекающий из сборки 
 //текстовую переменную ClosingText
 resourceManager = new ResourceManager("TextEditor.ClosingText", Assembly.GetExecutingAssembly());
      
 }

Перегружаем конструктор формы:

public Form1(string FormCulture)
 {
    
 InitializeComponent();
 EnglishCulture = "en-US";
 RussianCulture = "ru-RU";
 //В качестве культуры устанавливаем значение CultureDefine
 CultureDefine = FormCulture;
 // Создаем новый объект resourceManager, извлекающий из сборки 
 //текстовую переменную ClosingText
 resourceManager = new ResourceManager("TextEditor.ClosingText", Assembly.GetExecutingAssembly());
  
 }

Окно-предупреждение появляется при наступлении события формы Closing. Заменяем строку Do you want to save changes in this document? на извлекаемую переменную MessageText файла ресурса (выделено цветом):

private void Form1_Closing(object sender, System.ComponentModel.CancelEventArgs e)
 {
…

  if(MessageBox.Show(resourceManager.GetString("MessageText"), 
  "Message", MessageBoxButtons.YesNo, 
  MessageBoxIcon.Question) == DialogResult.Yes)

…
 }

Добавляем возможность изменения языка при выборе определенного пункта меню. Создаем обработчик пункта меню mnuEnglish:

private void mnuEnglish_Click(object sender, System.EventArgs e)
  {
  //Устанавливаем английскую культуру в качестве выбранной.
  CultureDefine = EnglishCulture;
  // Устанавливаем выбранную культуру в качестве культуры  пользовательского интерфейса 
  Thread.CurrentThread.CurrentUICulture = new CultureInfo(CultureDefine, false);
  // Устанавливаем в качестве текущей культуры выбранную
  Thread.CurrentThread.CurrentCulture = new CultureInfo(CultureDefine, false);
  //Создаем новый экземпляр frm формы Form1:
  Form1 frm = new Form1(CultureDefine);
  //Скрываем текущий экземпляр
  this.Hide();
  //Вызываем новый экземпляр
  frm.Show();
}

Обработчик пункта меню mnuRussian аналогичен, только в качестве выбранной устанавливается русская культура:

private void mnuRussian_Click(object sender, System.EventArgs e)
  {
  CultureDefine = RussianCulture;
  Thread.CurrentThread.CurrentUICulture = new CultureInfo(CultureDefine, false);
  Thread.CurrentThread.CurrentCulture = new CultureInfo(CultureDefine, false);
  Form1 frm = new Form1(CultureDefine);
  this.Hide();
  frm.Show();
  }

Запускаем приложение. При изменении языка текущая форма скрывается, вместо нее появляется новая форма с нужным интерфейсом. При попытке закрыть форму с изменениями в сохраненном документе текст в окне предупреждения появляется на выбранном языке (рис. 8.31 и 8.32).

(рис 8.32) Русская версия приложения(рис 8.31) Английская версия приложения

При закрывании видимой формы остаются запущенными скрытые копии. Для полного завершения работы с приложением в событии Closed формы Form1 создадим процедуру выхода:

private void Form1_Closed(object sender, System.EventArgs e)
 {
   Application.Exit();
 }

Другие текстовые переменные, например, заголовок Message, также могут быть без труда локализованы при добавлении их в файлы ресурсов (рис. 8.33).

(рис 8.33) Для перевода заголовка была добавлена переменная ItemText в файлы ресурсов

На диске, прилагаемом к книге, вы найдете приложение TextEditor (Code\Glava8\TextEditor).

Форматированный вывод строк

На вкладке "Региональные параметры" инструмента "Язык и региональные стандарты" вы могли заметить группу числовых и денежных форматов. В приложениях может потребоваться специальное определение заданного формата, например, вывод результата в рублях или долларах. Рассмотрим это на практике. Создайте новое консольное приложение и назовите его FormatOutput. Весь дальнейший код будем писать внутри блока try…catch:

try 
  {
    //Дальнейший код…
  }
catch (Exception ex)
  {
  Console.WriteLine(ex.Message);
  }

Для начала разберемся с конструкцией, которую вы наверняка много раз встречали:

int i = 15;
Console.WriteLine("{0}", i);

При запуске на экран выведется число 15. Зачем так писать? Не проще ли вывести на экран это число следующим образом:

int i = 15;
Console.WriteLine( i);

Результат будет в точности таким же! Дело в том, что сами скобки и числа в них ({0}, {1}) — так называемые подстановочные знаки, позволяющие легко добиваться более сложного вывода на экран, например, такого:

int x = 23, y = –4, z = 5, j = 20, v = 40;
Console.WriteLine ("переменная x = {0}, переменная y = {1}, 
переменная z = {2}, переменная j = {3}, 
переменная v = {4}", x, y, z, j, v);

Результатом будет:

переменная x = 23, переменная y = –4, переменная z = 5, 
переменная j = 20, переменная v = 40

Опять-таки, такой же результат можно получить другим способом:

Console.WriteLine("переменная " + x);
Console.WriteLine("переменная " + y);
Console.WriteLine("переменная " + z);
Console.WriteLine("переменная " + j);
Console.WriteLine("переменная " + v);

Использование подстановочных знаков здесь, несомненно, является оправданным.

Для вывода в определенном формате подстановочные знаки с параметрами оказываются просто незаменимыми. Некоторые параметры подстановочных знаков:

  • d — десятичный формат. Позволяет задать общее количество знаков (при необходимости число дополняется слева нулями).
    int a = 38;
      //Результат  0038
      Console.WriteLine("a={0:d4}", a);
  • f — формат с фиксированной точностью. Позволяет задать количество знаков после запятой.
    double pi = 3.1415926;
      //Результат 3.14
      Console.WriteLine("pi={0:f2}", pi);
  • x — шестнадцатеричный формат.
    int b = 255;
      //Результат FF.
      Console.WriteLine("b={0:X}", b);
    int c = 255;
      //Результат ff.
      Console.WriteLine("c={0:x}", c);
  • c — денежный формат (добавляет знак доллара и показывает два знака после запятой).
    double d = 1003.214;
      //Результат $1, 003.14 в английской версии Windows (или при выборе 
      //английского языка (США) на вкладке "Региональные параметры" инструмента 
      //"Язык и региональные параметры")
      //1 003,14 р. в русской.
    Console.WriteLine("d={0:c}", d);
  • e — вывод числа в экспоненциальной форме.
    double e = 213.1;
      //Результат 2.131000e+002
      Console.WriteLine("e={0:e}", e);
  • На диске, прилагаемом к книге, вы найдете приложение FormatOutput (Code\Glava8\ FormatOutput)

    Специальные возможности

    Операционная система Windows предоставляет способы работы пользователям с ограниченными возможностями. Экранный диктор — одна из специальных утилит системы — произносит вслух заголовки программ, названия элементов управления, помогая ориентироваться людям с частичной или полной потерей зрения. Для запуска этой утилиты в меню "Пуск" выбираем команду "Выполнить" (Эквивалентное сочетание клавиш Windows+R) и вводим в строке narrator. Запущенный диктор объявляет о событиях на экране, читает вслух печатаемые символы, правда, только на английском языке.

    Некоторые свойства элементов управления были созданы именно для поддержки специальных возможностей. Скопируйте приложение Calculator из лекции 1. Значение свойства AccessibleName определяет текст, произносимый экранным диктором. Устанавливаем следующие значения этого свойства элементам управления, размещенным на форме:

    Свойство Name элементаСвойство AccessibleName элемента
    txtOutput Display
    btn0 zero
    btn1 one
    btn2 two
    btn3 three
    btn4 four
    btn5 five
    btn6 six
    btn7 seven
    btn8 eight
    btn9 nine
    btnChangesign change sign
    btnpoint point
    btn_delenie divide
    btn_umnojenie multiply
    btn_minus minus
    btn_plus plus
    btn_sbros reset
    btn_ravno equal

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

    Другие специальные свойства, такие как AccessibleDescription и AccessibleRole, применяемые гораздо реже, также могут быть использованы для разработки специализированных приложений. Подробное описание их см. в MSDN.

    На диске, прилагаемом к книге, вы найдете приложение Calculator с поддержкой свойства AccessibleName. (Code\Glava8\Calculator).

    Страницы:
    Для работы с данной лекцией используйте примеры.

    Создание справки

    Справка — непременный атрибут любой, даже самой небольшой программы. Хорошо написанная справка дает пользователям возможность быстро освоить основы работы с программой, практически не прибегая к помощи дополнительных учебников. Ее содержание может быть совсем маленьким — таким как справка к блокноту Windows, или огромным — таким как MSDN (библиотека, представляющая собой, по сути, гигантскую справочную систему).

    Файл справки представляет собой совокупность HTML-страниц, скомпилированных в одно приложение формата *.chm или *.hlp. Иерархическая структура образуется системой гиперссылок между страницами и их древовидным расположением. В папке C:\WINDOWS\Help находятся справочные файлы большинства приложений операционной системы Windows.

    В качестве приложения, к которому мы будем составлять справку, возьмем Notepad C#, разработанный нами во второй лекции. Поскольку программа включает в себя простейшие и всем известные операции с текстом, мы не будем их описывать, а в качестве материала воспользуемся их кодом (рис. 8.1).

    (рис 8.1) Готовая справка приложения Notepad C#

    Подготовка HTML-страниц

    Исходные страницы справки лучше всего создавать в одном из пакетов верстки web-страниц, например, Microsoft Front Page. Справка будет состоять из 36 страниц, связанных между собой. В качестве фонового цвета на всех страницах я выбрал светло-голубой (Тег <body bgcolor="#66CCFF">). Для копирования кода я свернул все методы и обработчики в проекте в блоки, а при вставке в документ они автоматически разворачивались (рис. 8.2):

    (рис 8.2) Копирование блоков кода

    Таблица 8.1 содержит данные о страницах справки. Желательно самим создать HTML-страницы со всеми ссылками, указанными в этой таблице.

    Исходные HTML — страницы справки
    Название файлаЗаголовок страницыСодержание страницы
    AboutForm.htm Свойства формы About

    Свойства формы About:

    Форма About, свойство Значение
    Name About
    FormBorderStyle FixedSingle
    MaximizeBox False
    MinimizeBox False
    Size 318; 214
    Text About Notepad C#

    Внешний вид формы в режиме дизайна:

    Полный листинг формы About. (ссылка на FullCodeAbout.htm)

    AboutProgram.htm Обработчик пункта меню About Program

    Обработчик пункта меню About Program..., форма frmmain (ссылка на frmmain.htm):

    private void mnuAbout_Click(object sender, 
               System.EventArgs e)
    {
    //Создаем новый экземпляр формы About
    About frm = new About();
    frm.Show();
    }

    При выборе этого пункта меню появляется форма About (ссылка на AboutForm).

    ArrangeIcons.htm Обработчик пункта меню Arrange Icons

    Обработчик пункта меню Arrange Icons, форма frmmain (ссылка на frmmain.htm):

    private void mnuArrangeIcons_Click(object sender, 
               System.EventArgs e)
    {
    this.LayoutMdi(MdiLayout.ArrangeIcons);
    }
    blank.htm Свойства формы blank

    Свойства формы blank:

    Форма blank, свойство Значение
    Name blank
    Text blank
    WindowState Maximized

    Внешний вид формы в режиме дизайна:

    При выборе этого пункта меню появляется форма About (ссылка на AboutForm).

    blank.htm Свойства формы blank

    Свойства формы blank:

    Форма blank, свойство Значение
    Name blank
    Text blank
    WindowState Maximized

    Внешний вид формы в режиме дизайна:

    Полный листинг формы blank. (ссылка на FullCodeblank.htm)

    blankCopy.htm Метод Copy формы blank

    Метод Copy формы blank (ссылка на blank.htm):

    public void Copy()
    {
    this.BufferText = richTextBox1.SelectedText;
    }
    blankCut.htm Метод Cut формы blank

    Метод Cut формы blank (ссылка на blank.htm):

    public void Cut()
    {
    this.BufferText = richTextBox1.SelectedText;
    richTextBox1.SelectedText = "";
    }
    blankDelete.htm Метод Delete формы blank

    Метод Delete формы blank (ссылка на blank.htm):

    public void Delete()
    {
    richTextBox1.SelectedText = ""; 
    this.BufferText = "";
    }
    blankOpen.htm Метод Open формы blank

    Метод Open формы blank (ссылка на blank.htm):

    public void Open(string OpenFileName)
    {
    ///Вставьте сюда код из проекта
    }
    blankPaste.htm Метод Paste формы blank

    Метод Paste формы blank (ссылка на blank.htm):

    public void Paste()
    {
    richTextBox1.SelectedText = this.BufferText;
    }
    blankSave.htm Метод Save формы blank

    Метод Save формы blank (ссылка на blank.htm):

    public void Save(string SaveFileName)
    {
    ///Вставьте сюда код из проекта
    }
    blankSelectAll.htm Метод Select All формы blank

    Метод Select All формы blank (ссылка на blank.htm):

    public void SelectAll()
    {
    richTextBox1.SelectAll(); 
    }
    Cascade.htm Обработчик пункта меню Cascade

    Обработчик пункта меню Cascade, форма frmmain (ссылка на frmmain.htm):

    private void mnuCascade_Click(object sender, 
               System.EventArgs e)
    {
    this.LayoutMdi(MdiLayout.Cascade);
    }
    Color.htm Обработчик пункта меню Color

    Обработчик пункта меню Color, форма frmmain (ссылка на frmmain.htm):

    private void mnuColor_Click(object sender, 
               System.EventArgs e)
    {
    ///Вставьте сюда код из проекта
    }
    Copy.htm Обработчик пункта меню Copy

    Обработчик пункта меню Copy, форма frmmain (ссылка на frmmain.htm):

    private void mnuCopy_Click(object sender, 
               System.EventArgs e)
    {
    blank frm = (blank)this.ActiveMdiChild;
    frm.Copy();
    }

    В коде вызывается метод Copy (ссылка на blankCopy.htm) формы blank (ссылка на blank.htm)

    Cut.htm Обработчик пункта меню Cut

    Обработчик пункта меню Cut, форма frmmain (ссылка на frmmain.htm):

    private void mnuCut_Click(object sender, 
               System.EventArgs e)
    {
    blank frm = (blank)this.ActiveMdiChild;
    frm.Cut();
    }

    В коде вызывается метод Cut (ссылка на blankCut.htm.htm) формы blank (ссылка на blank.htm)

    Delete.htm Обработчик пункта меню Delete

    Обработчик пункта меню Delete, форма frmmain (ссылка на frmmain.htm):

    private void mnuDelete_Click(object sender, 
               System.EventArgs e)
    {
    blank frm = (blank)this.ActiveMdiChild;
    frm.Delete();
    }

    В коде вызывается метод Delete (ссылка на blankDelete.htm) формы blank (ссылка на blank.htm)

    Exit.htm Обработчик пункта меню Exit

    Обработчик пункта меню Exit, форма frmmain (ссылка на frmmain.htm):

    private void mnuExit_Click(object sender, 
               System.EventArgs e)
    {
    this.Close();
    }
    Find.htm Обработчик пункта меню Find

    Обработчик пункта меню Find, форма frmmain (ссылка на frmmain.htm):

    private void mnuFind_Click(object sender, 
               System.EventArgs e)
    {
    ///Вставьте сюда код из проекта
    }

    При выборе этого пункта меню появляется форма FindForm (ссылка на FindForm.htm).

    FindForm.htm Свойства формы FindForm

    Свойства формы FindForm:

    Форма FindForm, свойствоЗначение
    Name FindForm
    FormBorderStyle FixedToolWindow
    Size 328; 112
    Text Find

    Внешний вид формы в режиме дизайна:

    Полный листинг формы FindForm. (Ссылка на FullCodeFindForm.htm)

    Font.htm Обработчик пункта меню Font

    Обработчик пункта меню Font, форма frmmain (ссылка на frmmain.htm):

    private void mnuFont_Click(object sender, 
               System.EventArgs e)
    {
    ///Вставьте сюда код из проекта
    }
    frmmain.htm Свойства формы frmmain

    Свойства формы frmmain:

    Form1, форма, свойствоЗначение
    Name frmmain
    Icon Code\Glava2\NotepadCSharp\Icon\README.ICO
    IsMdiContainer True
    Menu mainMenu1
    Text Notepad C#
    WindowState Maximized
    Внешний вид формы в режиме дизайна:

    Полный листинг формы frmmain. (Ссылка на FullCodefrmmain.htm)

    FullCodeAbout.htm Полный листинг формы About

    Полный листинг формы About:

    ///Вставьте сюда код из проекта

    FullCodeblank.htm Полный листинг формы blank

    Полный листинг формы blank:

    ///Вставьте сюда код из проекта

    FullCodeFindForm.htm Полный листинг формы FindForm

    Полный листинг формы FindForm:

    ///Вставьте сюда код из проекта

    FullCodefrmmain.htm Полный листинг формы frmmain

    Полный листинг формы frmmain:

    ///Вставьте сюда код из проекта

    index.htm Введение

    Программа Notepad C# была сделана в ходе изучения элементов программирования на языке C# для Windows. По своей функциональности она напоминает что-то среднее между блокнотом и текстовым редактором WordPad. Некоторые фрагменты кода были приведены в чистом виде, без блоков обработки исключений. В результате при выборе неподходящих действий — например, операций работы с текстом при отсутствии бланка, — возможны ошибки. Поскольку исходный код программы прилагается, Вы можете добавить соответствующие блоки. Также, используя свойство Enabled и Visible элементов, можно получить недоступность или невидимость элементов, работа с которыми в определенные моменты вызывает исключения

    New.htm Обработчик пункта меню New

    Обработчик пункта меню New, форма frmmain (ссылка на frmmain.htm):

    private void mnuNew_Click(object sender, 
               System.EventArgs e)
    {
    ///Вставьте сюда код из проекта 
    }
    Notepadhelp.htm Обработчик пункта меню Notepad C# Help

    Обработчик пункта меню Notepad C# Help, форма frmmain (ссылка на frmmain.htm):

    private void mnunotepadhelp_Click(object sender, 
               System.EventArgs e)
    {
    try
    {
    Process SysInfo = new Process();
    SysInfo.StartInfo.ErrorDialog = true;
    SysInfo.StartInfo.FileName = "notepadhelp.chm";
    SysInfo.Start();
    }
    catch (Exception ex)
    {
    MessageBox.Show (ex.Message);
    }
    }
    Open.htm Обработчик пункта меню Open

    Обработчик пункта меню Open, форма frmmain (ссылка на frmmain.htm):

    private void mnuOpen_Click(object sender, 
               System.EventArgs e)
    {
    ///Вставьте сюда код из проекта 
    }

    В коде вызывается метод Open (ссылка на blankOpen.htm) формы blank (ссылка на blank.htm)

    Paste.htm Обработчик пункта меню Paste

    Обработчик пункта меню Paste, форма frmmain (ссылка на frmmain.htm):

    private void mnuPaste_Click(object sender, 
               System.EventArgs e)
    {
    blank frm = (blank)this.ActiveMdiChild;
    frm.Paste();
    }

    В коде вызывается метод Paste (ссылка на blankPaste.htm) формы blank (ссылка на blank.htm)

    Save.htm Обработчик пункта меню Save

    Обработчик пункта меню Save, форма frmmain (ссылка на frmmain.htm):

    private void mnuSave_Click(object sender, 
               System.EventArgs e)
    {
    //Переключаем фокус на данную форму.
    blank frm = (blank)this.ActiveMdiChild;
    //Вызываем метод Save формы blank
    frm.Save(frm.DocName);
    frm.IsSaved = true;
    }

    В коде вызывается метод Save (ссылка на blankSave.htm) формы blank (ссылка на blank.htm)

    SaveAs.htm Обработчик пункта меню Save As

    Обработчик пункта меню Save As, форма frmmain (ссылка на frmmain.htm):

    private void mnuSaveAs_Click(object sender, 
               System.EventArgs e)
    {
    ///Вставьте сюда код из проекта 
    }
    SelectAll.htm Обработчик пункта меню Select All

    Обработчик пункта меню Select All, форма frmmain (ссылка на frmmain.htm):

    private void mnuSelectAll_Click(object sender, 
               System.EventArgs e)
    {
    blank frm = (blank)this.ActiveMdiChild;
    frm.SelectAll();
    }

    В коде вызывается метод Select All (ссылка на blankSelectAll.htm) формы blank (ссылка на blank.htm)

    structure.htm Структура программы

    Все возможности программы собраны в нескольких пунктах главного меню:

    В пункте File собраны основные операции открытия и сохранения документа ( New (ссылка на New.htm), Open (ссылка на Open.htm), Save (ссылка на Save.htm), Save As (ссылка на SaveAs.htm), Exit (ссылка на Exit.htm)):

    В пункте Edit расположены операции работы с текстом (Cut (ссылка на Cut.htm), Copy (ссылка на Copy.htm), Paste (ссылка на Paste.htm), Delete (ссылка на Delete.htm), Select All (ссылка на SelectAll.htm), Find (ссылка на Find.htm)):

    Пункт Format позволяет задать свойства шрифта, такие как цвет, размер, стиль (Font (ссылка на Font.htm), Color (ссылка на Color.htm)) :

    Для упорядочивание нескольких открытых документов используется пункт меню Window (Arrange Icons (ссылка на ArrangeIcons.htm), Cascade (ссылка на Cascade.htm), Tile Horizontal (ссылка на TileHorizontal.htm), Tile Vertical (ссылка на TileVertical.htm)):

    В последнем пункте "?" содержатся пункты вызова этой справки и окно с информацией о программе (Notepad C# Help (ссылка на Notepadhelp.htm), About Program... (ссылка на AboutProgram.htm)):

    TileHorizontal.htm Обработчик пункта меню Tile Horizontal

    Обработчик пункта меню Tile Horizontal, форма frmmain (ссылка на frmmain.htm):

    private void mnuTileHorizontal_Click(object sender, 
               System.EventArgs e)
    {
    this.LayoutMdi(MdiLayout.TileHorizontal);
    }
    TileVertical.htm Обработчик пункта меню Tile Vertical

    Обработчик пункта меню Tile Vertical, форма frmmain (ссылка на frmmain.htm):

    private void mnuTileVertical_Click(object sender, 
               System.EventArgs e)
    {
    this.LayoutMdi(MdiLayout.TileVertical);
    }

    Итак, в результате у нас получились 36 HTML-файлов. На главной странице — structure.htm — размещены ссылки на ключевые страницы всей группы.

    На диске, прилагаемом к книге, вы найдете папку HelpPages с готовыми файлами (Code\Glava8\HELP\HelpPages).

    Создание проекта в программе HTML Help Workshop

    Приступим теперь к разработке файла справки, состоящего из подготовленных страниц. При установке Microsoft Visual Studio .NET на компьютер также устанавливается программа для создания справок — HTML Help Workshop. Для ее запуска переходим в меню Пуск\Все программы\папка HTML Help Workshop\ HTML Help Workshop. Подобно Visual Studio .NET, для работы с этой программой требуется создать проект. В меню File выбираем New\Project, в появившемся Мастере New Project нажимаем кнопку "Далее", указываем расположение проекта и его название (notepadhelp.hhp), в шаге New Project —> Existing Files снова нажимаем "Далее" и завершаем работу Мастера. В результате главное окно программы примет следующий вид (рис. 8.3):

    Добавляем в проект html-страницы, на боковой панели инструментов щелкаем на кнопке(рис 8.3) Кнопка(Add/Remove topic files…), в появившемся окне нажимаем на кнопку Add и выбираем папку, содержащую страницы (рис. 8.4).

    В результате в окне Project под заголовком [Files] появится список добавленных страниц. Можно просмотреть HTML-код каждой страницы, нажав кнопку(рис 8.4) Кнопка(View HTML Source). Обратите внимание на заголовки страниц: названия должны быть видны на русском языке, т. е. быть в кодировке Windows — 1251 или 1252 (рис. 8.5). Если заголовки представлены в другой кодировке, исправьте их — они понадобятся нам в дальнейшем.

    (рис 8.5) Заголовки читаются (содержимое между <title> Обработчик пункта меню About Program</title>), сам текст может быть в другой кодировке (содержимое <font size = "2"> </font>)

    Создание содержания

    После того как в проект были включены исходные страницы, можно приступать к созданию содержания. Щелкаем на вкладку Contents, при этом появляется окно — "Таблица содержания не определена" (Table Contents Not Specified) — при создании проекта мы пропустили шаг Мастера с созданием файла содержания. Сделаем это теперь – выбираем пункт Create new contents file, указываем директорию для сохранения (желательно сохранять файл содержания там же, где расположен файл проекта notepadhelp.hhp) и называем его ContentsNhelp.hhc. Щелкаем на кнопке добавления страницы(Insert a page), в поле Entry title вводим название заголовка, которое будет отображаться в содержании, щелкаем на кнопке Add/Edit… и выбираем аналогичный заголовок HTML-страницы из файла проекта (рис. 8.6).

    Добавляем таким же образом страницу "Структура программы". Изменяем порядок расположения заголовков в содержании, щелкая на кнопках со стрелками(рис 8.6) Кнопкаина панели инструментов. На рис. 8.1 замечаем, что заголовок "Главная форма frmmain" представляет собой папку, содержащую заголовок "Полный листинг главной формы", и папки c названиями пунктов меню, которые, в свою очередь, тоже содержат вложенные заголовки. Для вставки заголовка-папки нажимаем на кнопку(Insert a heading), появляется уже знакомое окно Table of Contents Entry. Вводим название заголовка и связываем с ним страницу frmmain.htm. Добавляем под ним еще один обычный заголовок "Полный листинг главной формы" (связанный со страницей FullCodefrmmain.htm), и он автоматически устанавливается с отступом от края окна. Расположение заголовка можно изменять, выделив его и нажимая на кнопки(Move selection right) и(Move selection left) (рис. 8.7).

    (рис 8.7) Заголовки с отступом (слева) превращаются во вложенные заголовки в готовой справке (справа)

    Заголовки-папки могут быть связанными с HTML-страницей или просто быть контейнером для других страниц (рис. 8.8).

    (рис 8.8) Папка-заголовок "Главная форма frmmain" связана со страницей frmmain.htm, папка-заголовок "Меню File" представляет собой просто контейнер для других страниц

    В результате должна получиться следующая иерархическая структура содержания (рис. 8.9):

    Скомпилируем готовый файл справки — нажимаем на кнопку(рис 8.9) Кнопка(Compile HTML file) на панели инструментов Toolbar или выбираем пункт меню File/Compile… . Появляется диалоговое окно Create a compiled file, в котором дополнительно ставим галочку Save all files before compiling (сохранить все файлы перед компиляцией). После компиляции выводится отладочная информация в окне HTML Help Workshop, а в указанной директории появляется файл notepadhelp.chm (рис. 8.10).

    (рис 8.10) Скомпилированный файл справки

    Создание указателя

    На рис. 8.1 располагается также вкладка "Указатель", при переключении на которую появляется возможность просматривать содержимое справки по ключевым словам (рис. 8.11).

    Для создания указателя в проекте notepadhelp.hhp щелкаем на вкладке Index. Появляется окно "Указатель не определен" (Index Not Specified), аналогичное окну, с которым мы сталкивались при создании содержания. Выбираем создание нового файла-индекса (Create a new index file), называем его NotepadIndex.hhk. Для добавления ключевого слова нажимаем на кнопку(рис 8.11) Кнопка(Insert a keyword), в появившемся окне вводим ключевое слово и связываем с ним HTML-страницу (рис. 8.12).

    Добавьте все ключевые слова, указанные на рис. 8.11. Для расположения элементов используйте стрелки(рис 8.12) Кнопкаина панели инструментов. При создании списка предоставляется возможность иерархического упорядочивания слов с помощью кнопоки— для больших списков это необходимо использовать. После завершения работы проведите сортировку слов, нажав на кнопку(Sort keywords alphabetically), и скомпилируйте проект.

    Создание поиска

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

    (рис 8.13) Поиск по ключевому слову по всей справке

    В окне "Выберите раздел для вывода" отображаются страницы по их HTML-заголовкам, поэтому здесь очень важна правильная кодировка.

    Для создания поиска в проекте notepadhelp.hhp переключаемся на вкладку Project и нажимаем на кнопку(Change project options). В появившемся окне на вкладке Compiler ставим галочку в чекбоксе Compile full-text search information. Теперь при компиляции будет создаваться база слов для поиска. На этой же вкладке Project нажимаем на кнопку(Add/Modify window definition) и в появившемся окне на вкладке General в поле Window type указываем название вкладки поиска (рис. 8.14).

    (рис 8.14) Создание вкладки "Поиск"

    В поле Title bar text также можно указать заголовок справки. Компилируем проект, открываем готовый файл notepad.chm — теперь появилась дополнительная вкладка с поиском.

    Создание вкладки "Избранное"

    При работе с большой справочной системой удобно организовывать собственную мини-справку, добавляя страницы в "Избранное" (рис. 8.15).

    Для добавления этой возможности в проекте notepadhelp.hhp переходим на вкладку Project и нажимаем на кнопку(рис 8.15) Кнопка(Add/Modify window definition). В появившемся окне переходим на вкладку Navigation Pane, в группе Tabs ставим галочку в чекбоксе Favorites tab (рис. 8.16).

    (рис 8.16) Добавление вкладки "Избранное"

    Закрываем окно свойств и снова компилируем проект.

    Тестирование и отладка справки

    В конце работы мы должны получить один скомпилированный файл .chm, содержащий в себе все HTML-страницы, рисунки на них и ссылки. При компиляции проекта следует обращать внимание на окно отладки, в котором выводится результаты компиляции. Если процесс прошел успешно, выводится следующая информация:

    Microsoft HTML Help Compiler 4.74.8702
    
    Compiling d:\Uchebnik\Code\Glava8\HELP\notepadhelp.chm
    
    
    Compile time: 0 minutes, 2 seconds
    38  Topics
    184  Local links
    0  Internet links
    1  Graphic
    
    
    Created d:\Uchebnik\Code\Glava8\HELP\notepadhelp.chm, 77,290 bytes
    Compression decreased file by 1,321,411 bytes.

    Если программа сталкивается с ошибкойПодробнее о предупреждениях и ошибках см. в следующем разделе справки HTML Help Workshop: Creating Help/Compile and Test Help/Compile a Help Project/Compiler messages. — например, с отсутствием части страниц, — она продолжит компиляцию и в конце выведет соответствующий отчет:

    Microsoft HTML Help Compiler 4.74.8702
    
    Compiling d:\Uchebnik\Code\Glava8\HELP\notepadhelp.chm
    
    HHC5003: Error: Compilation failed while compiling HelpPages\Paste.htm.
    HHC5003: Error: Compilation failed while compiling HelpPages\Save.htm.
    HHC5003: Error: Compilation failed while compiling HelpPages\SaveAs.htm.
    
    The following files were not compiled:
    HelpPages\Paste.htm
    HelpPages\Save.htm
    HelpPages\SaveAs.htm

    При компиляции большой справочной системы желательно сохранять отладочные сообщения в виде файлов (рис. 8.17).

    (рис 8.17) Сохранение отладочного сообщения в виде файла Test1.log

    Если по разным причинам вам не удается скомпилировать проект, лучше всего восстановить его заново — при наличии файла содержания .hhc и файла указателя .hhk сделать это достаточно просто.

    На диске, прилагаемом к книге, вы найдете файлы notepadhelp.chm, notepadhelp.hhp, ContentsNhelp.hhc, notepadhelp.hhk и Test1.log в каталоге Code\Glava8\HELP.

    Добавление готового файла справки к приложению

    Теперь, когда у нас есть готовый файл справки, нам остается только добавить его к приложению Notepad C#. Скопируем файл notepadhelp.chm в папку bin/Debug приложения. В главном меню формы frmmain добавляем новый пункт, устанавливая следующие свойства:

    Свойство Значение
    Name mnunotepadhelp
    Shortcut F1
    Text Notepad C# Help

    Во второй лекции мы проходили запуск программ из приложения. Здесь внешней программой будет файл notepadhelp.chm; переходим в код формы и подключаем соответствующее пространство имен:

    using System.Diagnostics;

    Создаем обработчик пункта меню mnunotepadhelp:

    private void mnunotepadhelp_Click(object sender, System.EventArgs e)
      {
        
        try
        {
          Process SysInfo = new Process();
          SysInfo.StartInfo.ErrorDialog = true;
          SysInfo.StartInfo.FileName = "notepadhelp.chm";
          SysInfo.Start();
        }
        catch (Exception ex)
        {
          MessageBox.Show (ex.Message);
        }
      }

    Запускаем приложение. Справка вызывается при выборе пункта меню Notepad C# Help или нажатии клавиши F1.

    Декомпиляция готовых файлов справки формата chm

    Программа HTML Help Workshop позволяет разбирать готовые файлы в формате chm на составляющие страницы. Запускаем программу, в меню File выбираем Decompile, в поле Destination folder указываем путь к папке, в которую будут помещаться извлеченные HTML-файлы, в поле Compiled help file — путь к файлу chm.

    (рис 8.18) Окно Decompile

    После декомпиляции в указанной папке появятся файлы содержания hhc, указателя hhk и исходная папка с HTML-страницами (рис. 8.19).

    (рис 8.19)

    Создание интерактивной справки. Элемент управления Help Provider

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

    (рис 8.20) При создании нового подключения в программе HyperTerminal, щелкнув на кнопку с вопросом можно получить краткое описание элемента

    Создадим подобную функциональность на форме FindForm проекта NotepadCSharp. Открываем проект и перетаскиваем на форму FindForm элемент управления HelpProvider из окна Toolbox. Добавляем к имеющимся следующие свойства формы:

    FindForm, свойствоЗначение
    FormBorderStyle FixedDialog
    HelpButton True
    MaximizeBox False
    MinimizeBox False

    Заголовок формы изменился — на нем появилась кнопка с вопросительным знаком. На форме расположены пять видимых элементов управления — текстовое поле, две кнопки и два чекбокса. В свойстве ShowHelp on helpProvider1 каждого из этих элементов устанавливаем значение True. Текст, введенный в поле свойства HelpString on helpProvider1, будет появляться в качестве описания элемента. Установим следующие значения этого свойства:

    Элемент Описание
    txtFind Введите текст для поиска
    cbMatchCase Найти с учетом регистра
    cbMatchWhole Найти по целому слову
    btnOK Выделить слово и закрыть форму
    btnCancel Закрыть форму

    Запускаем приложение. При щелчке на выбранном элементе появляется его описание (рис. 8.21).

    (рис 8.21) Описание элемента

    Всплывающие подсказки. Элемент управления ToolTip

    C всплывающими подсказками мы уже сталкивались в лекции 2 в приложении NotepadCSharp — свойство ToolTipText кнопок панели инструментов toolBarMain позволяло устанавливать всплывающие подсказки. Это же свойство есть у панелей строки состояния StatusBar — мы выводили в него текущую дату. Для добавления всплывающих подсказок ко всем прочим объектам используется элемент управления ToolTip. Перетаскиваем его из окна ToolBox на форму FindForm. В окне Properties расположенных на форме элементов и в самой форме появилось свойство ToolTip on toolTip1. Устанавливаем следующие значения этого свойства:

    Элемент Описание
    txtFind Текст для поиска
    cbMatchCase Поиск с учетом регистра
    cbMatchWhole Поиск по целому слову
    btnOK Найти слово
    btnCancel Закрыть форму

    Запускаем приложение. При наведении курсора на элемент управления появляется его подсказка (рис. 8.22).

    (рис 8.22) Всплывающая подсказка элементов управления

    Для появления подсказки необходимо, чтобы курсор оставался неподвижным на элементе в течение определенного промежутка времени. По умолчанию это время равно полсекунде. Для его изменения в окне Properties самого элемента toolTip1 устанавливаем нужное значение в миллисекундах в свойстве IntitialDelay.

    Перевод приложений

    При распространении приложения приходится задумываться о переводе пользовательского интерфейса на другие языки. При переводе больших пакетов, как правило, создается локальная версия целиком на одном языке. Это самый простой способ перевода программ. Другие программы, такие как Total Commander или Alcohol 120%, содержат многоязычный интерфейс, позволяющий менять оформление приложения непосредственно в ходе работы. Далее мы рассмотрим оба этих способа.

    Автоматический выбор языка

    В ходе установки операционной системы Windows при определении региональных параметров пользователю предлагается выбрать язык стандартов и форматов. Выбранное значение доступно для изменения в дальнейшем — в меню "Пуск" выбираем "Панель управления\Язык" и региональные параметры, вкладка "Региональные параметры" (рис. 8.23).

    (рис 8.23) Инструмент "Язык и региональные параметры" Панели управления

    Сделаем приложение, которое автоматически будет определять установленный язык стандартов и выводить соответствующий пользовательский интерфейс. Создаем новый Windows-проект, называем его SimpleCulture. Добавляем на форму кнопку и главное меню, устанавливаем следующие значения свойства Text этих элементов (рис. 8.24).

    (рис 8.24) Приложение SimpleCulture. Размер формы — 300х128 пикселей

    Значения свойств Name изменять не будем — наш проект достаточно прост, чтобы тратить на это время. Для кнопки устанавливаем обработчик, закрывающий форму:

    private void button1_Click(object sender, System.EventArgs e)
      {
        this.Close();
      }

    Итак, у нас получилась версия программы с интерфейсом на английском языке. В окне Properties формы устанавливаем свойству Localizable значение True. Это свойство разрешает поддержку многоязычного интерфейса. В свойстве Language выбираем значение English (United States). В выпадающем списке этого свойства доступны практически все языки мира с учетом региона; так, английскому языку соответствует 14 значений. Компилируем приложение. В свойстве Language выбираем Russian (Russia). Изменяем свойство Text элементов, просто удаляя названия на английском языке (рис. 8.25).

    (рис 8.25) Приложение SimpleCulture с интерфейсом на русском языке. Размер формы — 264х208 пикселей

    При изменении значения свойства Language форма теперь меняет пользовательский интерфейс. Обратите внимание на то, что значение Default этого свойства не является тождественным значению English (United States)! В этом можно убедиться, изменив размер формы или текст на кнопке в локальной версии, а затем переключившись на Default. Более того, при разработке интерфейса на нескольких языках следует выполнить основную функциональность приложения в значении Default, а затем заняться его локализацией — при переключении на другие языки интерфейс наследуется только от Default!

    Переходим в код формы. Подключаем пространство имен Threading:

    using System.Threading;

    В конструкторе формы до (!) InitializeComponent устанавливаем культуру пользовательского интерфейса равной текущей культуре:

    public Form1()
        
    {
      Thread.CurrentThread.CurrentUICulture = 
      Thread.CurrentThread.CurrentCulture;
      InitializeComponent();
      }

    Под культурой понимается язык и регион, под текущей культурой — соответствующие настройки инструмента "Язык и региональные параметры". Запускаем приложение. Среда CLR проверяет установленный язык и выводит приложение с русским интерфейсом. Закрываем его, переходим в "Панель управления" и устанавливаем язык "Английский (США)" на вкладке "Региональные параметры" в настройках инструмента "Язык и региональные параметры". Снова запускаем приложение. Теперь интерфейс приложения — на английском языке.

    При локализации приложения среда Visual Studio .NET создает сборку, в которой хранятся все данные о приложении. В окне Solution Explorer нажимаем на кнопку (Show All Files) для просмотра добавленных файлов (рис. 8.26).

    (рис 8.26) Добавление сборок при локализации приложения

    Названия файлов-ресурсов (Form1. en-US и Form1.ru-RU) содержат в себе указание на язык (первая часть – en или ru) и регион (вторая часть US или RU). При создании собственных файлов-ресурсов следует придерживаться этого правила.

    Область Windows Form Designer generated code также изменяется — теперь в ней содержатся свойства элементов, извлекаемые из сборок.

    На диске, прилагаемом к книге, вы найдете приложение SimpleCulture (Code\Glava8\SimpleCulture).

    Пользовательский выбор языка. Перевод сообщений приложения

    В рассмотренном примере меняется пользовательский интерфейс, представляющий собой значения свойства Text элементов управления. Между тем в приложениях используются текстовые сообщения, определяемые в коде, например, в лекции 2 в приложении Notepad C# при попытке закрыть измененный документ появлялось окно-предупреждение Do you want save changes in NameDocument?. Рассмотрим перевод сообщений приложения и пользовательское изменение интерфейса. Скопируем проект TextEditor из лекции 2. В классе формы добавляем переменные для сохранения документа:

    public bool IsSaved = false;
    public string fileName;

    Создаем метод Save, в который вставляем вырезанный обработчик пункта меню mnuSave:

    public void Save(object sender, System.EventArgs e)
      {
        //Показываем диалог выбора файла
        saveFileDialog1.ShowDialog();
        // В качестве имени сохраняемого файла устанавливаем переменную fileName
         fileName=saveFileDialog1.FileName;
        //Создаем поток fs и открываем файл для записи.
        FileStream filestream = File.Open(fileName, FileMode.Create, FileAccess.Write);
        //Проверяем,  открыт ли поток,  и если открыт, выполняем условие
        if(filestream != null)
        {
          //Создаем объект streamwriter и связываем его с потоком filestream
          StreamWriter streamwriter = new StreamWriter(filestream);
          //Записываем данные из TextBox в файл
          streamwriter.Write(txtBox.Text);
          //Переносим данные из потока в файл
          streamwriter.Flush();
          //Закрываем поток
          filestream.Close();
          IsSaved = true;
        }
      }

    В обработчике меню mnuSave вызываем этот метод:

    private void mnuSave_Click(object sender, System.EventArgs e)
      {
        this.Save( fileName, e);
      }

    Добавляем обработчик события Closing формы:

    private void Form1_Closing(object sender, System.ComponentModel.CancelEventArgs e)
      {
        //Если переменная IsSaved имеет значение true, т. е. документ новый документ 
      //был сохранен (Save As) или в открытом документе были сохранены изменения (Save), 
      то выполняется условие
        if(IsSaved ==true)
          //Появляется диалоговое окно, предлагающее сохранить документ.
          if  (MessageBox.Show("Do you want to save changes in this document?", 
            "Message", MessageBoxButtons.YesNo, 
            MessageBoxIcon.Question) == DialogResult.Yes)
            //Если была нажата  кнопка Yes, вызываем метод Save
          {
            this.Save( fileName, e);
          }  
      }

    Запускаем приложение. Теперь при попытке закрыть измененный документ появляется окно-предупреждение. Закрываем приложение, переключаемся в режим дизайна и добавляем следующие пункты меню (рис. 8.27):

    Name Text
    mnuLanguage Language
    mnuEnglish English
    mnuRussian Русский
    (рис 8.27) Пункт главного меню Language

    Устанавливаем свойству Localizable формы значение True, в свойстве Language выбираем язык English (United States). Компилируем приложение, в свойстве Language выбираем язык Russian (Russia). Переводим пункты меню на русский язык:

    Name Text
    mnuFile Файл
    mnuOpen Открыть
    mnuSave Сохранить
    mnuLanguage Язык
    mnuEnglish English
    mnuRussian Русский

    В окне Solution Explorer щелкаем правой кнопкой на названии проекта TextEditor и добавляем новый файл — Add/Add New Item… . В появившемся окне выбираем шаблон Assembly Resource File и называем его ClosingText.en-US.resx (рис. 8.28).

    (рис 8.28) Файл Assembly Resource File

    Проделаем эту операцию еще раз, новый шаблон назовем ClosingText.ru-RU.resx. Мы добавили эти файлы для хранения в них текстовых переменных, используемых приложением для различных локализаций. Откроем ресурс ClosingText.en-US.resx и введем переменную MessageText, в значении value которой укажем текст Do you want to save changes in this document?, выводимый приложением при закрытии (рис. 8.29).

    (рис 8.29) Переменная MessageText в ресурсе ClosingText.en-US.resx

    Аналогично, в ресурсе ClosingText.ru-RU.resx создадим такую же переменную, в значении которой укажем текст на русском языке: "Вы хотите сохранить изменения в документе?" (рис. 8.30).

    (рис 8.30) Переменная MessageText в ресурсе ClosingText.ru-RU.resx

    Переходим в код формы, подключаем следующие пространства имен:

    //Пространство имен, используемое для определения культуры
    //приложения и операционной системы
    using System.Globalization;
    //Пространство, используемое для работы с файлами ресурсов .resx,
    //такими как ClosingText.en-US.resx, ClosingText.ru-RU.resx.
    using System.Resources;
    //Пространство для работы со сборками, более подробно о них см. лекцию 9.
    using System.Reflection;
    using System.Threading;

    В классе формы объявляем следующие переменные и объекты:

    //Переменная выбора, необходимая для определения культуры 
    public string CultureDefine;
    //Переменная для хранения английской культуры
    private  string EnglishCulture;
    //Переменная для русской культуры.
    private  string RussianCulture;

    Для управления ресурсами используется класс ResourceManager, который позволяет извлекать значения переменных, созданных в файле-ресурсе. Общая схема использования этого класса:

    ResourceManager resourceManager = new  ResourceManager
    ("ПространствоИмен.НазваниеРесурса", Assembly.GetExecutingAssembly());

    Для использования извлекаемой строковой переменной обращаемся к ее имени в ресурсе:

    MessageBox.Show(resourceManager.GetString("ИмяПеременнойвРесурсе");

    Возвращаемся к нашему листингу:

    //Создаем экземпляр resourceManager класса ResourceManager
     ResourceManager resourceManager;

    В конструкторе формы извлекается текстовая переменная из заданного ресурса:

    public Form1()
     {
        
     InitializeComponent();
     //Инициализируем переменные
     EnglishCulture = "en-US";
     RussianCulture = "ru-RU";
     // Перменной CultureDefine присваиваем значение культуры, установленной на компьютере, 
     //используя свойство класса ResourceManager
     CultureDefine = CultureInfo.InstalledUICulture.ToString();
     // Создаем новый объект resourceManager, извлекающий из сборки 
     //текстовую переменную ClosingText
     resourceManager = new ResourceManager("TextEditor.ClosingText", Assembly.GetExecutingAssembly());
          
     }

    Перегружаем конструктор формы:

    public Form1(string FormCulture)
     {
        
     InitializeComponent();
     EnglishCulture = "en-US";
     RussianCulture = "ru-RU";
     //В качестве культуры устанавливаем значение CultureDefine
     CultureDefine = FormCulture;
     // Создаем новый объект resourceManager, извлекающий из сборки 
     //текстовую переменную ClosingText
     resourceManager = new ResourceManager("TextEditor.ClosingText", Assembly.GetExecutingAssembly());
      
     }

    Окно-предупреждение появляется при наступлении события формы Closing. Заменяем строку Do you want to save changes in this document? на извлекаемую переменную MessageText файла ресурса (выделено цветом):

    private void Form1_Closing(object sender, System.ComponentModel.CancelEventArgs e)
     {
    …
    
      if(MessageBox.Show(resourceManager.GetString("MessageText"), 
      "Message", MessageBoxButtons.YesNo, 
      MessageBoxIcon.Question) == DialogResult.Yes)
    
    …
     }

    Добавляем возможность изменения языка при выборе определенного пункта меню. Создаем обработчик пункта меню mnuEnglish:

    private void mnuEnglish_Click(object sender, System.EventArgs e)
      {
      //Устанавливаем английскую культуру в качестве выбранной.
      CultureDefine = EnglishCulture;
      // Устанавливаем выбранную культуру в качестве культуры  пользовательского интерфейса 
      Thread.CurrentThread.CurrentUICulture = new CultureInfo(CultureDefine, false);
      // Устанавливаем в качестве текущей культуры выбранную
      Thread.CurrentThread.CurrentCulture = new CultureInfo(CultureDefine, false);
      //Создаем новый экземпляр frm формы Form1:
      Form1 frm = new Form1(CultureDefine);
      //Скрываем текущий экземпляр
      this.Hide();
      //Вызываем новый экземпляр
      frm.Show();
    }

    Обработчик пункта меню mnuRussian аналогичен, только в качестве выбранной устанавливается русская культура:

    private void mnuRussian_Click(object sender, System.EventArgs e)
      {
      CultureDefine = RussianCulture;
      Thread.CurrentThread.CurrentUICulture = new CultureInfo(CultureDefine, false);
      Thread.CurrentThread.CurrentCulture = new CultureInfo(CultureDefine, false);
      Form1 frm = new Form1(CultureDefine);
      this.Hide();
      frm.Show();
      }

    Запускаем приложение. При изменении языка текущая форма скрывается, вместо нее появляется новая форма с нужным интерфейсом. При попытке закрыть форму с изменениями в сохраненном документе текст в окне предупреждения появляется на выбранном языке (рис. 8.31 и 8.32).

    (рис 8.32) Русская версия приложения(рис 8.31) Английская версия приложения

    При закрывании видимой формы остаются запущенными скрытые копии. Для полного завершения работы с приложением в событии Closed формы Form1 создадим процедуру выхода:

    private void Form1_Closed(object sender, System.EventArgs e)
     {
       Application.Exit();
     }

    Другие текстовые переменные, например, заголовок Message, также могут быть без труда локализованы при добавлении их в файлы ресурсов (рис. 8.33).

    (рис 8.33) Для перевода заголовка была добавлена переменная ItemText в файлы ресурсов

    На диске, прилагаемом к книге, вы найдете приложение TextEditor (Code\Glava8\TextEditor).

    Форматированный вывод строк

    На вкладке "Региональные параметры" инструмента "Язык и региональные стандарты" вы могли заметить группу числовых и денежных форматов. В приложениях может потребоваться специальное определение заданного формата, например, вывод результата в рублях или долларах. Рассмотрим это на практике. Создайте новое консольное приложение и назовите его FormatOutput. Весь дальнейший код будем писать внутри блока try…catch:

    try 
      {
        //Дальнейший код…
      }
    catch (Exception ex)
      {
      Console.WriteLine(ex.Message);
      }

    Для начала разберемся с конструкцией, которую вы наверняка много раз встречали:

    int i = 15;
    Console.WriteLine("{0}", i);

    При запуске на экран выведется число 15. Зачем так писать? Не проще ли вывести на экран это число следующим образом:

    int i = 15;
    Console.WriteLine( i);

    Результат будет в точности таким же! Дело в том, что сами скобки и числа в них ({0}, {1}) — так называемые подстановочные знаки, позволяющие легко добиваться более сложного вывода на экран, например, такого:

    int x = 23, y = –4, z = 5, j = 20, v = 40;
    Console.WriteLine ("переменная x = {0}, переменная y = {1}, 
    переменная z = {2}, переменная j = {3}, 
    переменная v = {4}", x, y, z, j, v);

    Результатом будет:

    переменная x = 23, переменная y = –4, переменная z = 5, 
    переменная j = 20, переменная v = 40

    Опять-таки, такой же результат можно получить другим способом:

    Console.WriteLine("переменная " + x);
    Console.WriteLine("переменная " + y);
    Console.WriteLine("переменная " + z);
    Console.WriteLine("переменная " + j);
    Console.WriteLine("переменная " + v);

    Использование подстановочных знаков здесь, несомненно, является оправданным.

    Для вывода в определенном формате подстановочные знаки с параметрами оказываются просто незаменимыми. Некоторые параметры подстановочных знаков:

  • d — десятичный формат. Позволяет задать общее количество знаков (при необходимости число дополняется слева нулями).
    int a = 38;
      //Результат  0038
      Console.WriteLine("a={0:d4}", a);
  • f — формат с фиксированной точностью. Позволяет задать количество знаков после запятой.
    double pi = 3.1415926;
      //Результат 3.14
      Console.WriteLine("pi={0:f2}", pi);
  • x — шестнадцатеричный формат.
    int b = 255;
      //Результат FF.
      Console.WriteLine("b={0:X}", b);
    int c = 255;
      //Результат ff.
      Console.WriteLine("c={0:x}", c);
  • c — денежный формат (добавляет знак доллара и показывает два знака после запятой).
    double d = 1003.214;
      //Результат $1, 003.14 в английской версии Windows (или при выборе 
      //английского языка (США) на вкладке "Региональные параметры" инструмента 
      //"Язык и региональные параметры")
      //1 003,14 р. в русской.
    Console.WriteLine("d={0:c}", d);
  • e — вывод числа в экспоненциальной форме.
    double e = 213.1;
      //Результат 2.131000e+002
      Console.WriteLine("e={0:e}", e);
  • На диске, прилагаемом к книге, вы найдете приложение FormatOutput (Code\Glava8\ FormatOutput)

    Специальные возможности

    Операционная система Windows предоставляет способы работы пользователям с ограниченными возможностями. Экранный диктор — одна из специальных утилит системы — произносит вслух заголовки программ, названия элементов управления, помогая ориентироваться людям с частичной или полной потерей зрения. Для запуска этой утилиты в меню "Пуск" выбираем команду "Выполнить" (Эквивалентное сочетание клавиш Windows+R) и вводим в строке narrator. Запущенный диктор объявляет о событиях на экране, читает вслух печатаемые символы, правда, только на английском языке.

    Некоторые свойства элементов управления были созданы именно для поддержки специальных возможностей. Скопируйте приложение Calculator из лекции 1. Значение свойства AccessibleName определяет текст, произносимый экранным диктором. Устанавливаем следующие значения этого свойства элементам управления, размещенным на форме:

    Свойство Name элементаСвойство AccessibleName элемента
    txtOutput Display
    btn0 zero
    btn1 one
    btn2 two
    btn3 three
    btn4 four
    btn5 five
    btn6 six
    btn7 seven
    btn8 eight
    btn9 nine
    btnChangesign change sign
    btnpoint point
    btn_delenie divide
    btn_umnojenie multiply
    btn_minus minus
    btn_plus plus
    btn_sbros reset
    btn_ravno equal

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

    Другие специальные свойства, такие как AccessibleDescription и AccessibleRole, применяемые гораздо реже, также могут быть использованы для разработки специализированных приложений. Подробное описание их см. в MSDN.

    На диске, прилагаемом к книге, вы найдете приложение Calculator с поддержкой свойства AccessibleName. (Code\Glava8\Calculator).

    Вернуться к учебному плану