Как создать вертикальную прокрутку в основном окне WinApi
Подскажите пожалуйста, как создать рабочую вертикальную полосу прокрутки при создании основного окна средствами WinApi ? Я создаю окно через CreateWindow указываю флаг WS_VSCROLL, сама полоса прокрутки с бегунком появляется, но она по факту почему то не рабочая, потому что реально содержимое клиентской области окна она не прокручивает. Хотя, еслиe в этом же окне создать дочернее окно класса "edit" и поставить такой же флаг WS_VSCROLL, то в этом окне прокрутка нормально работает текст прокручивается. Не могу понять, что я не так делаю.
Ответы (1 шт):
Прокрутку содержимого нужно выполнять самостоятельно (с помощью функции ScrollWindow или ScrollWindowEx) при получении сообщения WM_VSCROLL. Также нужно отслеживать изменение размеров окна и/или содержимого, чтобы устанавливать scrollbar-у соответствующие этим размерам параметры (диапазон прокрутки и размер страницы).
Для примера предположим что содержимое не меняется, поэтому будем отслеживать только размер окна:
case WM_SIZE: {
SCROLLINFO scrInfo;
scrInfo.cbSize = sizeof(SCROLLINFO);
scrInfo.nPage = HIWORD(lParam); //размер страницы устанавливаем равным высоте окна
scrInfo.nMin = 0; //диапазон прокрутки устанавливаем по размеру содержимого
scrInfo.nMax = CONTENT_HEIGHT; //(вместо CONTENT_HEIGHT подставь нужное значение)
scrInfo.fMask = SIF_RANGE | SIF_PAGE; //применяем новые параметры
SetScrollInfo(hwnd, SB_VERT, &scrInfo, TRUE);
}
return 0;
прокрутка содержимого:
case WM_VSCROLL: {
SCROLLINFO scrInfo;
scrInfo.cbSize = sizeof(SCROLLINFO);
scrInfo.fMask = SIF_ALL; //получаем текущие параметры scrollbar-а
GetScrollInfo(hwnd, SB_VERT, &scrInfo);
int currentPos = scrInfo.nPos; //запоминаем текущее положение содержимого
switch (LOWORD(wParam)) { //определяем действие пользователя и изменяем положение
case SB_LINEUP: //клик на стрелку вверх
scrInfo.nPos -= 1;
break;
case SB_LINEDOWN: //клик на стрелку вниз
scrInfo.nPos += 1;
break;
case SB_THUMBTRACK: //перетаскивание ползунка
scrInfo.nPos = scrInfo.nTrackPos;
break;
default: return 0; //все прочие действия (например нажатие PageUp/PageDown) игнорируем
}
scrInfo.fMask = SIF_POS; //пробуем применить новое положение
SetScrollInfo(hwnd, SB_VERT, &scrInfo, TRUE);
GetScrollInfo(hwnd, SB_VERT, &scrInfo); //(см. примечание ниже)
int yScroll = currentPos - scrInfo.nPos; // вычисляем величину прокрутки
ScrollWindow(hwnd, 0, yScroll, NULL, NULL); //выполняем прокрутку
}
return 0;
Примечание: функция SetScrollInfo автоматически исправляет выход nPos из диапазона nMin...nMax, так что фактически установленное значение nPos может отличаться от запрошенного. Поэтому там и нужен повторный вызов GetScrollInfo.