
- •Уп. 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.3. Простейшие полосы прокрутки
В качестве примера рассмотрим окно стиля SBS_SIZEBOX. Слово "простейшая" означает, что приложение лишь создает такую полосу, всю работу выполняет функция окна полосы.
Представим, что при создании окна получена полоса прокрутки стиля SBS_SIZEBOX. Например, следующий оператор создает такую полосу размером 16*16 пикселей в точке с координатами (100,100):
CreateWindow("scrollbar", NULL,
WS_CHILD | WS_VISIBLE | SBS_SIZEBOX,
100, 100, 16, 16, hwnd, (HMENU)0, hInstance, NULL);
В точке с координатами (100, 100) рабочей области окна hwnd постоянно будет находиться серый прямоугольник размером 16*16 пикселей. Если курсор мыши поместить над прямоугольником полосы прокрутки, нажать на левую клавишу и перемещать мышь, то нижняя и правая рамки окна приложения повторяют движение курсора. Если отпустить клавишу мыши, то эти рамки останутся в том положении, в котором находились в момент отжатия клавиши.
Полоса прокрутки стиля SBS_SIZEBOX работоспособна без помощи родительского окна. Она обходится без идентификатора и дескриптора окна. Но такая "простота" порождает неудобства. Например, в окне постоянно находится некий серый прямоугольник или его позиция не всегда удовлетворяет потребностям пользователя. Чтобы избежать таких неудобств, описывают дескриптор полосы и с его помощью управляют состоянием прямоугольника. То есть полоса прокрутки подчиняется обычным функциям управления окнами.
Приложение на следующем листинге свободно от этих недостатков.
Листинг 2.3. Полоса прокрутки стиля SBS_SIZEBOX
#include <windows.h>
BOOL RegClass(WNDPROC, LPCTSTR, UINT);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
HINSTANCE hInstance;
TCHAR szClassName[] = TEXT("AppClass");
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,
TEXT("Прокрутка окна"),
WS_OVERLAPPEDWINDOW | WS_VISIBLE,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
0, 0, hInstance, NULL))) return FALSE;
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 hScroll;
switch (msg)
{
case WM_CREATE:
{
hScroll = CreateWindow(TEXT("scrollbar"),
NULL, WS_CHILD | SBS_SIZEBOX,
0, 0, 16, 16,
hwnd, (HMENU)0, hInstance, NULL);
if(!hScroll) MessageBox(NULL, TEXT("Error"), TEXT("scrollbar"), NULL);
return 0;
}
case WM_SIZE:
{
ShowWindow(hScroll, SW_HIDE);
return 0;
}
case WM_LBUTTONDOWN:
{
MoveWindow(hScroll, LOWORD(lParam)-8, HIWORD(lParam)-8, 16, 16, TRUE);
ShowWindow(hScroll, SW_NORMAL);
return 0;
}
case WM_DESTROY: { PostQuitMessage(0); return 0; }
}
return DefWindowProc(hwnd, msg, wParam, lParam);
}
В левом верхнем углу рабочей области окна создана невидимая полоса прокрутки стиля WS_CHILD | SBS_SIZEBOX.
После нажатия левой клавиши мыши на том месте рабочей области, где находится курсор мыши, появится серый прямоугольник размером 16*16 пикселей. С этой целью полоса прокрутки сначала перемещается в точку с координатами (LOWORD(lParam), HIWORD(lParam)):
MoveWindow(hScroll, LOWORD(lParam)-8, HIWORD(lParam)-8, 16, 16, TRUE);
Добавка -8 "совмещает" центр прямоугольника с позицией курсора мыши. Затем полоса переводится в видимое состояние:
ShowWindow(hScroll,SW_NORMAL);
Если курсор мыши поместить над этим серым прямоугольником, нажать на левую клавишу и перемещать курсор мыши, то нижняя и правая рамки окна приложения будут повторять движение курсора. Если отпустить клавишу мыши, эти рамки останутся в том положении, в котором находились в момент отжатия клавиши.
После изменения размеров окна полоса прокрутки переводится в невидимое состояние:
ShowWindow(hScroll,SW_HIDE);
Так же создают полосу стиля SBS SIZEGRIP. С ней работают так же, как и с полосой стиля SBS_SIZEBOX. Но она не изменяет размеры родительского окна, а выделяет прямоугольную область в рабочей области.