Системное программирование в среде Windows
Шрифт:
Стратегии использования символов Unicode
Приступая к работе над проектом в Windows, либо для разработки нового программного кода, либо для переноса существующего, программист, в зависимости от требований проекта, может выбрать одну из четырех стратегий.
1. Только 8-битовые символы. Игнорируйте Unicode и продолжайте использовать для таких функций, как printf, atoi и strcmp, типы данных char (или CHAR) и стандартную библиотеку С.
2. 8-битовые символы, но с возможностью использования символов Unicode. Следуйте ранее данным рекомендациям в отношении обобщенных приложений, но не определяйте константы UNICODE и _UNICODE директивами препроцессора. В приведенных
3. Только символы Unicode. Следуйте рекомендациям в отношении обобщенных приложений, но при этом определите директивами препроцессора обе константы UNICODE и _UNICODE. Другой возможный вариант состоит в том, чтобы использовать исключительно расширенную форму символов и функций для работы с символами. Результирующие программы не смогут правильно выполняться под управлением Windows 9x.
4. Символы Unicode и 8-битовые символы. Программа ориентируется на работу как с символами Unicode, так и с ASCII-символами, причем решение относительно того, какие участки программного кода должны работать, принимается программой на стадии выполнения с использованием переключателей времени выполнения или других возможных средств.
Как уже отмечалось ранее, несмотря на то что написание обобщенного кода требует дополнительных усилий, а результирующая программа становится менее удобочитаемой, эта мера позволяет программисту добиться максимальной гибкости приложения.
Параметры локализации могут устанавливаться во время выполнения программы. В программе 2.2 показано, как определить язык, который должен использоваться в сообщениях об ошибках.
Стандарт локализации приложений POSIX XPG4, предоставляемый многими поставщиками UNIX, существенно отличается от стандарта Unicode. Помимо всего прочего, символы в этом стандарте могут представляться 4, 3 или 1 байтами в зависимости от контекста, особенностей локализации и так далее.
Microsoft С реализует функции стандартной библиотеки С, среди которых имеются также версии, рассчитанные на работу с символами в расширенной форме. Так, заголовочный файл <wchar.h> содержит описание функции _tsetlocale. В Windows NT используются символы Unicode, тогда как в Windows 9x используются те же многобайтовые символы (смесь 8– и 16-битовых символов), что и в Windows 3.1.
Стандартные устройства и консольный ввод/вывод
Как и в UNIX, в Windows предусмотрены три стандартных устройства, предназначенные, соответственно, для ввода данных (input), вывода данных (output) и вывода сообщений об ошибках (error). В UNIX для этих устройств используются известные системе значения дескрипторов файлов (0, 1 и 2), однако в Windows доступ к стандартным устройствам осуществляется с помощью дескрипторов типа HANDLE, для получения которых предоставляется специальная функция.
Возвращаемое значение: в случае успешного выполнения — действительный дескриптор, иначе — значение INVALID_HANDLE_VALUE.
Параметр nStdHandle должен принимать одно из следующих значений:
В качестве стандартных устройств обычно назначаются консоль и клавиатура. Стандартный ввод/вывод можно перенаправлять на другие устройства.
Вызов функции GetStdHandle не приводит к созданию новых или дублированию существующих дескрипторов стандартных устройств. Последовательные вызовы с указанием в качестве аргумента одного и того же устройства будут возвращать одно и то же значение дескриптора. Закрытие дескриптора стандартного устройства делает это устройство недоступным для дальнейшего использования. По этой причине
в примерах ниже мы будем часто открывать дескриптор стандартного устройства, но не закрывать его.Возвращаемое значение: в случае успешного выполнения — TRUE, иначе — FALSE.
Допустимые значения параметра nStdHandle функции SetStdHandle являются теми же, что и в случае функции GetStdHandle. Параметр hHandle указывает открытый файл, который назначается в качестве стандартного устройства.
Одним из методов перенаправления стандартного ввода/вывода является последовательный вызов функций SetStdHandle и GetStdHandle. Полученный в результате этого дескриптор используется в последующих операциях ввода/ вывода.
Для указания путей доступа к консольному вводу (клавиатуре) и консольному выводу предусмотрены два зарезервированных имени: "CONIN$" и "CONOUT$". Роль стандартных устройств ввода, вывода и вывода ошибок первоначально отводится консоли. Однако консоль можно использовать даже после того, как операции ввода/вывода, требующие применения стандартных устройств, будут перенаправлены; для этого требуется лишь открыть дескрипторы для файлов "CONIN$" и "CONOUT$", вызвав функцию CreateFile.
В UNIX стандартный ввод/вывод может быть перенаправлен одним из трех способов (см. [40], стр. 61—64).
Первый метод является косвенным и основывается на том, что функция dup возвращает дескриптор файла с наименьшим доступным номером. Предположим, вы хотите переназначить стандартный ввод (файловый дескриптор 0) открытому файлу, описанному как fd_redirect. Тогда можно записать следующий код:
Во втором методе используется функция dup2, а третий метод предполагает вызов замысловатой перегруженной функции fcntl с использованием в качестве параметра значения F_DUPFD.
Операции консольного ввода/вывода могут выполняться с помощью функций ReadFile и WriteFile, но проще использовать предназначенные специально для этого функции консоли ReadConsole и WriteConsole. Основное преимущество этих функций заключается в том, что они манипулируют не байтами, а обобщенными символами (TCHAR), и, кроме того, обрабатывают символы в соответствии с текущими режимами консоли, которые устанавливаются функцией SetConsoleMode.
Возвращаемое значение: тогда, и только тогда, когда функция завершается успешно — TRUE, иначе — FALSE.
hConsoleHandle — дескриптор буфера ввода консоли или буфера дисплея, который должен быть создан с правами доступа GENERIC_WRITE, даже если устройство предназначено только для ввода информации.
Параметр fdevMode задает способ обработки символов. В имени каждого из его флагов содержится компонент, указывающий, к чему относится данный флаг— к вводу (input) или выводу (output). Ниже перечислены пять обычно используемых флагов, причем все они устанавливаются по умолчанию.
• ENABLE_LINE_INPUT — возврат из функции чтения (ReadConsole) происходит только после считывания символа возврата каретки.
• ENABLE_ECHO_INPUT — эхо-отображение вводимых символов на экране.
• ENABLE_PROCESSED_INPUT — установка этого флага приводит к обработке системой управляющих символов возврата на одну позицию, возврата каретки и перехода на новую строку.
• ENABLE_PROCESSED_OUTPUT — установка этого флага приводит к обработке системой управляющих символов возврата на одну позицию, табуляции, подачи звукового сигнала, возврата каретки и перехода на новую строку.