- •Часть II. Проектирование пользовательских интерфейсов средствами win32 api п 1. Основы приложений для Windows. П 1.1 Типы данных Windows.
- •П. 1.2 Главная функция приложения WinMain().
- •П. 1.3 Оконная функция.
- •П. 1.4 Сообщения от окна
- •П. 1.5 Сообщения от мыши
- •1.5.1 Сообщения мыши, связанные с рабочей областью окна
- •1.5.3 Двойные щелчки мыши
- •1.5.4 Сообщения мыши, связанные с нерабочей областью окна
- •1.5.5 Захват мыши
- •П. 1.6 Сообщения от клавиатуры
- •1.6.1 Синхронизация событий клавиатуры
- •1.6.2 Игнорирование событий клавиатуры
- •1.6.3 Понятие фокуса ввода
- •1.6.4 Категории клавиатурных сообщений
- •1.6.5 Аппаратные сообщения
- •1.6.6 Символьные сообщения
- •П. 1.7 Таймеры Windows и служба времени.
- •П. 1.8 Классы окон
- •1.8.1. Описание используемых классом окон ресурсов
- •1.8.2. Регистрация класса окон
- •1.8.3. Создание окон
- •1.8.4. Стили окна
- •П. 1.9 Цикл обработки сообщений
- •П. 1.10 Структура текста приложения
- •П. 1.11 Вспомогательные функции создания окон
- •1.11.1 Функции отображения и перерисовки окон
- •1.11.2 Функции поиска и определения состояния окон
- •1.11.3 Функции перемещения окон
- •1.11.4 Сообщения приложения для пользователя
- •П. 1.12 Примеры создания окон
- •П 2. Органы управления
- •П 2.1. Кнопки
- •2.1.1. Создание кнопок
- •2.1.2. Кнопки и сообщения
- •2.1.3. Флажки и переключатели
- •П 2.2. Статический орган управления
- •П 2.3. Полоса прокрутки
- •2.3.1. Общие сведения
- •2.3.2. Создание полосы прокрутки
- •2.3.3. Простейшие полосы прокрутки
- •2.3.4. Сообщения от полосы прокрутки
- •2.3.5. Управление полосой прокрутки
- •П 2.4 Редактор текста
- •2.4.1. Создание редактора
- •2.4.2. Сообщения для редактора текста
- •2.4.3. Сообщения от редактора текста
- •П 2.5. Списки строк
- •2.5.1. Создание списка
- •2.5.2. Сообщения от списка
- •2.5.3. Сообщения для списка
- •П. 2.6. Комбинированный список
- •2.6.1. Создание комбинированного списка
- •2.6.2. Коды извещения
- •2.6.3. Сообщения для комбинированного списка
- •П 3. Вывод в окно
- •П. 3.1. Виды контекста отображения
- •П 3.2. Сообщение wm_paint
- •П 3.3. Установка атрибутов контекста отображения для текста
- •П 3.4. Вывод текста
- •3.4.1. Настройка параметров шрифта
- •3.4.2. Выбор шрифта в контекст отображения
- •3.4.3. Функции вывода текста
- •3.4.4. Определение метрик шрифта
- •П 3.5. Рисование геометрических фигур
- •3.5.1 Установка атрибутов контекста отображения для рисования.
- •3.5.1. Функции рисования точки
- •3.5.2. Функции рисования линий
- •3.5.3. Функции рисования замкнутых фигур
- •3.5.4 Функции создания и рисования регионов
- •П. 4 Ресурсы приложения и их использование. П. 4.1 Файл ресурсов.
- •П 4.2 Главное меню
- •П. 4.2.1 Элементы меню
- •П. 4.2.2 Создание меню
- •П. 4.2.3 Сообщения от меню
- •П. 4.3. Плавающее меню
- •П. 4.4. Акселераторы
- •П. 4.5. Панель инструментов
- •4.5.1. Создание панели инструментов
- •4.5.2. Управление состоянием кнопок панели
- •4.5.3. Вывод подсказок в панели инструментов
- •П. 4.6. Строка состояния
- •4.6.1. Создание строки состояния
- •4.6.2. Сообщения о меню в строке состояний
- •П 5. Диалоговые панели п. 5.1. Характеристики диалоговых панелей
- •5.1.1. Единицы диалоговой панели '
- •5.1.2. Стили диалоговой панели
- •5.1.3. Функция окна диалоговой панели
- •П. 5.2. Создание диалоговой панели
- •5.2.1 Создание окна модальной диалоговой панели
- •5.2.2 Создание окна немодальной диалоговой панели
- •П. 5.3 Разработка и компоновка диалоговых панелей.
- •П. 5.4 Сообщения и диалоговые панели
- •П. 5.5. Стандартные диалоговые панели
- •5.5.1. Панели для открытия или сохранения файлов
- •5.5.2. Панель для выбора цветов
- •5.5.3. Панель для выбора шрифта
П. 1.12 Примеры создания окон
Задача 1. Окно приложения стиля временного окна с кнопкой минимизации и с фоном цвета рабочего стола Windows занимает весь экран. При попытке запуска второго экземпляра на передний план переместить окно первого экземпляра и завершить работу.
Анализ задания.
Для поиска других экземпляров приложения воспользуемся функцией FindWindow:
HWND hwnd=FindWindow(szMainClass,szTiUe);
Она возвращает дескриптор окна класса szMainClass с заголовком szTitle. Если такого окна нет, то это первый экземпляр приложения и дескриптору hwnd присваивается NULL. Иначе, возвращается дескриптор найденного окна.
Внимание! Функция FindWindow проверяет только совпадение имени класса и заголовка. То есть, если работает экземпляр другого приложения с окном класса с таким же именем szMainClass и заголовком szTitle, то функция вернет дескриптор окна другого приложения.
Если "предыдущий экземпляр приложения" обнаружен, выводим сообщение:
MessageBox(hwnd,
"Можно запускать только одну копию приложения!!!"
"Перемещаю на передний план первый экземпляр", szTitle, MB_OK | MB_CONSTOP);
До перемещения окна на передний план проверяем состояние этого окна и, если оно свернуто, восстанавливаем его предыдущее состояние:
if (lslconic( hwnd)) ShowWindow( hwnd, SW_RESTORE);
Перемещаем окно первого экземпляра приложения на передний план:
SetForegroundWindow(hwnd);
Затем второй экземпляр приложения завершает работу.
Если предыдущий экземпляр приложения не найден, регистрируем класс окна:
if (!RC(WndProc,szMainClass,COLOR_DESKTOP)) return FALSE;
Для создания максимально распахнутого окна приложения определяем ширину и высоту экрана в пикселях:
Int w=GetSystemMetrics(SM_CXSCREEN);
int h=GetSystemMetrics(SM_CYSCREEN);
Создаем окно:
hwnd = CreateWindow(szMainClass, szTitle,
WS_POPUPWINDOW | WS_CAPTION | WS_MINIMIZEBOX | WS_VISIBLE, 0,0, w, h, 0,0, hinstance, NULL);
Далее активизируем цикл обработки и диспетчеризации сообщений:
while(GetMessage(&msg, 0,0,0)) DispatchMessage(&msg);
Любые действия над окном передают функции окна, которая ранее уже была рассмотрена.
#include <windows.h>
LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM);
HINSTANCE hInstance;
char szMainClass[ ] = "MainClass";
char szTitle[]= "Пример 1.2";
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevlnst,
LPSTR IpszCmdLine, int nCmdShow)
{
MSG msg;
hInstance=hInst;
HWND hwnd=FindWindow(szMainClass,szTitle);
if (hwnd) { MessageBox(hwnd,
"Можно запускать только одну копию приложения!!!"
"Перемещаю на передний план первый экземпляр", szTitle, MB_OK | MB_ICONSTOP);
if (IsIconic(hwnd))
ShowWindow(hwnd, SW_RESTORE);
SetForegroundWindow(hwnd);
return 0;
}
WNDCLASS wc;
wc.style=wc.cbClsExtra=wc.cbWndExtra=0;
wc.lpfnWndProc=Proc;
wc.hInstance = hInstance;
wc.hIcon=LoadIcon(NULL,IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW +1);
wc.lpszMenuName = (LPCTSTR)NULL;
wc.lpszClassName=szName;
if (RegisterClass(&wc) == 0) return FALSE;
int w=GetSystemMetrics(SM_CXSCREEN)-1; //Ширина
int h=GetSystemMetrics(SM_CYSCREEN)-1; //Высота
hwnd = CreateWindow(szMainClass, szTitle,
WS_POPUPWINDOW | WS_CAPTION |WS_MINIMIZEBOX | WS_VISIBLE,
0,0, w, h, 0,0, hInstance, NULL);
if (!hwnd) return FALSE;
while(GetMessage(&msg, 0,0,0)) DispatchMessage(&msg);
return msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg,
WPARAM wParam, LPARAM lParam)
{
switch (msg)
{ case WM_DESTROY: { PostQuitMessage(0); return 0; }}
return DefWindowProc(hwnd, msg, wParam, lParam);
}
Задача 2. После нажатия на левую клавишу мыши над рабочей областью главного окна приложения в левом верхнем углу области отобразить временное окно цвета трехмерных элементов размером в четверть области. Временное окно скрыть после отжатия клавиши в любом месте экрана.
Анализ задачи. Перекрывающееся и временное окна создаем в функции WinMain, но отображаем на экране только перекрывающееся, временное создаем в памяти.
Для того, расположить временное окно в правом верхнем углу главного окна, нужно знать координаты этого угла. При поступлении кода WM_MOVE параметр lParam оконной функции содержит экранные координаты левого верхнего угла рабочей области. То есть:
left=LOWORD(IParam); //Координата левого края рабочей области top=HIWORD(IParam); //Координата верхнего края рабочей области
Таким образом, программа должна содержать обработку сообщения WM_MOVE.
Для определения ширины и высоты временного окна, нужно знать соответствующие параметры главного окна. Такую информацию несет параметр lParam при поступлении сообщения WM_SIZE. То есть:
cx=LOWORD(IParam); //Ширина рабочей области
cy=HIWORD(IParam); //Высота рабочей области
Тогда ширина временного окна определяется так:
cx=LOWORD(IParam)\2; //Ширина рабочей области
cy=HIWORD(IParam)\2; //Высота рабочей области
При нажатии левой клавиши мыши поступает сообщение WM_LBUTTONDOWN. Алгоритм обработки этого сообщения следующий: 1) Передать мышь в монопольное пользование главному окну, чтобы последующие действия выполнялись и в том случае, если указатель мыши находится над временным окном. Для этого воспользоваться функцией SetCapture(hwnd).
-
Отобразить временное окно на экране функцией ShowWindow(pop,SW_SHOW).
При отжатии левой клавиши мыши поступает сообщение WM_LBUTTONUP. Здесь скрыть окно функцией ShowWindow(pop,SW_HIDE) и отменить режим монопольного использования мыши функцией ReleaseCapture.
Так как дескриптор временного окна, а также переменные left, top, cx, cy должны быть доступны в оконной функции, нужно описать их как глобальные. А так как необходимо, чтобы эти переменные сохраняли свои значения между вызовами оконной функции, нужно описать их с приставкой static:
static HWND pop;
static short left, top, cx,cy;
#include <windows.h>
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK WndPop(HWND, UINT, WPARAM, LPARAM);
BOOL RC(WNDPROC, LPCTSTR, UINT);
char Name[]="Class";
char NamePop[]="Popup";
HINSTANCE hinst;
static HWND pop;
static short left, top, cx,cy;
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE Prev,
LPSTR Line,
int Show)
{
MSG msg;
HWND hwnd;
hinst=hInstance;
if(!RC(WndProc,Name,COLOR_WINDOW)) return FALSE;
if(!RC(WndPop,NamePop,COLOR_BTNFACE)) return FALSE;
hwnd=CreateWindow(Name,"m a i n",
WS_OVERLAPPEDWINDOW|WS_VISIBLE,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
0, 0, hInstance, NULL);
if (!hwnd) return FALSE;
pop =CreateWindow(NamePop,"Мое окно",
WS_POPUPWINDOW,
left,top,cx,cy,
hwnd, 0, hinst, NULL);
if (!pop) return FALSE;
while (GetMessage(&msg, 0, 0, 0)) DispatchMessage(&msg);
return msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg,
WPARAM wParam, LPARAM lParam)
{
switch (msg)
{ case WM_DESTROY : {PostQuitMessage(0); return (0);}
case WM_LBUTTONDOWN : {
SetCapture(hwnd);
ShowWindow(pop,SW_SHOW);
return 0; }
case WM_LBUTTONUP : {
ShowWindow(pop,SW_HIDE);
ReleaseCapture();
return 0;}
case WM_MOVE : {
left = LOWORD(lParam);
top = HIWORD (lParam); return 0;}
case WM_SIZE : {
cx = LOWORD(lParam)/2;
cy = HIWORD(lParam)/2; return 0;}
}
return DefWindowProc(hwnd, msg, wParam, lParam);
}
LRESULT CALLBACK WndPop(HWND hwnd, UINT msg,
WPARAM wParam, LPARAM lParam)
{
return DefWindowProc(hwnd, msg, wParam, lParam);
}
BOOL RC(WNDPROC WndProc, LPCTSTR Name, UINT brBackground)
{
WNDCLASS wc;
wc.style=wc.cbClsExtra=wc.cbWndExtra=0;
wc.lpfnWndProc=WndProc;
wc.hInstance=hinst;
wc.hIcon=LoadIcon(NULL,IDI_APPLICATION);
wc.hCursor=LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground=(HBRUSH)( brBackground +1);
wc.lpszMenuName=NULL;
wc.lpszClassName=Name;
return (RegisterClass(&wc)!=0);}