Студопедия

КАТЕГОРИИ:

АвтоАвтоматизацияАрхитектураАстрономияАудитБиологияБухгалтерияВоенное делоГенетикаГеографияГеологияГосударствоДомЖурналистика и СМИИзобретательствоИностранные языкиИнформатикаИскусствоИсторияКомпьютерыКулинарияКультураЛексикологияЛитератураЛогикаМаркетингМатематикаМашиностроениеМедицинаМенеджментМеталлы и СваркаМеханикаМузыкаНаселениеОбразованиеОхрана безопасности жизниОхрана ТрудаПедагогикаПолитикаПравоПриборостроениеПрограммированиеПроизводствоПромышленностьПсихологияРадиоРегилияСвязьСоциологияСпортСтандартизацияСтроительствоТехнологииТорговляТуризмФизикаФизиологияФилософияФинансыХимияХозяйствоЦеннообразованиеЧерчениеЭкологияЭконометрикаЭкономикаЭлектроникаЮриспунденкция

Примеры приложений для MVS-2005




Эти примеры взяты из MSDN-2005.

Пример ViewEx – окна с разделителями

 Это приложение иллюстрирует создание окон вида с разделителями (splitter) на этапе выполнения приложения. Класс документа весьма примитивен: он сохраняет только текст и цвет. На рис. 15. показано одно из возможных состояний приложения ViewEx.

 

Рис. 15. Окно приложения ViewEx

 




Пример SnapVw – страница свойств

Этот пример демонстрирует технику использования страницы свойств в классе CFormView. Рамка дочернего окна приложения с многодокументным интерфейсом (MDI) используется вместо вместо property sheet, которая может содержать кнопки OK, Cancel и Apply.

 

 

Рис. 16. Окно приложения SnapVW


Пример DockTool – панели инструментов

Иллюстрирует использование панелей инструментов: создание, перемещение, стыковка, отображение, прятание и т.д. Экземпляры классов панелей создаются и настраиваются в методе ainFrame::OnCreate(). В методе CMainFrame::OnClose() сохраняются текущие настройки приложения в файле инициализации.

 

Рис. 17. Окно приложения DockTool




Консольные приложения Windows

Основные понятия

Этот материал взят из MSDN (см. раздел Consoles and Character-Mode Support)

Консоль (console) предоставляет высокоуровневую поддержку простых приложений, работающих в текстовом (а не в графическом) режиме, которые взаимодействуют с пользователем посредством функций, обеспечивающих ввод из стандартного ввода и вывод в стандартный вывод или стандартный вывод ошибок (standard output or standard error). Консоли также предоставляют современную низкоуровневую поддержку, которая обеспечивает прямой доступ к буферу консоли и позволяет приложениям получать расширенную входную информацию, например, ввод от мыши.

Консоль представляет собой интерфейс, который обеспечивает ввод/вывод для символьных приложений (character-mode applications – приложения, работающие в текстовом режиме).

Консоль имеет один буфер ввода (input buffer) и один или несколько дисплейных буферов (screen buffers). Буфер ввода содержит очередь записей (input records), каждая из которых содержит информацию о событии ввода (input event). Очередь ввода всегда включает события нажатия и отпускания клавиши (key-press and key-release events). Очередь ввода может также включать события от мыши (перемещение мыши, нажатие и отпускание ее клавиш) и события, вызванные воздействиями пользователя на размер активного дисплейного буфера (active screen buffer). Дисплейный буфер представляет собой двумерный массив символов и их атрибутов цвета для вывода в консольное окно.

