
- •Уп. 2. Органы управления в приложениях Win32
- •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.3.6. Пример обработки сообщений от полос прокрутки
- •2.3.7. Новые функции управления полосами прокрутки
- •2.3.8. Пример окна приложения с полосой просмотра
- •2.4. Редактор текста
- •2.4.1. Создание редактора
- •2.4.2. Сообщения для редактора текста
- •2.4.3. Сообщения от редактора текста
- •2.4.4. Пример работы с однострочным редактором
- •2.5. Списки строк
- •2.5.1. Создание списка
- •2.5.2. Сообщения от списка
- •2.5.3. Сообщения для списка
- •2.5.4. Пример работы со списком
- •2.6. Комбинированный список
- •2.6.1. Создание комбинированного списка
- •2.6.2. Коды извещения
- •2.6.3. Сообщения для комбинированного списка
- •2.6.4. Пример работы с комбинированным списком
- •Контрольные вопросы
- •Упражнения
- •Приложение 2
2.3.6. Пример обработки сообщений от полос прокрутки
Задача. В окне приложения создать две полосы прокрутки (горизонтальную и вертикальную) для управления размерами двух прямоугольников (черного по горизонтали и темно-серого по вертикали).
Решение данной задачи полностью происходит в функции окна приложения, представленного листингом 2.4.
Листинг 2.4. Полоса прокрутки – орган управления
#include <windows.h>
BOOL RegClass(WNDPROC, LPCTSTR, UINT);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
HINSTANCE hInstance;
TCHAR szClassName[] = TEXT("ScrollClass");
TCHAR szTitle[] = TEXT("Полоса прокрутки – орган управления");
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpszCmdLine, int nCmdShow)
{
MSG msg;
HWND hwnd;
hInstance = hInst;
if (!RegClass(WndProc, szClassName, COLOR_WINDOW))
return FALSE;
if (!(hwnd = CreateWindow(szClassName, szTitle, WS_OVERLAPPEDWINDOW, 194, 50, 246, 350, 0, 0, hInstance, NULL)))
return FALSE;
ShowWindow(hwnd, SW_SHOWNORMAL);
UpdateWindow(hwnd);
while(GetMessage(&msg, 0, 0, 0))
DispatchMessage(&msg);
return msg.wParam;
}
BOOL RegClass(WNDPROC Proc, LPCTSTR szName, UINT brBackground)
{
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)(brBackground + 1);
wc.lpszMenuName = (LPCTSTR)NULL;
wc.lpszClassName = szName;
return (RegisterClass(&wc) != 0);
}
LRESULT CALLBACK WndProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
static HWND hxScroll, hxStatic, hyScroll, hyStatic;
static int nxPos, nxMin, nxMax, nyPos, nyMin, nyMax;
switch (msg)
{
case WM_CREATE:
{
hxScroll = CreateWindow(TEXT("scrollbar"), NULL,
WS_CHILD | WS_VISIBLE | SBS_HORZ,
20, 60, 200, 25, hwnd, (HMENU)-1, hInstance, NULL);
nxPos = 100; nxMin = 1; nxMax = 200;
SetScrollRange(hxScroll, SB_CTL, nxMin, nxMax, TRUE);
SetScrollPos(hxScroll, SB_CTL, nxPos, TRUE);
hxStatic = CreateWindow(TEXT("static"), NULL,
WS_CHILD | WS_VISIBLE | SS_BLACKRECT,
20, 40, nxPos, 15, hwnd, (HMENU)-1, hInstance, NULL);
hyScroll = CreateWindow(TEXT("scrollbar"), NULL,
WS_CHILD | WS_VISIBLE | SBS_VERT,
20, 100, 90, 200, hwnd, (HMENU)-1, hInstance, NULL);
nyPos = 100; nyMin = 1; nyMax = 200;
SetScrollRange(hyScroll, SB_CTL, nyMin, nyMax, TRUE);
SetScrollPos(hyScroll, SB_CTL, nyPos, TRUE);
hyStatic = CreateWindow(TEXT("static"), NULL,
WS_CHILD | WS_VISIBLE | SS_GRAYRECT,
130,100, 90, nyPos, hwnd, (HMENU)-1, hInstance, NULL);
return 0;
}
case WM_HSCROLL:
{
switch (LOWORD(wParam))
{
case SB_PAGERIGHT: { nxPos+=10; break; }
case SB_LINERIGHT: { nxPos+=1; break; }
case SB_PAGELEFT: { nxPos-=10; break; }
case SB_LINELEFT: { nxPos-=1; break; }
case SB_TOP: { nxPos = nxMin; break; }
case SB_BOTTOM: { nxPos = nxMax; break; }
case SB_THUMBPOSITION:
case SB_THUMBTRACK: { nxPos = HIWORD(wParam); break; }
default: break;
}
if (nxPos > nxMax) nxPos = nxMax;
if (nxPos < nxMin) nxPos = nxMin;
SetScrollPos(hxScroll, SB_CTL, nxPos, TRUE);
if (nxPos==nxMax)
EnableScrollBar(hxScroll, SB_CTL, ESB_DISABLE_RIGHT);
MoveWindow(hxStatic, 20,40, nxPos, 15, TRUE);
return 0;
}
case WM_VSCROLL:
{
switch (LOWORD(wParam))
{
case SB_PAGERIGHT: { nyPos+=10; break; }
case SB_LINERIGHT: { nyPos += 1; break; }
case SB_PAGELEFT: { nyPos-=10; break; }
case SB_LINELEFT: { nyPos-=1; break; }
case SB_TOP: { nyPos = nyMin; break; }
case SB_BOTTOM: { nyPos = nyMax; break; }
case SB_THUMBPOSITION:
case SB_THUMBTRACK: { nyPos = HIWORD(wParam); break; }
default: break;
}
if (nyPos > nyMax) nyPos = nyMax;
if (nyPos < nyMin) nyPos = nyMin;
SetScrollPos(hyScroll, SB_CTL, nyPos, TRUE);
MoveWindow(hyStatic, 130,100, 90, nyPos, TRUE);
return 0;
}
case WM_DESTROY: { PostQuitMessage(0); return 0;}
}
return DefWindowProc(hwnd, msg, wParam, lParam);
}
На этапе создания окна приложения создают горизонтальную полосу прокрутки нестандартных размеров и без идентификатора:
hxScroll = CreateWindow("scrollbar", NULL,
WS_CHILD | WS_VISIBLE | SBS_HORZ,
20, 60, 200, 25, hwnd, (HMENU)-1, hInstance, NULL);
Далее устанавливают диапазон перемещения и начальную позицию ползунка:
nxPos = 100;
nxMin = 1;
nxMax = 200;
SetScrollRange(hxScroll, SB_CTL, nxMin, nxMax, TRUE);
SetScrollPos(hxScroll, SB_CTL, nxPos, TRUE);
Затем создают статический орган – закрашенный прямоугольник черного цвета с шириной, равной позиции nxPos ползунка:
hxStatic = CreateWindow("static", NULL,
WS_CHILD | WS_VISIBLE | SS_BLACKRECT,
20, 40, nxPos, 15, hwnd, (HMENU)-1, hInstance,NULL);
Таким же образом создают вертикальную полосу прокрутки и прямоугольник темно-серого цвета.
После запуска приложения на экране появится окно, в рабочей области которого расположены элементы hxStatic, hxScroll, hyScroll и hyStatic (рис. 2.3).
Рис. 2.3. Пример управления полосами прокрутки
Рассмотрим, как работает горизонтальная полоса прокрутки.
При нажатии на кнопку на левом конце полосы поступает сообщение WM_HSCROLL с кодом SB_LINELEFT. При обработке этого сообщения значение nxPos уменьшается на единицу:
nxPos -= 1;
Далее ползунок устанавливают в новую позицию nxPos:
SetScrollPos(hxScroll, SB_CTL, nxPos, TRUE);
и перемещают черный прямоугольник – у окна hxScroll изменяют ширину:
MoveWindow(hxStatic, 20, 40, nxPos, 15, TRUE);
Так же обрабатывают и другие сообщения. Разница лишь в том, что при нажатии на область между кнопкой и ползунком происходит "постраничное" перелистывание – значение nxPos изменяется на 10. При плавном перемещении ползунка поступает сообщение с кодом SB_THUMBTRACK и текущая позиция определяется через старшее слово параметра wParam: nxPos = HIWORD(wParam). После плавной установки ползунка код действия равен SB_THUMBPOSITION и текущая позиция определяется через старшее слово параметра wParam: nxPos = HIWORD(wParam)
В текст включен пример блокирования правой кнопки горизонтальной полосы прокрутки:
if (nxPos==nxMax)
EnableScrollBar(hxScroll, SB_CTL, ESB_DISABLE_RIGHT);
Правая кнопка этой полосы блокируется при достижении крайней правой позиции, и нажатие на эту кнопку не вызывает никакой реакции. Вызов другой функции для этой полосы отменяет блокировку.
Параметры nxPos, nxMin и nxMax, а также шаг изменения значения nxPos на "позицию" или на "страницу" разработчик задает, исходя из потребностей решаемой задачи. В примере эти параметры выбраны с целью наглядного изменения размеров статических органов. В других задачах эти параметры могут быть другими. Например, значение "позиции" может быть равно средней ширине или высоте одного символа установленного шрифта при просмотре документов в окне.
Обработка сообщений от вертикальной полосы прокрутки происходит точно так же.