Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Последние темы форума

Показать новые сообщения »

Почтовая рассылка

Подписчиков: 6314
Последний выпуск: 19.06.2015

Возможности консольных приложений для Windows

Автор: Виталий Рычков
27 апреля 2007 года

В настоящее время, когда у разработчиков программного обеспечения появляется всё больше возможностей для сознания приложений со сложным графическим интерфейсом, консольные приложения по-прежнему прочно удерживают свои позиции, даже в такой, казалось бы им среде, как современная операционная система Windows. Это объясняется в первую очередь простотой их исполнения и некоторыми специфическими особенностями консольных приложений, которые делают их в ряде случаев более подходящими для решения задачи, чем приложения с графическим интерфейсом. Один минус: выглядят такие приложения очень уныло и однообразно, как безликая серая масса букв и цифр на чёрном фоне окна консоли. Но не всё так безнадёжно, как может показаться на первый взгляд. В этой статье я попытаюсь дать несколько полезных рецептов расширения функциональности консольных приложений и придания их внешнему виду большей выразительности.

И так: начнём с заголовка окна консоли. При запуске программы в заголовке окна отображается полное имя файла, с которого было запущено приложение. Вместо имени файла, в заголовке окна можно указать любой другой текст: название приложения, например. Это делается с помощью функции SetConsoleTitle.

::SetConsoleTitle(_T("Пример программы на C++"));

Далее рассмотрим проблему с выводом на консоль текста кириллицы. Практически каждому программисту когда-нибудь приходилось с этим сталкиваться. По сложившейся традиции, для вывода текста на консоль в большинстве примеров на C++ используются функции стандартной библиотеки, такие как printf или puts, которые работают с текстом в кодировке OEM, что соответствует кодовой странице 866 для русского языка. То же самое происходит при использовании потока вывода cout. Но проблема в том, что большинство текстовых редакторов для Windows работают с текстом в кодировке ANSI, что для русского языка соответствует кодовой странице 1251.

Как решить эту проблему? Проще всего использовать функции, которые записывают текст непосредственно в буфер консоли, а не в стандартный поток. Для этого нужно в программный код включить заголовочный файл CONIO.H и, вместо функций printf и puts, вызывать аналогичные функции _cprintf и _cputs.

Так они выглядят в коде на Visual C++:

      _cputts(_T("Всем привет от меня!\r\n"));
      _tcprintf(_T("%s\r\n"), _T("Благодарю за внимание."));

Несложно написать и собственную процедуру вывода текста на консоль с использованием системной функции WriteConsole. Вот пример такой процедуры:

BOOL PrintText(LPCTSTR szText)
{
      static HANDLE hConsole = ::GetStdHandle(STD_OUTPUT_HANDLE);
      //
      DWORD dw(0);
      return ::WriteConsole(hConsole, szText, ::lstrlen(szText), &dw, NULL);
}

А вот так она используется:

PrintText(_T("Всем пока...\r\n"));

Как вы уже наверно заметили, для перевода строки необходимо указывать последовательность из двух символов: "\r\n", в отличие от стандартного потока, где указывается лишь один символ '\n'. Но бывает и так, что нужно вывести текст именно через стандартный поток, чтобы его можно было перенаправить в текстовый файл или в другое консольное приложение. Для этого текст нужно перевести в другую кодировку с помощью функции CharToOem. Или использовать функцию WideCharToMultiByte с параметром CP_OEMCP, если ваш текст в кодировке UNICODE.

Размер буфера консоли по умолчанию равен 80х300, т.е. 300 строк по 80 символов каждая. Задать буферу консоли другой размер можно при помощи функции SetConsoleScreenBufferSize.

Атрибутами текста консоли являются: цвет символов и цвет заднего фона. Код атрибута соответствует числовому значению в диапазоне от 0x00 до 0x7F. Так выглядит таблица с числовыми значениями атрибутов текста в шестнадцатеричном коде:

00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F
60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F
70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F

Функция SetConsoleTextAttribute задаёт выводимому тексту указанный атрибут. Для задания всему окну консоли указанных атрибутов применяется функция FillConsoleOutputAttribute.

Позиционирование текста (т.е. установка курсора на позицию с заданными координатами) производится с помощью функции SetConsoleCursorPosition.

Полный код моего примера в Visual C++ 2005 выглядит так:

#include "stdafx.h"
#include <conio.h>


BOOL PrintText(LPCTSTR szText);
BOOL SetConsoleAttrib(WORD wAttrib);
BOOL SetCurrentPos(SHORT x, SHORT y);
BOOL SetConsoleSize(SHORT x, SHORT y);


int _tmain(int argc, _TCHAR* argv[])
{
      ::SetConsoleTitle(_T("Пример программы на C++"));
      //
      SetConsoleSize(160, 80);
      SetConsoleAttrib(0x6F);
      //
      _cputts(_T("Всем привет от меня!\r\n"));
      _tcprintf(_T("%s\r\n"), _T("Благодарю за внимание."));
      //
      SetCurrentPos(25, 10);
      PrintText(_T("Всем пока...\r\n"));
      //
_gettch(); // ожидание нажатия клавиши...
      return 0;
}

static HANDLE _ConsoleOut = ::GetStdHandle(STD_OUTPUT_HANDLE);

BOOL SetConsoleAttrib(WORD wAttrib)
{
      ::SetConsoleTextAttribute(_ConsoleOut, wAttrib);
      CONSOLE_SCREEN_BUFFER_INFO csbi = {0};
      ::GetConsoleScreenBufferInfo(_ConsoleOut, &csbi);
      DWORD dw(0);
      COORD cr = {0, 0};
      return ::FillConsoleOutputAttribute(_ConsoleOut, 
            wAttrib, csbi.dwSize.X * csbi.dwSize.Y, cr, &dw);
}


BOOL PrintText(LPCTSTR szText)
{
      DWORD dw(0);
      return ::WriteConsole(_ConsoleOut, szText, ::lstrlen(szText), &dw, NULL);
}


BOOL SetCurrentPos(SHORT x, SHORT y)
{
      COORD pos = {x, y};
      return ::SetConsoleCursorPosition(_ConsoleOut, pos);
}


BOOL SetConsoleSize(SHORT x, SHORT y)
{
      COORD size = {x, y};
      return ::SetConsoleScreenBufferSize(_ConsoleOut, size);

} 

Приведённый пример был создан в среде Visual C++ 2005 как проект Win32 Console Application.

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

Благодарю за внимание.

Оставить комментарий

Комментарий:
можно использовать BB-коды
Максимальная длина комментария - 4000 символов.
 

Комментарии

1.
52K
02 сентября 2009 года
Верон
1 / / 02.09.2009
+2 / -3
Мне нравитсяМне не нравится
19 сентября 2009, 21:45:17
Хорошая статья. Не знал, что с помощью VB можно работать с консолью.
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог