RUS_-_Karejev_-_Razrabotka_Windows-prilozhenij
.pdf
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;
}
}
Листинг 8.1.
В обработчике меню 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.2.
Запускаем приложение. Теперь при попытке закрыть измененный документ появляется окно-предупреждение. Закрываем приложение, переключаемся в режим дизайна и добавляем следующие пункты меню (рис. 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());
}
Листинг 8.3.
Перегружаем конструктор формы:
public Form1(string FormCulture)
{
InitializeComponent(); EnglishCulture = "en-US"; RussianCulture = "ru-RU";
//В качестве культуры устанавливаем значение CultureDefine CultureDefine = FormCulture;
// Создаем новый объект resourceManager, извлекающий из сборки //текстовую переменную ClosingText
Рис. 8.32. Английская версия приложения
При закрывании видимой формы остаются запущенными скрытые копии. Для полного завершения работы с приложением в событии 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).
1) Подробнее о предупреждениях и ошибках см. в следующем разделе справки HTML Help Workshop: Creating Help/Compile and Test Help/Compile a Help Project/Compiler messages.
© 2003-2007 INTUIT.ru. Все права защищены.
Интернет-Университет Информационных Технологий http://www.INTUIT.ru
Создание Windows-приложений на основе Visual C#
9. Лекция: Создание пакетов установки: версия для печати и PDA
Сборки. Утилита ildasm.exe. Частные сборки. Сборки со строгим именем. Защита сборок. Утилита ilasm.exe. Утилита .NET Reflector. Вскрытие защищенных сборок. Глобальный кэш сборок GAC (Global Assembly Cache). Утилита gacutil.exe. Настройка политики выполнения сборок и контроля версий. Управление политиками сборок. Файлы конфигурации приложения. Создание пакетов установки с библиотекой .NET Framework и без нее. Изменение каталога установки. Добавление ключей реестра на компьютер пользователя. Добавление публичных сборок в GAC. Библиотеки для работы приложения — MDAC, Jet и Crystal Reports. Изменение пользовательского интерфейса установочного пакета. Использование данных, получаемых при установке. Создание автозагрузочного диска
Для работы с данной лекцией используйте примеры.
Для установки на компьютер большинства программ достаточно просто вставить компакт диск с программой в дисковод и, следуя несложным инструкциям, скопировать ее на жесткий диск. В результате мы получаем возможность запускать программу одним из нескольких способов — щелкая на ярлыке на Рабочем столе, выбирая ее группу в меню Пуск или просто дважды щелкая на файле, расширение которого связано с этой программой. Мы не задумываемся, из каких частей состоит программа, как они взаимодействуют, а некоторые пользователи даже не представляют, где эти части находятся. В этой лекции мы научимся создавать дистрибутивы, или пакеты установки, предоставляющие возможность распространять программы с минимумом усилий со стороны конечного пользователя.
Сборки. Утилита ildasm.exe
Приложение всегда состоит из одной или более сборок. Сборка — это функциональная единица, имеющая версию и описание, которую можно использовать в других приложениях. Для каждой сборки можно прописывать отдельные разрешения (подробнее о разрешениях см. лекцию 10).
В самом простом случае, сборка — это приложение, которое состоит из одного функционального модуля — класса. В большинстве случаев в приложении может быть несколько сборок, и каждая может иметь свои вспомогательные файлы. При выполнении все сборки приложения должны существовать и к ним должен быть открыт доступ. Каждая сборка должна быть независимой. У любой сборки есть метаданные, которые описывают сборку и содержат версию.
Содержимое сборки можно просмотреть, запустив дизассемблер "Microsoft Intermediate Language Disassembler" (ildasm.exe).
Рассмотрим следующий пример — создадим простое консольное приложение, которое выводит на экран строку Hello World:
using System;
namespace SimpleApp
{
class Class1
{
[STAThread]
static void Main(string[] args)
{
Console.WriteLine("Hello World");
}
}
}
Утилиту ildasm.exe можно запустить двумя способами — перейти по адресу C:\Program Files\Microsoft Visual Studio .NET 2003\SDK\v1.1\Bin и запустить непосредственно файл ildasm.exe или перейти в Пуск\Все программы\ Microsoft Visual Studio .NET 2003 \ Visual Studio .NET Tools \ Visual Studio .NET 2003 Command Prompt и в появившейся командной строке ввести
ildasm.exe
После того как приложение запустится, откроем только что созданную сборку (файл SimpleApp.exe из папки bin/Debug), (рис. 9.1).
Рис. 9.1. Сборка SimpleApp, открытая с помощью утилиты ildasm.exe
Как мы знаем, у класса всегда есть конструктор. Если он не был создан вручную, компилятор создаст конструктор по умолчанию. В утилите он называется .ctor. Также в созданной нами программе есть метод Main, который принимает строковый массив и не возвращает значений. Щелкаем на методе Main два раза. Открывается окно с MSIL (Microsoft Intermediate Language) кодом этого метода. Здесь видим строковую переменную ldstr со значением "Hello World" и запуск статического метода WriteLine класса Console (рис. 9.2).
увеличить изображение
Рис. 9.2. MSIL-код метода Main
На рис. 9.2 я снова привел окно утилиты ildasm.exe: щелкнув на кнопку прокрутки, замечаем номер версии сборки —
1.0.2300.26912.
Частные сборки
Программы, которые написаны на языках, поддерживаемых библиотекой .NET Framework, и на C# в частности, компилируются в код MSIL, которые затем среда CLR (Common Language Runtime) преобразует в машинный код.
Частные сборки отвечают тем же требованиям, что и обычные, но используются они, как правило, только в одном приложении. При этом файл сборки может находиться в корневой или вложенных папках корневого каталога, используемого приложением. Приложение связывается со сборкой по ее частному имени, содержащемуся в коде MSIL. Среда CLR, использующая код MSIL, ищет частную сборку по ее имени.
Частные сборки отвечают тем же требованиям, что и обычные, но предназначены они для использования только в одном приложении и, как правило, лежат в той же папке, что и использующее их приложение. Частная сборка может находиться не только в корневой папке, но и во вложенных папках корневого каталога. Приложение ссылается на частную сборку по ее частному имени, которое содержится в метаданных. Когда среда CLR ищет частную сборку для применения, она использует частное имя сборки для поиска, причем поиск осуществляется в корневом каталоге и дочерних подкаталогах. Среда не будет искать сборку в родительской папке каталога.
Если мы хотим использовать любой путь для размещения сборки, то следует воспользоваться методом LoadFrom класса Assembly и указать ему адрес нахождения файла со сборкой. Класс Assembly находится в пространстве имен System.Reflection. Создайте новое консольное приложение и назовите его SimpleAssembly. Удалите все фрагменты кода, оставив только следующий участок:
using System;
namespace SimpleAssembly
{
public class Class
{
public static string HelloWorld()
{
return "hello world";
}
}
}
Скомпилировав приложение (Ctrl+Shift+B), мы получим сборку SimpleAssembly.dll. Теперь создадим еще одно консольное приложение — UsingLoadFrom, в папку bin/Debug которого помещаем файл SimpleAssembly.dll. В методе LoadFrom считываем
содержимое сборки SimpleAssembly.dll:
using System;
using System.Reflection;
namespace UsingLoadFrom
{
class Class1
{
[STAThread]
static void Main(string[] args)
{
Assembly privateAss = Assembly.LoadFrom("SimpleAssembly.dll");
MethodInfo info = privateAss.GetTypes()[0].GetMethod("HelloWorld");
Object obj = info.Invoke(null, null); Console.WriteLine("Результат выполнения метода: {0}",
obj);
}
}
}
