Операционная система Microsoft Windows 3.1 для программиста -том 2

         

Файл edit\edit.cpp


// ---------------------------------------- // Редактор текста // ----------------------------------------

#define STRICT #include <windows.h>
#include <mem.h>

// Идентификатор редактора текста #define ID_EDIT 1

// Идентификатор кнопки #define ID_BUTTON 2

// Прототипы функций BOOL InitApp(HINSTANCE);
LRESULT CALLBACK _export WndProc(HWND, UINT, WPARAM, LPARAM);

// Имя класса окна char const szClassName[] = "EditAppClass";

// Заголовок окна char const szWindowTitle[] = "Edit Demo";

// Идентификатор копии приложения HINSTANCE hInst;

// ===================================== // Функция WinMain // ===================================== #pragma argsused

int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow) { MSG msg; // структура для работы с сообщениями HWND hwnd; // идентификатор главного окна приложения

// Инициализируем приложение if(!InitApp(hInstance)) return FALSE;

// Сохраняем идентификатор копии приложения // в глобальной переменной hInst = hInstance;

// После успешной инициализации приложения создаем // главное окно приложения hwnd = CreateWindow( szClassName, // имя класса окна szWindowTitle, // заголовок окна WS_OVERLAPPEDWINDOW, // стиль окна CW_USEDEFAULT, // задаем расположение и размеры CW_USEDEFAULT, // окна, принятые по умолчанию CW_USEDEFAULT, // CW_USEDEFAULT, // 0, // идентификатор родительского окна 0, // идентификатор меню hInstance, // идентификатор приложения NULL);
// указатель на дополнительные // параметры // Если создать окно не удалось, завершаем приложение if(!hwnd) return FALSE;

// Рисуем главное окно ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);

// Запускаем цикл обработки сообщений while(GetMessage(&msg, 0, 0, 0)) { // Создаем символьные сообщения TranslateMessage(&msg);
DispatchMessage(&msg);
} return msg.wParam; }

// ===================================== // Функция InitApp // Выполняет регистрацию класса окна // =====================================


BOOL InitApp(HINSTANCE hInstance) { ATOM aWndClass; // атом для кода возврата WNDCLASS wc; // структура для регистрации // класса окна

memset(&wc, 0, sizeof(wc));

wc.style = 0; wc.lpfnWndProc = (WNDPROC) WndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInstance; wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wc.lpszMenuName = (LPSTR)NULL; wc.lpszClassName = (LPSTR)szClassName;

// Регистрация класса aWndClass = RegisterClass(&wc);

return (aWndClass != 0);
}

// ===================================== // Функция WndProc // =====================================

LRESULT CALLBACK _export WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { // Идентификатор редактора текста static HWND hEdit;

// Идентификатор кнопки static HWND hButton;

switch (msg) { case WM_CREATE: { // Создаем редактор текста hEdit = CreateWindow("edit", NULL, WS_CHILD | WS_VISIBLE | WS_BORDER | ES_LEFT, 30, 30, 300, 30, hwnd, (HMENU) ID_EDIT, hInst, NULL);

// Создаем кнопку hButton = CreateWindow("button", "OK", WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, 30, 80, 100, 30, hwnd, (HMENU) ID_BUTTON, hInst, NULL);

return 0; }

// Когда главное окно приложения получает // фокус ввода, отдаем фокус редактору текста case WM_SETFOCUS: { SetFocus(hEdit);
return 0; }

case WM_COMMAND: { // Обработка извещения текстового редактора // об ошибке if(wParam == ID_EDIT) { if(HIWORD(lParam) == EN_ERRSPACE) { MessageBox(hwnd, "Мало памяти", szWindowTitle, MB_OK);
} }

// Сообщение от кнопки else if(wParam == ID_BUTTON) { BYTE chBuff[80]; WORD cbText;

// Записываем в первое слово буфера // значение размера буфера в байтах * (WORD *) chBuff = sizeof (chBuff) - 1;

// Получаем от редактора текста содержимое // первой строки. Функция возвращает количество // байт, скопированных в буфер cbText = SendMessage(hEdit, EM_GETLINE, 0, (LPARAM)(LPSTR)chBuff);

// Закрываем буфер двоичным нулем chBuff[cbText] = '\0';



// Выводим содержимое буфера на экран MessageBox(hwnd, chBuff, szWindowTitle, MB_OK);
} return 0; }

case WM_PAINT: { HDC hdc; PAINTSTRUCT ps;

// Получаем индекс контекста устройства hdc = BeginPaint(hwnd, &ps);

// Выводим текстовую строку TextOut(hdc, 30, 10, "Введите строку и нажмите кнопку 'OK'", 36);

// Отдаем индекс контекста устройства EndPaint(hwnd, &ps);
return 0; }

case WM_DESTROY: { PostQuitMessage(0);
return 0; } } return DefWindowProc(hwnd, msg, wParam, lParam);
}

В начале исходного текста определены идентификаторы редактора текста и кнопки:

#define ID_EDIT 1 #define ID_BUTTON 2

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

while(GetMessage(&msg, 0, 0, 0)) { TranslateMessage(&msg);
DispatchMessage(&msg);
}

В функции главного окна приложения определены две статические переменные для хранения идентификаторов созданных органов управления - редактора текста и кнопки:

static HWND hEdit; static HWND hButton;

По сообщению WM_CREATE функция окна создает редактор текста и кнопку, вызывая функцию CreateWindow. При создании текстового редактора используется комбинация стилей WS_CHILD | WS_VISIBLE | WS_BORDER | ES_LEFT. При этом создается дочернее окно, которое изначально является видимым и имеет рамку. Для текста задается выравнивание по левой границе:

hEdit = CreateWindow("edit", NULL, WS_CHILD | WS_VISIBLE | WS_BORDER | ES_LEFT, 30, 30, 300, 30, hwnd, (HMENU) ID_EDIT, hInst, NULL);

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



case WM_SETFOCUS: { SetFocus(hEdit);
return 0; }

Сообщение WM_COMMAND может приходить в функцию главного окна от текстового редактора или от кнопки.

Если сообщение пришло от текстового редактора, параметр wParam этого сообщения содержит идентификатор редактора ID_EDIT. В этом случае обработчик сообщения получает код извещения из старшего байта параметра lParam. Обрабатывается только одно извещение с кодом EN_ERRSPACE (мало памяти).

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

Подготовка буфера заключается в том, что в его первое слово записывается размер буфера в байтах:

* (WORD *) chBuff = sizeof (chBuff) - 1;

Затем текстовому редактору посылается сообщение EM_GETLINE:

cbText = SendMessage(hEdit, EM_GETLINE, 0, (LPARAM)(LPSTR)chBuff);

В качестве парамера lParam используется адрес подготовленного буфера.

После посылки сообщения функция SendMessage возвращает количество скопированных в буфер символов, причем буфер нулем не закрывается. Далее обработчик сообщения закрывает буфер нулем и выводит содержимое буфера на экран:

chBuff[cbText] = '\0'; MessageBox(hwnd, chBuff, szWindowTitle, MB_OK);

Обработчик сообщения WM_PAINT выводит в окно приглашение для ввода текста, вызывая функцию TextOut:

TextOut(hdc, 30, 10, "Введите строку и нажмите кнопку 'OK'", 36);

Файл определения модуля для приложения EDIT приведен в листинге 2.23.


Содержание раздела