API и FreeBasic. (дочерние окна-Pager)
Pager - это один из контролов, по которому оказалось трудно найти информацию на русском языке. По своей сути данный контрол является контейнером для других дочерних окон, не имеющих достаточного места. Pager позволяет делать скроллинг не умещающихся контролов. Чаще всего Pager применяют для скроллинга тулбара из-за того, что некоторым пользователям кнопок на тулбаре может не хватать. Но можно использовать для любого контрола. Как раз в нашем примере для простоты мы в контейнер поместим простую кнопку.
Иногда бывает, что в заголовках к компилятору FreeBasic содержатся ошибки или попросту не объявлены какие-то константы, декларации и пр. Я устал на оф. сайте доказывать их нужность или правильность... Так и в этот раз была найдена ошибка с помощью одного из пользователей форума SARG (создателя FbDebugger) в структуре NMPGSCROLL. Мы попросту в примере ниже объявим эту структуру правильно под другим именем. И конечно объявим нужные нам константы.
Pager контрол имеет свойство выставлять размер дочернего элемента автоматически по своему размеру. В результате чего отпадает надобность заботиться о размерах его дочернего элемента. Так например, если мы изменим размер Pager с помощью MoveWindow , то автоматически изменятся размеры его дочернего элемента.
Создается Pager как обычно функцией CreateWindowEx с классом окна SysPager. В его стиле должен быть указан один из стилей PGS_HORZ или PGS_VERT , которые означают горизонтальную или вертикальную прокрутку соответственно. Далее создается его дочерний элемент и ему в функции CreateWindowEx в девятом параметре указывается родительским окном хендл Pager. Следом должно быть послано сообщение PGM_SETCHILD контролу Pager с указанием хендла дочернего элемента в параметре LPARAM.
Для того чтобы появилась возможность скроллинга дочернего элемента Pager, нужно обработать сообщение WM_NOTIFY с его кодами извещения PGN_CALCSIZE и PGN_SCROLL. По первому коду извещения устанавливаются размеры рабочей поверхности скроллинга в пикселях. По второму извещению ставится шаг скроллинга в пикселях.
По получению извещения PGN_CALCSIZE , в параметре LPARAM будет предоставлен указатель на структуру NMPGCALCSIZE , в параметр iWidth или iHeight которой (в зависимости от прокрутки, которая указывается изначально при создании Pager), нужно указать величину размера прокручиваемой поверхности.
При получении извещения PGN_SCROLL, система передаст нам указатель на структуру NMPGSCROLL в параметре LPARAM. В один из параметров ( iScroll ) этой структуры (в нашем примере NMPGSCROLL2) , нужно указать смещение на сколько пикселей необходимо смещаться при нажатии на кнопку скроллинга.
И конечно пример для потверждения вышеописанного:
#INCLUDE "windows.bi" #INCLUDE "win/commctrl.bi" #IFNDEF PGN_SCROLL #DEFINE PGN_SCROLL (PGN_FIRST-1) #ENDIF #IFNDEF PGN_CALCSIZE #DEFINE PGN_CALCSIZE (PGN_FIRST-2) #ENDIF Type NMPGSCROLL2 Field=1 As NMHDR hdr As Short fwKeys As RECT rcParent As Integer iDir As Integer iXpos As Integer iYpos As Integer iScroll End Type Dim msg As MSG Dim As WNDCLASSEX wc Dim As String NameClass="MyClass" Dim As HINSTANCE Hinst=GetModuleHandle(0) ' Для систем Windows XP ' и может быть более ранних версий Windows ' нужен вызов функции InitCommonControlsEx ' для 100% загрузки comctl32.dll ' такой вот баг хрюши, ' кстати сказать далеко не единственный ' спасибо пользователю miver, что напомнил и помог ' дополнить исходный код Dim InitCtrlEx As InitCommonControlsEx InitCtrlEx.dwSize = Sizeof(InitCommonControlsEx) InitCtrlEx.dwICC = ICC_STANDARD_CLASSES InitCommonControlsEx(@InitCtrlEx) Function wndproc(hwnd As HWND, msg As Uinteger,_ wparam As WPARAM, lparam As LPARAM) As Integer Static As HWND hButton,hPager Select Case msg Case WM_CREATE hPager = CreateWindowEx( 0, "SysPager", 0,_ WS_CHILD+PGS_HORZ+WS_VISIBLE,_ 10, 10, 100, 20, hwnd, Cast(HMENU,1000), 0, 0) hButton = CreateWindowEx(0,"Button",_ "Это очень длинная кнопка",WS_VISIBLE Or WS_CHILD,_ 0,0,0,0,hPager,Cast(HMENU,1),0,0) SendMessage(hPager,PGM_SETCHILD,0,Cast(Lparam,hButton)) SendMessage(hPager,PGM_SETBKCOLOR,0, &hFF00FF) Case WM_NOTIFY Dim As NMHDR Ptr nmhdr = Cast(NMHDR Ptr,lParam) If nmhdr->code = PGN_CALCSIZE Then Dim As NMPGCALCSIZE Ptr nmcal = Cast(NMPGCALCSIZE Ptr,lParam) If nmcal->dwFlag = PGF_CALCWIDTH Then nmcal->iWidth = 200 Endif Elseif nmhdr->code = PGN_SCROLL Then Dim As NMPGSCROLL2 Ptr nmgs = Cast(NMPGSCROLL2 Ptr,lParam) nmgs->iScroll = 40 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_WINLOGO) .hCursor=LoadCursor(0,IDC_ARROW) .hbrBackground=Cast(HBRUSH,COLOR_WINDOWFRAME) .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,100,100,150,100,0,0,Hinst,0) While GetMessage(@msg,0,0,0) TranslateMessage(@msg) DispatchMessage(@msg) Wend
Дополнительно:
Стили Pager:
- PGS_AUTOSCROLL - Пейджер будет прокручиваться, когда пользователь наводит курсор мыши на одну из кнопок прокрутки.
- PGS_DRAGNDROP - The contained window can be a drag-and-drop target. The pager control will automatically scroll if an item is dragged from outside the pager over one of the scroll buttons.
- PGS_HORZ - Горизонтальный стиль прокрутки. Этот стиль не может быть совместим со стилем pgs_vert
- PGS_VERT - Вертикальный стиль прокрутки. Этот стиль не может быть совместим со стилем pgs_horz
Сообщения Pager:
- PGM_FORWARDMOUSE - Включение или отключение переадресации сообщения WM_MOUSEMOVE в окно, которое содержится в текущем элементе Pager
- PGM_GETBKCOLOR - Возвращает текущий цвет фона Pager
- PGM_GETBORDER - Возвращает текущий размер границы Pager
- PGM_GETBUTTONSIZE - Возвращает текущий размер кнопки Pager
- PGM_GETBUTTONSTATE - Получает состояние кнопки Pager
- PGM_GETDROPTARGET - Получает указатель на IDropTarget интерфейс Pager
- PGM_GETPOS - Возвращает текущую позицию прокрутки Pager
- PGM_RECALCSIZE - Вызывается, когда нужно пересчитать размер содержимого окна
- PGM_SETBKCOLOR - Устанавливает текущий цвет фона Pager
- PGM_SETBORDER - Устанавливает текущий размер границы Pager
- PGM_SETBUTTONSIZE - Устанавливает текущий размер кнопки Pager
- PGM_SETCHILD - Устанавливает контролу Pager дочернее окно
- PGM_SETPOS - Устанавливает текущую позицию прокрутки Pager
Получить больше информации о сообщениях Pager можно ЗДЕСЬ
содержание | назад | вперед