Консольные функции предоставляют различные уровни доступа к собственно консоли. Высокоуровневые функции ввода/вывода позволяют приложениям читать из стандартного ввода данные, поступающие от клавиатуры и сохраняемые в буфере ввода консоли. Эти функции также позволяют приложению записывать данные в стандартный вывод или стандартный вывод сообщений об ошибках (standard error) для их отображения в дисплейном буфере консоли (in the console's screen buffer). Высокоуровневые функции также поддерживают перенаправление стандартных дескрипторов и управление режимами консоли. Низкоуровневые функции позволяют приложениям получать полную информацию о событиях, поступающих от клавиатуры и мыши, а также о событиях, вызванных взаимодействиями пользователя с консольным окном (например, изменение атрибутов шрифтов). Низкоуровневые функции предоставляют приложениям больший контроль по управлению выводом на экран.

Возможные действия пользователя иллюстрирует рис.1, на котором отображена вкладка «Расположение» окна «Свойства», которое можно вызвать из системного меню любого консольного приложения. Посредством этого окна пользователь может управлять многими параметрами окна консольного приложения, в частности, числом символов в окне и числом строк (ширина и высота окна).

 

 

 

 

Рис. 1. Тема системного меню «Свойства» консольного приложения

 

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

Система создает новую консоль, когда она создает консольный процесс  (console process) – процесс с текстовым (в противоположность графическому) режимом, точкой входа которого является функция main() или _tmain(). Например, система создает новую консоль (new console), когда она запускает командный процессор (command processor – чаще всего переводится как командная строка). Когда командный процессор запускает новый консольный процесс, пользователь может указать, должна ли система содать новую консоль для нового процесса или она должна унаследовать консоль командного процессора. Процесс может создать консоль одним из следующих способов.

Первый способ. Процесс с графическим интерфейсом пользователя (GUI – Graphical User Interface) или консольный процесс, который в текущий момент времени не прикреплен (not currently attached) к консоли, может использовать функцию AllocConsole() для создания новой консоли.

Второй способ. GUI-процесс или консольный процесс может использовать функцию CreateProcess() для создания нового консольного процесса и установить флаг, предписывающий системе создать новую консоль.

Обычно процесс использует функцию AllocConsole() для создания консоли, когда возникает ошибка, требующая взаимодействия с пользователем. Например, GUI-процесс может создать консоль, когда случается такая ошибка, которая делает невозможным использование графического интерфейса или консольный процесс, который не может нормально взаимодействовать с пользователем, может создать новую консоль, если это необходимо для исправления ошибки. Процесс, вызывающий функцию AllocConsole(), не должен быть прикреплен к существующей консоли. Когда создается GUI-процесс, он не прикреплен ни к какой консоли. Консольный процесс не присоединен к консоли, если при вызове функции CreateProcess() для его создания был указан параметр DETACHED_PROCESS (неприкрепленный процесс). Процесс может использовать функцию FreeConsole() для открепления себя от унаследованной консоли или консоли, созданной с помощью AllocConsole().

Третий способ. Процесс может также создать консоль путем указания параметра CREATE_NEW_CONSOLE при вызове функции CreateProcess(). Этот метод создает новую консоль, которая доступна для дочернего процесса, но недоступна для родительского. Раздельные консоли позволяют родительскому и дочернему процессам взаимодействовать с пользователем без конфликтов. Если флаг CREATE_NEW_CONSOLE не был указан при создании консольного процесса, оба процесса присоединяются к одной и той же консоли и в этом случае нет никакой гарантии того, что процесс получит данные, предназначенные именно для него. Приложения могут предотвратить путаницу путем создания дочерних процессов, которые не наследуют дескрипторы входного буфера или путем предоставления монопольного права только дочернему процессу унаследовать дескриптор входного буфера до тех пор, пока он не закончит чтение данных.

Создание новой консоли приводит к появлению как нового консольного окна. так и отдельных буферов ввода/вывода. Процесс, связанный с новой консолью, использует функцию GetStdHandle() для получения дескрипторов дисплейного буфера и буфера ввода. Эти дескрипторы позволяют процессу получить доступ к консоли.

Когда процесс использует функцию CreateProcess(), он может также указать структуру STARTUPINFO, члены которой управляют характеристиками первой новой консоли, созданной для дочернего процесса. Структура STARTUPINFO, указанная в качестве параметра при вызове функции CreateProcess(), оказывает такое же действие, как и указание флага CREATE_NEW_CONSOLE. Тот же результат получается в том случае, если дочерний процесс последовательно вызовет функцию AllocConsole(). В структуре STARTUPINFO могут быть, в частности, указаны такие характеристики консоли:

· размеры (в знакоместах) и положение (в пикселах) окна новой консоли; 

· размер (в знакоместах) дисплейного буфера консоли;

· цветовые атрибуты (цвет символов и фона) дисплейного буфера консоли; 

· имя окна консоли, отображаемое в строке заголовка окна.

 

Если структура STARTUPINFO приложением не определяется, используются значения по умолчанию. Дочерний процесс может использовать функцию GetStartupInfo() для получения значений членов структуры STARTUPINFO.

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

 

Функция Описание
GetConsoleScreenBufferInfo() Возвращает размер окна, буфера и цветовые атрибуты
SetConsoleWindowInfo() Изменяет размер окна консоли
SetConsoleScreenBufferSize() Изменяет размер дисплейного буфера
SetConsoleTextAttribute() Устанавливает цветовые атрибуты
SetConsoleTitle() Устанавливает заголовок окна консоли
GetConsoleTitle() Возвращает заголовок окна консоли

 

Закрытие консоли

Процесс может использовать функцию FreeConsole() для открепления себя от консоли. Если другой процесс разделяет доступ к этой консоли, консоль не будет уничтожена, однако процесс, который себя от нее открепил, не может с ней взаимодействовать. После вызова функции FreeConsole() процесс может создать новую консоль с помощью функции AllocConsole(). Консоль закрывается, когда последний прикрепленный к ней процесс завершается или вызывает FreeConsole().

Дескрипторы консоли

Консольные процессы используют дескрипторы для получения доступа к входному и дисплейным буферам консоли. Процесс может использовать функции GetStdHandle(), CreateFile() или CreateConsoleScreenBuffer() для получения дескрипторов.

Функция GetStdHandle() предоставляет механизм дескрипторов стандартного ввода (STDIN), стандартного вывода (STDOUT) и стандартного потока вывода ошибок (STDERR), ассоциированных с процессом. Эти дескрипторы создаются системой во время создания консоли. Изначально STDIN является дескриптором входного буфера консоли, а STDOUT и STDERR – дескрипторами активного дисплейного буфера. Тем не менее, функция SetStdHandle() может переориентировать стандартные дескрипторы, ассоциированные с STDIN, STDOUT и STDERR. Так как родительские стандартные дескрипторы наследуются любым дочерним процессом, последующие вызовы GetStdHandle() возвращают переориентированный дескриптор. Дескриптор, возвращаемый GetStdHandle(), может, таким образом, ссылаться на нечто отличное от консольного ввода/вывода. Например, перед созданием дочернего процесса, родительский процесс может использовать SetStdHandle() для того, чтобы установить дескриптор некоторого программнного канала (pipe handle) как дескриптор STDIN, который затем и наследуется дочерним процессом. Теперь, когда дочерний процесс вызывает GetStdHandle(), он получает программный канал. Это значит, что родительский процесс может управлять стандартными дескрипторами дочернего процесса. Дескрипторы, возвращаемые GetStdHandle(), имеют доступ GENERIC_READ|GENERIC_WRITE до тех пор, пока SetStdHandle() не будет использована для снижения уровня доступа.

Значения дескрипторов, возвращаемые GetStdHandle(), не будут равны 0, 1 или 2, так как стандартные предопределенные в файле STDIO.H константы потоков (STDIN, STDOUT и STDERR) не могут быть использованы в функциях, которые требуют дескриптора консоли.

Функция CreateFile() позволяет процессу получить дескриптор буфера ввода консоли и активного дисплейного буфера, даже если STDIN и STDOUT были перенаправлены. Для открытия дескриптора входного буфера консоли надо указать значение CONIN$ в вызове CreateFile(), а для открытия активного дисплейного буфера – значение CONOUT$. Функция CreateFile() позволяет Вам определить права чтения/записи дескриптора, кооторый она возвращает.

Функция CreateConsoleScreenBuffer() создает новый дисплейный буфер и возвращает дескриптор, который может быть использован в любой функции, которая принимает дескриптор для консольного вывода. Новый дисплейный буфер будет неактивным до тех пор, пока его дескриптор не будет указан в вызове функции SetConsoleActiveScreenBuffer(). Заметьте, что изменение активного дисплейного буфера не оказывает влияния на дескриптор, возвращаемый GetStdHandle(). Аналогично, использование SetStdHandle() для изменения дескриптора STDOUT не оказывает влияния на активный дисплейный буфер.

Дескрипторы консоли, возвращаемые функциями CreateFile() и CreateConsoleScreenBuffer(), могут быть использованы в любой консольной функции, которая требует дескриптор входного буфера консоли или дисплейного буфера. Дескрипторы, возвращаемые GetStdHandle(), могут быть использованы консольными функциями, если они не перенаправлены на нечто, отличающееся от консольного ввода/вывода. Если стандартный дескриптор был перенаправлен на файл или программный канал, он, тем не менее, может быть использован в функциях ReadFile() и WriteFile().

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

Следующая функция возвращает дескриптор текущего окна консольного приложения (HWND). Если функция выполнена удачно, то возвращённое значение будет являться дескриптором консольного окна, иначе, в случае ошибки будет возвращён NULL. Для краткости некоторые проверки возможных ошибок убраны.

Источник: http://netcode.ru/cpp/?lang=&katID=16&skatID=152&artID=4865

HWND GetConsoleHwnd(void)

{

  #define MY_BUFSIZE 1024 // Размер буфера для заголовка консольного окна.

  HWND hwndFound;    // Это то, что будет возвращено.

  char pszNewWindowTitle[MY_BUFSIZE]; // Уникальный заголовок окна.

  char pszOldWindowTitle[MY_BUFSIZE]; // Изначальный заголовок окна.

 

  // Выбираем текущий заголовок окна.

 

  GetConsoleTitle(pszOldWindowTitle, MY_BUFSIZE);

 

  // Формируем "уникальный" NewWindowTitle.

 

  wsprintf(pszNewWindowTitle,"%d/%d",

              GetTickCount(),

              GetCurrentProcessId());

 

  // Изменяем текущий заголовок окна.

 

  SetConsoleTitle(pszNewWindowTitle);

 

  // даём время заголовку, чтобы измениться.

 

  Sleep(40);

 

  // Ищем NewWindowTitle.

 

  hwndFound=FindWindow(NULL, pszNewWindowTitle);

 

  // Восстанавливаем изначальный заголовок окна.

 

  SetConsoleTitle(pszOldWindowTitle);

 

  return(hwndFound);

}

 

 

Входной буфер консоли

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

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

 Входная запись представляет собой структуру, содержащую информацию о типе события (клавиатура, мышь, изменение размера окна, получение клавиатурной фокусировки или вызов меню) и специфические данные о событии. Член EventType структуры INPUT_RECORD указывает на тип события, содержащегося в записи. События получения клавиатурной фокусировки и вызова тем меню помещаются в буфер консоли для внутреннего использования системой и должны игнорироваться приложениями.

 

События клавиатуры.

 Эти события генерируются при нажатии и отпускании клавиш, включая управляющие клавиши. Тем не менее, клавиша Alt имеет специальное значение для системы, когда нажимается и отпускается без комбинации с другими символами, и не передается приложению. Аналогичным образом клавишная команда Ctrl+C тоже не передается, если дескриптор ввода находится в режиме обработки.

Если входное событие представляет собой нажатие клавиши, член Event структуры INPUT_RECORD представляет собой структуру KEY_EVENT_RECORD, содержащую такую информацию:

· значение булевского типа, указывающее на то, была ли клавиша нажата или отпущена;

· счетчик повторений, больший 1 в случае, если клавиша удерживается;

· виртуальный ключ (virtual-key code) – независимое от устройства значение, идентифицирующее клавишу клавиатуры;

· виртуальный скан-ключ (virtual-scan code), генерируемый клавиатурой;

· символ Unicode или ANSI;

· флаг, указывающий на состояние клавиш сдвига (alt, ctrl, shift, num lock, scroll lock и caps lock) и на то, была ли нажата «расширенная» клавиша (enhanced key). Расширенные клавиши для клавиатур IBM 101-клавишных и 102-клавишных – это ins, del, home, end, page up, page down и клавиши перемещения курсора, расположенные левее цифровой клавиатуры (numeric keypad), а также клавиши divide (/)  и Enter цифровой клавиатуры.

 

typedef struct _INPUT_RECORD { // ir

WORD EventType;

union {

   KEY_EVENT_RECORD KeyEvent;

   MOUSE_EVENT_RECORD MouseEvent;

   WINDOW_BUFFER_SIZE_RECORD WindowBufferSizeEvent;

   MENU_EVENT_RECORD MenuEvent;

   FOCUS_EVENT_RECORD FocusEvent;

} Event;

} INPUT_RECORD;

 

typedef struct _KEY_EVENT_RECORD { // ker

BOOL bKeyDown;

WORD wRepeatCount;

WORD wVirtualKeyCode;

WORD wVirtualScanCode;

union {

   WCHAR UnicodeChar;

   CHAR AsciiChar;

} uChar;

DWORD dwControlKeyState;

} KEY_EVENT_RECORD;

 

События мыши.

Эти события генерируются при перемещении мыши и нажатии или отпускании ее клавиш. События мыши помещаются во входной буфер в следующих случаях:

· режим ввода консоли установлен в ENABLE_MOUSE_INPUT (это режим по умолчанию);

· окно консоли имеет клавиатурную фокусировку (keyboard focus);

· указатель мыши находится в области границ окна консоли.  

 

Если входным событием является событие от мыши, то член Event структуры INPUT_RECORD является, в свою очередь, структурой MOUSE_EVENT_RECORD, содержащей такую информацию:

· координаты указателя мыши – позиция в строке и номер строки в координатной системе дисплейного буфера;

· флаг, указывающий на состояние кнопок мыши;

· флаг, указывающий на состояние клавиш сдвига (alt, ctrl, shift, num lock, scroll lock и caps lock) и на то, была ли нажата «расширенная» клавиша (enhanced key). Расширенные клавиши для клавиатур IBM 101-клавишных и 102-клавишных – это ins, del, home, end, page up, page down и клавиши перемещения курсора, расположенные левее цифровой клавиатуры (numeric keypad), а также клавиши divide (/) и Enter цифровой клавиатуры;

Замечание. Координаты мыши указываются в термах именно дисплейного буфера, а не окна консоли. Дисплейный буфер может быть скроллирован относительно окна, так что левый верхний угол окна не обязательно будет иметь координаты (0,0) в дисплейном буфере. Для получения координат мыши относительно координатной системы окна необходимо вычесть начальные координаты окна (the window origin coordinates) из координат мыши. Для получения этих начальных координат окна используйте функцию GetConsoleScreenBufferInfo().

· флаг, идентифицирующий событие: нажатие или отпускание кнопки, перемещение мыши, второй щелчок клавиши или двойной щелчок.

 

typedef struct _MOUSE_EVENT_RECORD { // mer

COORD dwMousePosition;

DWORD dwButtonState;

DWORD dwControlKeyState;

DWORD dwEventFlags;

} MOUSE_EVENT_RECORD;

 

Член dwButtonState структуры MOUSE_EVENT_RECORD имеет бит, соответствующий каждой кнопке мыши. Если бит равен 1, то кнопка нажата, 0 – не нажата. Отпускание кнопки мыши обнаруживается по нулевому значению члена dwEventFlags структуры MOUSE_EVENT_RECORD и изменению значения бита кнопки с 1 на 0. Функция GetNumberOfConsoleMouseButtons() возвращает число кнопок мыши.

События изменения размера буфера.

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

Если входное событие есть обсуждаемое, то член Event структуры INPUT_RECORD представляет собой структуру WINDOW_BUFFER_SIZE_RECORD, содержащую новые размеры дисплейного буфера, выраженные в знакоместах.

Если пользователь уменьшает размер дисплейного буфера, любые данные в уничтожаемой области буфера теряются. Изменение приложением размеров дисплейного буфера с помощью функции SetConsoleScreenBufferSize() не генерирует событие изменения размера буфера.

Буферы дисплея консоли

Дисплейный буфер представляет собой двумерный массив символов и их цветов, которые выводятся в окно консоли. Консоль может иметь много дисплейных буферов. Активный дисплейный буфер – тот, содержимое которого отображается на дисплее.

Система создает дисплейный буфер всякий раз, когда создает новую консоль. Процесс может использовать функцию CreateConsoleScreenBuffer() для создания дополнительных дисплейных буферов для своей консоли. Новый дисплейный буфер не станет активным до тех пор, пока его дескриптор не будет указан в качестве параметра функции SetConsoleActiveScreenBuffer(). Тем не менее, дисплейные буферы доступны для чтения и записи независимо от того, являются они активными или нет.

Каждый дисплейный буфер имеет свой собственный двумерный массив записей с информацией о символах. Данные по каждому символу хранятся в структуре CHAR_INFO, которая содержит Unicode или ANSI код символа и цвета символа и его фона.

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

· размер буфера в знакоместах, т.е. число символов в строке и число строк;

· текстовые атрибуты (цвета символов и фона, которые используются функциями WriteFile() и WriteConsole() для вывода текста на консоль);

· позиция и размеры окна (прямоугольная область дисплейного буфера, которая отображается в окне консоли);

· позиция курсора, его форма и видимость;

· режимы вывода (ENABLE_PROCESSED_OUTPUT и ENABLE_WRAP_AT_EOL_OUTPUT). Для получения дополнительной информации по этим режимам см. подраздел «Высокоуровневые режимы консоли».

 

При создании дисплейного буфера он содержит пробелы. Его курсор видим и установлен в позицию буфера (0,0), а левый верхний угол окна совмещен с левым верхним углом буфера. Размер дисплейного буфера, размер окна, текстовые атрибуты и вид курсора определяются пользователем или системными значениями по умолчанию. Получить значения этих и других свойств можно с помощью функций GetConsoleScreenBufferInfo(), GetConsoleCursorInfo() и GetConsoleMode().

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

 










Последнее изменение этой страницы: 2018-04-12; просмотров: 344.

stydopedya.ru не претендует на авторское право материалов, которые вылажены, но предоставляет бесплатный доступ к ним. В случае нарушения авторского права или персональных данных напишите сюда...