API и FreeBasic. (дочерние окна-ScrollBar)
ScrollBar - контрол, необходимый для прокручивания определенной области, вмещающей данные большие по размеру, чем видимая область. Часть дочерних контролов имеют встроенные полосы прокрутки (EDIT, TREEVIEW, LISTVIEW...). Вызываются и прокручиваются они автоматически, когда область вмещенных данных вылезает за видимую часть. Но для обычных родительских окон автоматически работающих полос прокрутки не предусмотрено. В этом случае программист сам реализует данную возможность. Так же можно создать самостоятельный дочерний ScrollBar контрол , для которого так же нужно вручную реализовывать прокрутку. Надо сказать, что компания Майкрософт максимально облегчила задачу, поэтому реализация не сложна сама по себе.
Начнем с создания полос прокрутки для родительских окон. Различие таких полос от полос дочерних окон в том, что они не реагируют на действия клавиатуры, только на мышь. В первую очередь чтобы активировать данные полосы прокрутки для родительских окон, надо указать стили при создания окна WS_HSCROLL и\или WS_VSCROLL (горизонтальная и вертикальная соответственно). Можно использовать любую, можно использовать обе. По умолчанию диапазон прокрутки равен от 0 до 100, но его можно менять с помощью специальной функции SetScrollRange. Функция имеет пять параметров:
- hWnd - хендл окна для которого выставлен ScrollBar или хендл контрола ScrollBar
- nBar - флаг , определяющий прокрутку, может быть:
- SB_HORZ - горизонтальная
- SB_VERT - вертикальная
- SB_CTL - определяет, что ScrollBar контрол дочернее окно, созданное программистом. В параметре Hwnd должен быть указан хендл этого контрола
- nMinPos - минимальный диапазон прокрутки
- nMaxPos - максимальный диапазон прокрутки
- bRedraw - флаг перерисовки контрола ScrollBar
Как вы поняли данную функцию можно использовать как для родительского окна, так для вами созданного самостоятельного дочернего контрола ScrollBar.
Так же для получения диапазонов есть обратная функция GetScrollRange:
- hWnd - хендл окна для которого выставлен ScrollBar или хендл контрола ScrollBar
- nBar - флаг , определяющий прокрутку, может быть:
- SB_HORZ - горизонтальная
- SB_VERT - вертикальная
- SB_CTL - определяет, что ScrollBar контрол дочернее окно, созданное программистом. В параметре Hwnd должен быть указан хендл этого контрола
- nMinPos - адрес переменной для получения минимального диапазона прокрутки
- nMaxPos - адрес переменной для получения максимального диапазона прокрутки
Сам по себе ползунок ScrollBar двигаться не будет, но при действиях произведенных на нем пользователем, в процедуру родительского окна посылаются сообщения WM_VSCROLL и WM_HSCROLL. Их и должен отловить программист. В первую очередь нужно принять во внимание уведомление в младшем слове(loword) параметра WPARAM. Список уведомлений:
- SB_ENDSCROLL - конец скроллинга (отпущена кнопки мыши , удерживающая стрелку или полосу прокрутки контрола)
- SB_LEFT - скроллинг в левом углу (только для дочерних контролов)
- SB_RIGHT - скроллинг в правом углу (только для дочерних контролов)
- SB_LINELEFT - сдвиг на одну колонку влево
- SB_LINERIGHT - сдвиг на одну колонку вправо
- SB_PAGELEFT - сдвиг на одну страницу влево
- SB_PAGERIGHT - сдвиг на одну страницу вправо
- SB_THUMBPOSITION - закончено передвижение бегунка, кнопка мыши отпущена
- SB_THUMBTRACK - бегунок перемещается
- SB_BOTTOM - Скроллинг в нижнем углу (только для дочерних контролов)
- SB_TOP - скроллинг в верхнем углу (только для дочерних контролов)
- SB_LINEDOWN - сдвиг на одну строчку вниз
- SB_LINEUP - сдвиг на одну строчку вверх
- SB_PAGEDOWN - сдвиг на одну страницу вниз
- SB_PAGEUP - сдвиг на одну страницу вверх
Если уведомление будет равно SB_THUMBPOSITION или SB_THUMBTRACK, то в старшем слове (hiword) параметра WPARAM будет позиция ползунка, во всех остальных случаях hiword(wparam) не используется. Параметр LPARAM будет хранить хендл ScrollBar если конечно он реализован как дочернее окно.
Для того чтобы сместить ползунок существует функция SetScrollPos. Она имеет 4 параметра:
- hWnd - хендл окна для которого выставлен ScrollBar или хендл контрола ScrollBar
- nBar - флаг , определяющий прокрутку, может быть:
- SB_HORZ - горизонтальная
- SB_VERT - вертикальная
- SB_CTL - определяет, что ScrollBar контрол дочернее окно, созданное программистом. В параметре Hwnd должен быть указан хендл этого контрола
- nPos - новая позиция ползунка
- bRedraw - флаг перерисовки контрола ScrollBar
Обратная функция , возвращающая расположения ползунка GetScrollPos имеет два параметра:
- hWnd - хендл окна для которого выставлен ScrollBar или хендл контрола ScrollBar
- nBar - флаг , определяющий прокрутку, может быть:
- SB_HORZ - горизонтальная
- SB_VERT - вертикальная
- SB_CTL - определяет, что ScrollBar контрол дочернее окно, созданное программистом. В параметре Hwnd должен быть указан хендл этого контрола
Так же для установки и получения различных параметров (позиции ползунка, размеры страниц, диапазонов) ScrollBar есть функции GetScrollInfo и SetScrollInfo Использование их основывается на заполнении структуры SCROLLINFO . Так например для получения размера страницы нужно заполнить поля структуры: cbSize (размер структуры), fMask (указать маску SIF_PAGE), nPage (адрес переменной куда будет помещен размер страницы). Далее вызвать функцию GetScrollInfo и в 3 параметре функции передать указатель на структуру. Параметры функций GetScrollInfo и SetScrollInfo очень схожи с вышеописанными функциями, думаю сложностей быть не должно. Но если есть вопросы, задаем на форуме.
После того, как стало понятно как передвигать ползунок, становится наверно не очень понятно как же будет смещаться сама скроллируемая область. Тут важно понять принцип. Все движения скроллируемой области напрямую зависят от позиции ползунка. К примеру у нас рисунок до скроллинга находится в координатах 100х100 и мы сдвинули ползунок на 10 позиций вниз, то рисунок должен подняться на 10 пикселей вверх (то есть в координаты 100х90). Отсюда при получении сообщения WM_VSCROLL и соответствующих уведомлений нам нужно не только установить значение для ползунка с помощью SetScrollPos, но и установить новые координаты для рисунка и перерисовать видимую область.
Что касается самостоятельных дочерних контролов ScrollBar, то они как и все дочерние окна создаются с помощью функции CreateWindowEx, только с классом окна SCROLLBAR. Так же в стиле функции надо указать тип контрола (SB_HORZ - горизонтальный или SB_VERT - вертикальный). Для них можно строго определить нужный размер. Как я и писал выше они хорошо реагируют не только на мышь но и на клавиатуру, в том числе есть возможность переключаться между контролами по клавише TAB при установке стиля WS_TABSTOP.
А теперь пару примеров:
#INCLUDE "windows.bi" Dim msg As MSG Dim As WNDCLASSEX wc Dim As String NameClass="MyClass" Dim As HINSTANCE Hinst=GetModuleHandle(0) Function wndproc(hwnd As HWND, msg As Uinteger,_ wparam As WPARAM, lparam As LPARAM) As Integer Static Button As HWND Static As Integer nPos, Ypos = 40 Select Case msg Case WM_CREATE Button = CreateWindowEx(0,"button","Большая кнопка",WS_VISIBLE Or WS_CHILD,40,Ypos,200,400,hwnd,Cast(HMENU,1),0,0) SetScrollRange(hwnd,SB_VERT,0,400,TRUE) Case WM_VSCROLL If Loword(WPARAM) = SB_THUMBPOSITION Or Loword(WPARAM) = SB_THUMBTRACK Then nPos = Hiword(wParam) MoveWindow(Button,40,Ypos - nPos,200,400,TRUE) SetScrollPos(hwnd,SB_VERT,nPos,TRUE) Endif Case WM_DESTROY PostQuitMessage(0) End Select Return DefWindowProc(hwnd,msg,wparam,lparam) End Function With wc .cbSize=SizeOf(WNDCLASSEX) .style=CS_HREDRAW Or CS_VREDRAW .lpfnWndProc=@wndproc .hInstance=Hinst .hIcon=LoadIcon(0,IDI_QUESTION) .hCursor=LoadCursor(0,IDC_ARROW) .hbrBackground=Cast(HBRUSH,COLOR_WINDOW) .lpszClassName=StrPtr(NameClass) .hIconSm=.hIcon End With If RegisterClassEx(@wc)=0 Then Print "Register error, press any key" Sleep End Endif CreateWindowEx(0,NameClass,"Окно со скроллингом",_ WS_VISIBLE Or WS_OVERLAPPEDWINDOW Or WS_VSCROLL,10,10,300,200,0,0,Hinst,0) While GetMessage(@msg,0,0,0) TranslateMessage(@msg) DispatchMessage(@msg) Wend
#INCLUDE "windows.bi" Dim msg As MSG Dim As WNDCLASSEX wc Dim As String NameClass="MyClass" Dim As HINSTANCE Hinst=GetModuleHandle(0) Function wndproc(hwnd As HWND, msg As Uinteger,_ wparam As WPARAM, lparam As LPARAM) As Integer Static As HWND Button, Scroll Static As Integer nPos, Ypos = 40 Select Case msg Case WM_CREATE Button = CreateWindowEx(0,"button","Большая кнопка",WS_VISIBLE Or WS_CHILD,40,Ypos,200,400,hwnd,Cast(HMENU,1),0,0) Scroll = CreateWindowEx(0,"SCROLLBAR","",WS_VISIBLE Or WS_CHILD Or SB_VERT,10,10,20,100,hwnd,Cast(HMENU,2),0,0) SetScrollRange(Scroll,SB_CTL,0,400,TRUE) Case WM_VSCROLL Select Case Loword(WPARAM) Case SB_LINEUP nPos = GetScrollPos(Scroll,SB_CTL) nPos-=1 SetScrollPos(Scroll,SB_CTL,nPos,TRUE) Case SB_LINEDOWN nPos = GetScrollPos(Scroll,SB_CTL) nPos+=1 SetScrollPos(Scroll,SB_CTL,nPos,TRUE) Case SB_PAGEUP nPos = GetScrollPos(Scroll,SB_CTL) nPos-=10 SetScrollPos(Scroll,SB_CTL,nPos,TRUE) Case SB_PAGEDOWN nPos = GetScrollPos(Scroll,SB_CTL) nPos+=10 SetScrollPos(Scroll,SB_CTL,nPos,TRUE) Case SB_THUMBPOSITION,SB_THUMBTRACK nPos = Hiword(wParam) SetScrollPos(Scroll,SB_CTL,nPos,TRUE) End Select MoveWindow(Button,40,Ypos - nPos,200,400,TRUE) Case WM_DESTROY PostQuitMessage(0) End Select Return DefWindowProc(hwnd,msg,wparam,lparam) End Function With wc .cbSize=SizeOf(WNDCLASSEX) .style=CS_HREDRAW Or CS_VREDRAW .lpfnWndProc=@wndproc .hInstance=Hinst .hIcon=LoadIcon(0,IDI_QUESTION) .hCursor=LoadCursor(0,IDC_ARROW) .hbrBackground=Cast(HBRUSH,COLOR_WINDOW) .lpszClassName=StrPtr(NameClass) .hIconSm=.hIcon End With If RegisterClassEx(@wc)=0 Then Print "Register error, press any key" Sleep End Endif CreateWindowEx(0,NameClass,"Окно со скроллингом",_ WS_VISIBLE Or WS_OVERLAPPEDWINDOW,10,10,300,200,0,0,Hinst,0) While GetMessage(@msg,0,0,0) TranslateMessage(@msg) DispatchMessage(@msg) Wend
содержание | назад | вперед