Книга: Системное программирование в среде Windows

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

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

Функция ConsolePrompt, входящая в программу 2.1, является полезной утилитой, которая выводит на консоль заданное сообщение и возвращает ответ пользователя на него. Данная утилита предусматривает возможность подавления эхо-отображения ответной информации, полученной от пользователя. В указанной функции используются функции консольного ввода/вывода и обобщенные символы. Двумя другими точками входа в этом модуле являются функции Print-Strings и PrintMsg; эти функции допускают использование любого дескриптора, однако обычно они применяются совместно с дескрипторами устройств стандартного вывода информации и стандартного вывода сообщений об ошибках. В первой функции разрешается использовать список аргументов переменной длины, тогда как во второй в качестве аргумента можно задавать только одну строку, что в некоторых случаях может оказаться удобнее. Для обработки списка аргументов переменной длины функция PrintStrings использует функции va_start, va_arg и va_end стандартной библиотеки С.

Описанные функции, а также функции из обобщенной библиотеки С будут привлекаться для использования в приводимых в данной книге примерах программ при всякой удобной возможности. 

Примечание

Коды программ, находящиеся на Web-сайте книги, содержат подробные комментарии и тщательно документированы, тогда как в самой книге большинство комментариев с целью сокращения места были опущены, и основное внимание в ней уделяется использованию Windows.

Следует также отметить, что в примере вводится заголовочный файл Envirmnt.h (его код приведен в приложении А и предоставлен на Web-сайте книги), который должен использоваться совместно со всеми приводимыми в книге программами. Этот файл содержит определения символических констант UNICODE и _UNICODE (сами определения "закомментированы"; при компоновке приложений, предназначенных для работы с символами стандарта Unicode, символы комментариев следует удалить), а также необходимых макропеременных, учитывающих особенности окружения. В заголовочных файлах, находящихся на Web-сайте, определены также дополнительные модификаторы, которые обеспечивают импортирование и экспортирование имен функций, а также гарантируют соблюдение соответствующих соглашений о вызове функций.

Программа 2.1. PrintMsg: вспомогательные функции вывода на консоль сообщений и ожидания ответа от пользователя 

/* PrintMsg.с: ConsolePrompt, PrintStrings, PrintMsg */
#include "Envirmnt.h" /* В этом файле устанавливаются директивы #define и #undef для UNICODE. */
#include <windows.h>
#include <stdarg.h>
BOOL PrintStrings (HANDLE hOut, ...)
/* Запись сообщений в буфер экрана консоли. */
{
 DWORD MsgLen, Count;
 LPCTSTR pMsg;
 va_list pMsgList; /* Строка текущего сообщения. */
 va_start (pMsgList, hOut); /* Начать обработку сообщений. */
 while ((pMsg = va_arg(pMsgList, LPCTSTR)) != NULL) {
  MsgLen = _tcslen(pMsg);
  /* Функция WriteConsole может применяться только с дескриптором буфера экрана консоли. */
  if (!WriteConsole(hOut, pMsg, MsgLen, &Count, NULL)
      /* Функция WriteFile вызывается только в случае неудачного завершения функции WriteConsole. */
      && !WriteFile(hOut, pMsg, MsgLen * sizeof (TCHAR), &Count, NULL)) return FALSE;
 }
 va_end(pMsgList);
 return TRUE;
}
BOOL PrintMsg(HANDLE hOut, LPCTSTR pMsg)
/* Версия PrintStrings для вывода одиночного сообщения. */
{
 return PrintStrings(hOut, pMsg, NULL);
}
BOOL ConsolePrompt(LPCTSTR pPromptMsg, LPTSTR pResponse, DWORD MaxTchar, BOOL Echo)
/* Вывести на консоль подсказку для пользователя и получить от него ответ. */
{
 HANDLE hStdIn, hStdOut;
 DWORD TcharIn, EchoFlag;
 BOOL Success;
 hStdIn = CreateFile(_T("CONIN$"), GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
 hStdOut = CreateFile(_T("CONOUT$"), GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
 EchoFlag = Echo ? ENABLE_ECHO_INPUT : 0;
 Success = SetConsoleMode(hStdIn, ENABLE_LINE_INPUT | EchoFlag | ENABLE_PROCESSED_INPUT) &&
           SetConsoleMode (hStdOut, ENABLE_WRAP_AT_EOL_OUTPUT | ENABLE_PROCESSED_OUTPUT) &&
           PrintStrings (hStdOut, pPromptMsg, NULL) &&
           ReadConsole (hStdIn, pResponse, MaxTchar, &TcharIn, NULL);
 if (Success) pResponse [TcharIn – 2] = '';
 CloseHandle (hStdIn);
 CloseHandle (hStdOut);
 return Success;
}

Обратите внимание, что при вычислении возвращаемого функцией значения булевской переменной Success, которое служит индикатором успешности выполнения, в программе, с выгодой для логики ее работы, используется тот факт, что стандартом ANSI С гарантируется так называемое "сокращенное" вычисление логических выражений в направлении слева направо; поэтому, как только при вычислении части выражения, расположенной слева от любой из операций логического "и" (&&), в качестве результата будет получено значение FALSE, остальная часть выражения, расположенная справа от данной операции, вычисляться не будет, поскольку результат вычисления всего выражения в целом оказывается предопределенным. Данный стиль написания программ может показаться чересчур компактным, однако он обладает тем преимуществом, что позволяет организовать логически стройную и понятную последовательность системных вызовов, не загромождая программу многочисленными операторами условных переходов. Для получения более подробной информации о возможных ошибках можно воспользоваться функцией GetLastError. Распространенный в Windows возврат функциями логических значений поощряет подобную практику.

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

В программном коде используется тот документированный факт, что при использовании функции WriteConsole вместе с дескриптором, который не является дескриптором консоли, ее выполнение будет завершено с ошибкой. В связи с этим предварительный запрос свойств дескриптора не является обязательным. Функция воспользуется консольным режимом лишь в том случае, если указанный в ее вызове дескриптор действительно связан с консолью.

Кроме того, функция ReadConsole возвращает управляющие символы возврата каретки и перехода на новую строку, что диктует необходимость вставки дополнительных нулевых символов после символов возврата каретки в соответствующих местах.

Оглавление книги


Генерация: 1.144. Запросов К БД/Cache: 3 / 1
поделиться
Вверх Вниз