Опубликован: 15.11.2010 | Доступ: свободный | Студентов: 745 / 44 | Оценка: 4.00 / 5.00 | Длительность: 17:30:00
Специальности: Программист
Лекция 9:

Ввод-вывод с использованием WinAPI

9.7. Приложение № IV

/* Файл INIT.CPP */
/**********************************************************
 * Каркас приложений Windows,
 * на основе которого можно строить более
 * сложные приложения MS WINDOWS.
 * Каркас использует правила для написани
 * программ на платформе Turbo C++ 3.1
 * 16-ти разрядных версий Windows.
 *
 * Более подробную информацию о "низкоуровневом" написании
 * программ для Microsoft Windows смотри А.В. Фролов, Г.В.
 * Фролов, "Операционная система Microsoft Windows 3.1.
 * для программиста". -- М. "ДИАЛОГ-МИФИ", 1994 г. и др.
 * книги этих авторов.
**********************************************************/
#define STRICT
#include <windows.h>
#include <mem.h>
// Прототипы функций
// Первая функция - для инициализации
// приложения Windows, вторая функция -
// для обработки системных сообщений.
BOOL InitApp(HINSTANCE);
LRESULT CALLBACK _export WndProc(HWND, UINT, WPARAM, LPARAM);
/* Значения класса и заголовка впоследствии нужно заменить */
// Имя класса окна
char const szClassName[]   = "WindowAppClass";
// Заголовок окна
char const szWindowTitle[] = "Window Application";
// =====================================
/***************************************
 * Функция WinMain
 * Получает управление при запуске
 * приложени
***************************************/
// =====================================
#pragma argsused
int PASCAL
WinMain(HINSTANCE hInstance,     // идентификатор текущей
				 // копии приложени
	HINSTANCE hPrevInstance, // идентификатор предыдущей
				 // копии приложени
	LPSTR     lpszCmdLine,   // указатель на командную строку
	int       nCmdShow)      // способ отображения главного
	                         // окна приложени
{
  MSG  msg;   // структура для работы с сообщениями
  HWND hwnd;  // идентификатор главного окна приложени
  // Проверяем, не запускалось ли это приложение ранее
//  if(!hPrevInstance)
//  {
    // Если не запускалось, вызываем функцию InitApp
    // для инициализации приложения.
/*****************************************************
 * Вызываем функцию InitApp
 * для инициализации приложения.
 * Если инициализацию выполнить не удалось,
 * завершаем приложение
*****************************************************/
    if(!InitApp(hInstance))
      return FALSE;
//  }
/****************************************************
 * После успешной инициализации приложения создаём
 * главное окно приложени
****************************************************/
  hwnd = CreateWindow(
    szClassName,         // имя класса окна (см. Выше )
    szWindowTitle,       // заголовок окна (см. Выше)
    WS_OVERLAPPEDWINDOW, // стиль окна
/****************************************************
 * В данном случае это перекрывающееся окно, но эту
 * опцию можно изменить для других типов окон
*****************************************************/
    CW_USEDEFAULT,       // задаём размеры и расположение
    CW_USEDEFAULT,       // окна, принятые по умолчанию
    CW_USEDEFAULT,
    CW_USEDEFAULT,
    0,                   // идентификатор родительского окна
			// Для главного окна его менять нельз
    0,                   // идентификатор меню
/**********************************************************
 * В случае если у окна необходимо создать меню, вместо
 * нуля сюда вставляется идентификатор меню (тип HMENU),
 * созданный с помощью функции LoadMenu.
 *
 * Если меню подключается как ресурс приложения в функции
 * InitApp, в этом поле также нужно оставить 0
**********************************************************/
    hInstance,           // идентификатор приложени
    NULL);               // указатель на дополнительные
			 // параметры
/**********************************************************
 * Далее код лучше не менять *
**********************************************************/
  // Если создать окно не удалось, завершаем приложение
  if(!hwnd)
    return FALSE;
/**********************************************************
 * В случае если Вам не нужно рисовать главное окно
 * приложения (например, Вы пишете программу-мастер)
 * две нижеперечисленные функции:  ShowWindow и
 * UpdateWindow, указывать не надо
**********************************************************/
  // Рисуем окно. Для этого после функции ShowWindow, рисующей
  // окно, вызываем функцию UpdateWindows, посылающую
  // сообщение WM_PAINT в функцию окна
  ShowWindow(hwnd, nCmdShow);
  UpdateWindow(hwnd);
/**********************************************************
 * Далее до конца функции код лучше не менять *
**********************************************************/
  // Запускаем цикл обработки сообщений
  while(GetMessage(&msg, 0, 0, 0))
  {
    DispatchMessage(&msg);
  }
  // Возвращаем значение WParam, переданное
  // в качестве параметра функции PostQuitMessage
  // в процессе инициирования завершения работы
  // приложения из функции окна.
  // Затем завершаем работу приложени
  return msg.wParam;
}
/* Конец функции WinMain *|
// =====================================
/**********************************************************
 * Функция InitApp
 * Вызывается из функции WinMain дл
 * инициализации приложения.
 * Выполняет регистрацию класса окна
**********************************************************/
// =====================================
BOOL InitApp(HINSTANCE hInstance)
{
  ATOM aWndClass; // атом для кода возврата
  WNDCLASS wc;    // структура для регистрации
                  // класса окна
  // Записываем нулевые значения во все поля структуры
  memset(&wc, 0, sizeof(wc));
  // Стиль окна
/**********************************************************
 * Поле style задаёт стиль класса окна и задаётся в виде
 * констант, описанных в файле <windows.h>. Описани
 * констант стилей начинается с префикса CS_. Стиль окна
 * задаёт реакцию окна на изменения его размера, на
 * выполнения в окне операции двойного щелчка мышью, а
 * также задаёт другие характеристики окна.
 * Если в главное окно предполагается вывод информации,
 * необходимо указать, по крайней мере:
 *   wc.style = CS_HREDRAW | CS_REDRAW;
 * в противном случае записать:
 *   wc.style = 0;
**********************************************************/
  wc.style = 0;
  // Указатель на функцию окна, обрабатывающую
  // сообщения, предназначенные для всех окон,
  // созданных на основе данного класса
  /* Желательно не менять! */
  wc.lpfnWndProc = (WNDPROC) WndProc;
  // Размер дополнительной области данных,
  // зарезервированной в описании класса окна
  /* Желательно не менять! */
  wc.cbClsExtra = 0;
  // Размер дополнительной области данных,
  // зарезервированной для каждого окна,
  // созданного на основе данного класса
  /* Желательно не менять! */
  wc.cbWndExtra = 0;
  // Идентификатор приложения, которое
  // создало данный класс
  /* Желательно не менять! */
  wc.hInstance = hInstance;
  // Идентификатор пиктограммы, используемой
  // для окно данного класса
/**********************************************************
 * Иконки создаются или "подгружаются" из специальных
 * файлов с "ресурсами", с помощью команды LoadIcon.
 * Первый параметр функции содержит идентификатор
 * приложения, в котором ищется иконка (значение NULL дл
 * системных областей), второй параметр задаёт имя ресурса-
 * пиктограммы. Если Вы не уверены, то этот параметр
 * менять не нужно.
**********************************************************/
  wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
  // Идентификатор курсора, используемого
  // для окно данного класса
/**********************************************************
 * Курсоры создаются или "подгружаются" из специальных
 * файлов с "ресурсами", с помощью команды LoadCursor.
 * Первый параметр функции содержит идентификатор
 * приложения, в котором ищется курсор (значение NULL дл
 * системных областей), второй параметр задаёт имя ресурса-
 * курсора. Если Вы не уверены, то этот параметр менять
 * не нужно (оставляем стандартный курсор в виде стрелки).
**********************************************************/
  wc.hCursor = LoadCursor(NULL, IDC_ARROW);
  // Цвет фона окна
  /* Желательно не менять, оставить системный цвет */
  wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
  // Идентификатор меню
/**********************************************************
 * В случае если у окна необходимо создать меню, в это
 * поле нужно указать адрес текстовой строки, содержащей
 * имя шаблона меню в файле ресурсов. Все перекрывающиеся и
 * временные окна, созданные на базе этого класса, будут
 * иметь меню, определённое данным шаблоном. Пример:
 *  wc.lpszMenuName = "APP_MENU";
 * Если для идентификации шаблона использовать целые
 * числа, необходимо использовать макрокоманду
 * MAKEINTRESOURCE. Например, в файле описания ресурсов и в
 * файле исходного приложения определена константа:
 * #define APP_MENU 123
 * В этом случае строка примет вид:
 *  wc.lpszMenuName = MAKEINTRESOURCE( APP_MENU );
 * Если в окне меню не нужно, оставьте параметр без
 * изменения.
**********************************************************/
  wc.lpszMenuName = (LPSTR)NULL;
  /* Желательно не менять остальные операторы до конца
     функции */
  // Имя, которое присваивается создаваемому
  // классу и используется при создании
  // окон данного класса
  wc.lpszClassName = (LPSTR)szClassName;
  // Регистрация класса
  aWndClass = RegisterClass(&wc);
  // Возвращаем результат регистрации класса
  return (aWndClass != 0);
}
/* Файл TEXTW.CPP */
/**********************************************************
 * Функция WndProc
**********************************************************/
#define STRICT
#include <windows.h>
#include <stdio.h>
#include <string.h>
// Задание максимальной длины символьного буфера строки
// для вывода в окно
#ifndef SCREEN_BUFSIZE
#define SCREEN_BUFSIZE	80
#endif
// Прототип функции для печати строки символов
void Print(HDC, char *, int);
void PrintLn(void);
/**********************************************************
 * cxChar -- значение ширины для самой широкой литеры
 * cyChar -- max высота литеры с учётом междустрочного
 *           интервала.
 * cxCurrentPosition -- текущая гориз. позиция вывода текста
 * cyCurrentPosition -- текущая верт. позиция вывода текста
**********************************************************/
static int cxChar, cyChar;
static int cxCurrentPosition;
static int cyCurrentPosition;
LRESULT CALLBACK _export
WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
  HDC hdc;              // индекс контекста устройства
  PAINTSTRUCT ps;       // структура для рисовани
  static TEXTMETRIC tm; // структура для записи метрик
                        // шрифта
  switch (msg)
  {
    case WM_CREATE:
    {
      // Получаем контекст отображения,
      // необходимый для определения метрик шрифта
      hdc = GetDC(hwnd);
      // Заполняем структуру информацией
      // о метрике шрифта, выбранного в
      // контекст отображени
      GetTextMetrics(hdc, &tm);
      // Запоминаем значение ширины дл
      // самого широкого символа
      cxChar = tm.tmMaxCharWidth;
      // Запоминаем значение высоты букв с
      // учётом межстрочного интервала
      cyChar = tm.tmHeight + tm.tmExternalLeading;
      // Инициализируем текущую позицию
      // вывода текста
      cxCurrentPosition = cxChar;
      cyCurrentPosition = cyChar;
      // Освобождаем контекст
      ReleaseDC(hwnd, hdc);
      return 0;
    }
    case WM_PAINT:
    {
      // Инициализируем текущую позицию
      // вывода текста
      cxCurrentPosition = cxChar;
      cyCurrentPosition = cyChar;
      hdc = BeginPaint(hwnd, &ps);
      // Выводим последовательно строки:
      Print(hdc, "Первая строка", 0); PrintLn();
      Print(hdc, "Вторая строка", 0); PrintLn();
      Print(hdc, "Третья строка( смещённая )", 10); PrintLn();
      EndPaint(hwnd, &ps);
      return 0;
    }
    case WM_DESTROY:
    {
      PostQuitMessage(0);
      return 0;
    }
  }
  return DefWindowProc(hwnd, msg, wParam, lParam);
}
/**********************************************************
 * Функция Print
 * Функция предназначена для вывода текста
 * в окно.
 *
 * ВХОДНЫЕ ЗНАЧЕНИЯ:
 * HDC hdc -- индекс контекста устройства;
 * char *str -- указатель на выводимую строку;
 * int iOFFSET -- смещение горизонтальной позиции
 * вывода текста в окно, указанное в символах;
 *
 * ГЛОБАЛЬНЫЕ ПЕРЕМЕННЫЕ:
 * cxChar -- значение ширины для самой широкой литеры
 * cyChar -- max высота литеры с учётом междустрочного
 *           интервала.
 * cxCurrentPosition -- текущая гориз. позиция вывода текста
 * cyCurrentPosition -- текущая верт. позиция вывода текста
 *
 * ФУНКЦИЯ ВОЗВРАЩАЕТ:
 * 	Возвращаемых значений нет.
 *
 * ПРИМЕЧАНИЕ:
 * Эта функция может быть переписана Вами под Ваши
 * нужды для вывода не только текста, но и числовых
 * значений, а также для форматирования в строке вывода.
 *
**********************************************************/
void Print(HDC hdc, char *str, int iOFFSET )
{
  char buf[SCREEN_BUFSIZE];
  int i;
/* Проверяем смещение на неравенство единице
   и корректируем его */
  if( iOFFSET < 0 ) iOFFSET = 0;
  // Подготавливаем в рабочем буфере
  i = strlen(str);
  // Проверка, что строка умещается в буфере
  if( i < SCREEN_BUFSIZE - 1 )
  // и выводим строку в зависимости от проверки
	sprintf(buf, "%s", str);
  else
	sprintf(buf, "%.*s", SCREEN_BUFSIZE-1, str);
  // Выводим текст в окно, начиная с текущей позиции
  // вывода текста + смещение в максимальном
  // количестве символов
  TextOut(hdc,
    cxCurrentPosition + iOFFSET * cxChar,
    cyCurrentPosition,
    buf, i);
}
/**********************************************************
 * Функция PrintLn
 * Функция предназначена для перевода на новую строку
 * при выводе в окно.
 *
 * ВХОДНЫЕ ЗНАЧЕНИЯ:
 * Не имеет.
 *
 * ГЛОБАЛЬНЫЕ ПЕРЕМЕННЫЕ:
 * cxChar -- значение ширины для самой широкой литеры
 * cyChar -- max высота литеры с учётом междустрочного
 *           интервала.
 * cxCurrentPosition -- текущая гориз. позиция вывода текста
 * cyCurrentPosition -- текущая верт. позиция вывода текста
 *
 * ФУНКЦИЯ ВОЗВРАЩАЕТ:
 * 	Возвращаемых значений нет.
 *
 * ПРИМЕЧАНИЕ:
 * Эта функция может быть переписана Вами под Ваши
 * нужды для вывода не только текста, но и числовых
 * значений, а также для форматирования в строке вывода.
 *
**********************************************************/
void PrintLn( void )
{
  // Увеличиваем текущую позицию по
  // вертикали на высоту символа
  cyCurrentPosition += cyChar;
}
/* Файл TEXTWN.DEF*/
; =============================
; Файл определения модул
; =============================
; Имя приложени
NAME TEXTWIN
; Описание приложени
DESCRIPTION 'Приложение WINDOW, (C) 1994, Frolov A.V.'
; Определение типа загрузочного модуля как
; приложения Windows
EXETYPE windows
; Программа, которая будет записана в начало файла
; приложения. Эта программа получит управление
; при попытке запуска приложения в среде MS-DOS
STUB 'winstub.exe'
; Размер стека в байтах
STACKSIZE 5120
; Размер локальной кучи памяти приложения в байтах
HEAPSIZE 1024
; Атрибуты сегмента кода
CODE preload moveable discardable
; Атрибуты сегмента данных
DATA preload moveable multiple