- •Московская финансово-промышленная академия
- •Содержание
- •Глава 1. Модель программирования приложений
- •1.1. Потребительские свойства Windows
- •1.2. Процессы в Windows и потоковая многозадачность
- •1.3. Динамические библиотеки
- •1.4. Программное обеспечение для создания Win-приложений
- •Спецификация префиксов венгерской нотации
- •Глава 2. Обзор возможностей программирования
- •2.1. Общий взгляд на программирование в Windows
- •2.2. Взаимодействие Windows с программой
- •2.3. Win32 api: прикладной интерфейс для Windows
- •2.4. Компоненты окна
- •2.5. Основы приложений Windows
- •2.6. Каркас приложения Windows
- •2.7. Определение класса окна
- •Значения параметра lpszName
- •Наиболее употребляемые макросы для встроенных курсоров
- •Типы системных кистей
- •2.8. Создание окна
- •Наиболее распространенные стили
- •Параметры способа отображения nHow
- •2.9. Цикл обработки сообщений
- •2.10. Оконная функция
- •Типы префиксов
- •Глава 3. Обработка сообщений Windows
- •3.1. Что такое сообщения?
- •3.2. Обработка нажатая клавиш
- •Битовая карта lParam
- •3.3. Обработка сообщений wm_paint
- •3.4. Обработка сообщений «мыши»
- •3.5. Генерация сообщения wm_paint
- •3.6. Генерация сообщений таймера
- •Глава 4. Ресурсы и меню
- •4.1. Окна сообщений MessageBox
- •Значения функции MessageBox
- •Значения wMbType
- •4.2. Представляем меню
- •4.3. Использование ресурсов
- •Параметры menu
- •Параметры элементов меню
- •4.4. Включение меню в программу. Обработка команд
- •4.5. Включение акселераторов сменю
- •4.6. Загрузка таблицы акселераторов
- •Глава 5. Создание диалогов
- •5.1. Взаимодействие Win-диалогов с пользователем
- •5.2. Модальные диалоги: обработка сообщений
- •5.3. Активизация и создание простейшего диалога
- •5.4. Определение ресурсов диалога
- •Стили диалога
- •5.5. Оконная функция диалога
- •5.6. Основы работы со списками
- •Типы сообщений
- •5.7. Инициализация списка и выбор элементов
- •5.8. Окно ввода
- •5.9. Использование немодального диалога
- •Глава 6. Графические образы, иконки и курсоры
- •6.1. Иконка и курсор
- •6.2. Определение малой иконки
- •6.3. Работа с растровыми изображениями
- •Значения параметра dwRaster
- •6.4. Работа с несколькими растровыми изображениями
- •Глава 7. Более подробно об элементах управления
- •7.1. Работа с контрольными переключателями
- •7.2. Статические элементы
- •7.3. Работа с селекторными кнопками
- •7.4. Линейки прокрутки
7.4. Линейки прокрутки
В заключении главы рассмотрим еще один элемент управления – линейку прокрутки (scroll bar). В Windows существует два варианта использования линеек прокрутки. Первый, когда линейка прокрутки может функционировать как часть обычного окна или диалога. Второй, когда она может действовать самостоятельно, как и любой другой элемент управления. Хотя в обоих вариантах управление линейкой прокрутки осуществляется одним и тем же способом, использование линейки прокрутки как элемента управления требует применения некоторых специальных приемов. По этой причине в данном разделе мы рассмотрим использование линейки прокрутки как отдельного элемента управления.
Рис. 7.3. Диалог с селекторными кнопками
Для того чтобы добавить линейку прокрутки в диалог, используется оператор SCROLLBAR, имеющий следующую общую форму:
SCROLLBAR ID, X, Y, Width, Height[, стиль]
Здесь ID – идентификатор линейки прокрутки, Х и Y – координаты ее верхнего левого угла, a Width и Height – размеры соответственно по горизонтали и вертикали. Стиль определяет вид и форму линейки прокрутки. По умолчанию выбирается стиль SBS_HORZ, который определяет горизонтальную линейку прокрутки. Для создания вертикальной линейки прокрутки необходимо задать стиль SBS_VERT. Чтобы линейка прокрутки могла получать фокус и реагировать на ввод с клавиатуры, следует добавить стиль VS_TABSTOP. Ниже приведен пример оператора создания вертикальной линейки прокрутки:
SCROLLBAR ID_SB1, 130, 10, 10, 70,
SBS_VERT|WS_TABSTOP
Сообщения линейки прокрутки. В отличие от других элементов управления линейки прокрутки не генерируют сообщения WM_COMMAND. Вместо него линейки прокрутки – независимо от того, являются ли они частью окна или отдельными элементами управления – генерируют либо WM_HSCROLL, либо WM_VSCROLL для горизонтальных и вертикальных линеек соответственно. При этом младшее слово wParam содержит код, который определяет действие, выполненное над линейкой прокрутки, a lParam – дескриптор линейки прокрутки. Для линеек прокрутки, являющихся частью окна, lParam равен 0.
Как уже упоминалось, LOWORD(wParam) содержит код действия, произведенного над линейкой прокрутки. Ниже перечислены некоторые типы таких действий:
SB_LINEUP
SB_LINEDOWN
SB_PAGEUP
SB_PAGEDOWN
SB_THUMBPOSITION
SB_THUMBTRACK
При изменении состояния линейки прокрутки на один шаг прокрутки в программу посылается один из кодов: SB_LINEUP или SB_LINEDOWN. Коды SB_PAGEUP и SB_PAGEDOWN используются при изменении состояния линейки прокрутки на страницу вверх или вниз. Код SB_THUMBPOSITION передается при изменении позиции слайдера (бегунка – подвижного элемента линейки прокрутки), а код SB_THUMBTRACK – при его перемещении. Это позволяет отслеживать перемещение слайдера и реагировать на этот процесс. При посылке кодов SB_THUMBPOSITION и SB_THUMBTRACK старшее слово параметра wParam содержит текущую позицию слайдера.
Установка диапазона прокрутки. Перед тем, как использовать линейку, необходимо установить для нее диапазон прокрутки, который определяет количество шагов прокрутки между крайними позициями слайдера. По умолчанию линейки прокрутки, использующиеся как часть окна, имеют диапазон от 0 до 100, линейки же, использующиеся как элементы управления, — от 0 до 0, поэтому для таких линеек нужно сначала явно задать диапазон прокрутки. С этой целью используется функция API SetScrollRange():
BOOL SetScrollRange(HWND hwnd, int which, int min,
int max, BOOL repaint) ;
Здесь hwnd – дескриптор, идентифицирующий линейку прокрутки. Для линеек прокрутки, использующихся как часть окна, hwnd должен быть дескриптором этого окна, а для элементов управления – дескриптором самого элемента. (Вспомните, линейки прокрутки передают свои дескрипторы в lParam.) Параметр which задает тип линейки прокрутки, для которой задается диапазон. Если линейки прокрутки используются как часть окна, для вертикальных линеек этот параметр должен равняться SB_VERT, а для горизонтальных – SB_HORZ. Для лийеек прокрутки, используемых как элементы управления, этот параметр должен быть SB_CTL. Значения min и max определяют диапазон прокрутки и могут задаваться в пределах от 0 до 32767. Значение параметра repaint определяет, должна ли линейка прокрутки перерисовываться при установке диапазона. Если он равен TRUE, то после установки диапазона линейка прокрутки перерисовывается, а если FALSE – перерисовка не выполняется. Функция возвращает ненулевое значение при успешном завершении и нуль при возникновении ошибки.
Установка позиции слайдера на линейке прокрутки. Линейки прокрутки всегда управляются программой. Поэтому Ваша программа должна при необходимости самостоятельно устанавливать позицию слайдера. Для этого используется функция API SetScrollPos(), прототип которой имеет следующий вид:
int SetScrollPos(HWND hwnd, int which, int pos,
BOOL repaint);
Здесь hwnd – дескриптор, идентифицирующий линейку прокрутки. Для линеек прокрутки, использующихся как часть окна, hwnd должен быть дескриптором этого окна, а для элементов управления – дескриптором этой линейки. Значение which определяет тип линейки прокрутки, для которой устанавливается позиция слайдера. В случае, если линейка прокрутки используется как часть окна, этот параметр должен быть SB_VERT или SB_HORZ для вертикальной или горизонтальной линейки соответственно. Для линеек прокрутки, используемых как элементы управления, этот параметр должен быть SB_CTL. Значение pos определяет позицию слайдера, которая должна быть установлена, и должно быть задано в пределах установленного диапазона прокрутки. Параметр repaint определяет, должна ли линейка прокрутки быть перерисована после установки позиции слайдера. Если он равен TRUE, то линейка прокрутки будет перерисована, а если FALSE, то нет.
Пример 7-5. Ниже приводится небольшая программа создания линейки прокрутки и обработки ее сообщений. Для этой программы необходим следующий файл ресурсов:
// Демонстрация линейки прокрутки
#include <Windows.h>
#include "Scroll.h"
MYMENU MENU
{
MENUITEM "&Прокрутка", IDM_DIALOG1
MENUITEM "Помощь", IDM_HELP
}
MYMENU ACCELERATORS
{
VK_F1, IDM_HELP, VIRTKEY
VK_F2, IDM_DIALOG1, VIRTKEY
}
MYDB DIALOG 18, 18, 142, 92
CAPTION "Работа с прокруткой"
STYLE DS_MODALFRAME|WS_POPUP|WS_CAPTION|WS_SYSMENU
{
GROUPBOX "Позиция слайдера",ID_GB1, 1, 1, 72, 30
SCROLLBAR ID_SB1, 130, 10, 10, 70,
SBS_VERT|WS_TABSTOP
}
Нужно также создать файл определений Sscroll.h:
#define IDM_DIALOG1 100
#define IDM_HELP 101
#define ID_SB1 102
#define ID_GB1 103
Ниже приводится текст программы работы с линейкой прокрутки. Эта программа обрабатывает сообщения SB_LINEUP, SB_LINEDOWN, SB_PAGEUP, SB_PAGE-DOWN, SB_THUMBPOSITION и SB_THUMBTRACK в соответствии с перемещениями слайдера. Текущая позиция слайдера отображается в группе Позиция слайдера. Отображаемое значение тем или иным способом будет изменяться при перемещении слайдера.
// Демонстрация линейки прокрутки
#include <Windows.h>
#include <String.h>
#include <Stdio.h>
#include "Scroll.h"
#define RANGEMAX 50
LRESULT CALLBACK WindowFunc(HWND,UINT,WPARAM,LPARAM);
BOOL CALLBACK DialogFunc(HWND,UINT,WPARAM,LPARAM);
char szWinName[]="МоеОкно"; // Имя класса окна
HINSTANCE hInst;
int WINAPI WinMain(HINSTANCE hThisInst,
HINSTANCE hPrevInst,
LPSTR lpszArgs,
int nWinMode)
{
HWND hwnd;
MSG msg;
WNDCLASS wcl;
HACCEL hAccel;
// Определить класс окна
wcl.hInstance=hThisInst; // Дескриптор приложения
wcl.lpszClassName=szWinName; // Имя класса окна
wcl.lpfnWndProc=WindowFunc; // Функция окна
wcl.style=0; // Стиль по умолчанию
wcl.hIcon=LoadIcon(NULL,IDI_APPLICATION); // Иконка
wcl.hCursor=LoadCursor(NULL,IDC_ARROW); // Курсор
wcl.lpszMenuName="MYMENU"; // Меню
wcl.cbClsExtra=0; // Без дополнительной
wcl.cbWndExtra=0; // информации
wcl.hbrBackground= // Белый фон
(HBRUSH)GetStockObject(WHITE_BRUSH);
if(!RegisterClass(&wcl)) // Зарегистр. класс окна
return 0;
hwnd=CreateWindow(szWinName, // Теперь создать окно
"Линейка прокрутки",
WS_OVERLAPPEDWINDOW, // Стиль
CW_USEDEFAULT, // Х-координата
CW_USEDEFAULT, // Y-координата
CW_USEDEFAULT, // Ширина
CW_USEDEFAULT, // Высота
HWND_DESKTOP, // Нет родит. окна
NULL, // Нет меню
hThisInst, // Дескрип. приложения
NULL); // Без дополн. аргументов
hInst=hThisInst; // Дескрип. текущ. приложения
// Загрузить акселераторы
hAccel=LoadAccelerators(hThisInst,"MYMENU");
ShowWindow(hwnd,nWinMode); // Показать окно
UpdateWindow(hwnd); // Перерисовать содержимое
while(GetMessage(&msg,NULL,0,0))
{ // Запустить цикл обработки сообщений
if(!TranslateAccelerator(hwnd,hAccel,&msg))
{
TranslateMessage(&msg); // Исп. клавиатуры
DispatchMessage (&msg); // Возврат к Windows
}
}
return msg.wParam;
}
// Следующая функция вызывается операционной системой
// Windows и получает в качестве параметров сообщения
// из очереди сообщений данного приложения
LRESULT CALLBACK WindowFunc(HWND hwnd,
UINT message,
WPARAM wParam,
LPARAM lParam)
{
switch(message)
{
case WM_COMMAND:
switch(LOWORD(wParam))
{
case IDM_DIALOG1:
DialogBox(hInst,"MYDB",
hwnd,DialogFunc);
break;
case IDM_HELP:
MessageBox(hwnd,"Помощь","",MB_OK);
break;
}
break;
case WM_DESTROY: // Завершение программы
PostQuitMessage(0);
break;
default:
// Все сообщения, не обрабатываемые в данной
// функции, направляются на обработку по
// умолчанию
return DefWindowProc(hwnd,message,
wParam,lParam);
}
return 0;
}
// Простая функция диалога
BOOL CALLBACK DialogFunc(HWND hdwnd,
UINT message,
WPARAM wParam,
LPARAM lParam)
{
char str[255];
static int pos=0;
HDC hdc;
switch(message)
{
case WM_COMMAND:
switch(LOWORD(wParam))
{
case IDCANCEL:
EndDialog(hdwnd,0);
return 1;
}
break;
case WM_VSCROLL:
SetScrollRange((HWND)lParam, SB_CTL, 0,
RANGEMAX, 1);
switch(LOWORD(wParam))
{
case SB_LINEDOWN:
pos++;
if(pos > RANGEMAX)
pos=RANGEMAX;
SetScrollPos((HWND)lParam, SB_CTL,
pos, 1);
hdc=GetDC(hdwnd);
sprintf(str, "%d", pos);
TextOut(hdc, 55, 30, " ", 4);
TextOut(hdc, 55, 30, str, strlen(str));
ReleaseDC(hdwnd, hdc);
return 1;
case SB_LINEUP:
pos--;
if(pos < 0)
pos=0;
SetScrollPos((HWND)lParam, SB_CTL,
pos, 1);
hdc=GetDC(hdwnd);
sprintf(str, "%d", pos);
TextOut(hdc, 55, 30, " ", 4);
TextOut(hdc, 55, 30, str, strlen(str));
ReleaseDC(hdwnd, hdc);
return 1;
case SB_THUMBPOSITION:
pos=HIWORD(wParam); // Текущая позиция
SetScrollPos((HWND)lParam, SB_CTL,
pos, 1);
hdc=GetDC(hdwnd);
sprintf(str, "%d", pos);
TextOut(hdc, 55, 30, " ", 4);
TextOut(hdc, 55, 30, str, strlen(str));
ReleaseDC(hdwnd, hdc);
return 1;
case SB_THUMBTRACK:
pos=HIWORD(wParam); // Текущая позиция
SetScrollPos((HWND)lParam, SB_CTL,
pos, 1);
hdc=GetDC(hdwnd);
sprintf(str, "%d", pos);
TextOut(hdc, 55, 30, " ", 4);
TextOut(hdc, 55, 30, str, strlen(str));
ReleaseDC(hdwnd, hdc);
return 1;
case SB_PAGEDOWN:
pos += 5;
if(pos > RANGEMAX)
pos=RANGEMAX;
SetScrollPos((HWND)lParam, SB_CTL,
pos, 1);
hdc=GetDC(hdwnd);
sprintf(str, "%d", pos);
TextOut(hdc, 55, 30, " ", 4);
TextOut(hdc, 55, 30, str, strlen(str));
ReleaseDC(hdwnd, hdc) ;
return 1;
case SB_PAGEUP:
pos -= 5;
if(pos < 0)
pos= 0;
SetScrollPos((HWND)lParam, SB_CTL,
pos, 1);
hdc=GetDC(hdwnd);
sprintf(str, "%d", pos);
TextOut(hdc, 55, 30, " ", 4);
TextOut(hdc, 55, 30, str, strlen(str));
ReleaseDC(hdwnd, hdc);
return 1;
}
}
return 0;
}
Рис. 7.4. Окно диалога с линейкой прокрутки
На рис. 7.4 представлен результат работы этой программы. Заметьте, что позиция слайдера отображается путем вывода текста в рабочую область окна диалога при помощи вызова TextOut(). Хотя диалог и является окном специального типа, он остается окном, с которым можно делать почти все то же, что и с главным окном.
Многие начинающие Windows-программисты часто считают, что линейки прокрутки использовать сложно. На самом деле линейка прокрутки является одним из простейших элементов управления в Windows.
В следующей главе более подробно изложены вопросы, связанные с выводом в окне текстовых строк.
*