Опубликован: 15.11.2010 | Доступ: свободный | Студентов: 753 / 47 | Оценка: 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