API и FreeBasic. (дочерние окна-Up-Down)

Up-Down - контрол, чаще всего используемый для изменения числовых значений с помощью подобия scrollbar , в котором как будто вырезали саму полосу и оставили только крайние кнопки. Я ни разу не видел , чтобы его использовали в таком виде. Обычно данный контрол комбинируют с другим контролом. Больше скажу, практически во всех случаях в паре с ним идут контролы EDIT или TAB . Прикрепив таким способом, оба контрола действуют как одно целое. Что касается примеров практического использования, то я не припомню ни один графический редактор без этого контрола. В частности, изменение размеров всегда возлагают на этот контрол.

Создать комбинированный контрол (Edit+Up-Down) можно как с помощью двух функций CreateWindowEx, так и связкой CreateWindowEx + CreateUpDownControl. Второй способ я считаю чуть более удобным, поскольку позволяет в параметрах CreateUpDownControl указать минимальный и максимальный диапазоны, а так же начальное текущее значение.

Приклепляемый контрол (EDIT) создается как обычно. Его создание описывалось в этой статье. Что касается Up-Down , то он создается на базе класса msctls_updown32. Если мы его создаем после прикрепляемого контрола EDIT и в стиле контрола Up-Down укажем UDS_AUTOBUDDY , то контрол автоматически прикрепится. Если нужно прикрепить независимо от порядка создания контролов, то можно послать сообщение UDM_SETBUDDY и в параметре WPARAM передать хендл приклеплямого контрола. Для того , чтобы не канителиться с координатами , важно указать автовыравнивание контрола с помощью стилей UDS_ALIGNRIGHT или UDS_ALIGNLEFT. В этом случае контрол прикрепится справа или слева соответственно , а параметры ( x , y , nWidth , nHeight) функции CreateWindowEx можно обнулить. Кроме того, при создании обоих контролов, неплохо указать стиль WS_CLIPSIBLINGS , который не даст конролу Edit рисоваться поверх Up-Down. Если для контрола Up-Down указать стиль UDS_SETBUDDYINT , то при изменении его значений, они автоматически будут записываться в EDIT.

Функция CreateUpDownControl так же позволяющая создать Up-Down , представляет из себя удобную обертку над CreateWindowEx. В ней нет необходимости прописывать класс контрола и как я и писал есть дополнительные возможности. Декларация функции:

CreateUpDownControl(_
dwStyle As DWORD,_ 'стиль окна
x As Integer,_ ' расположение по X
y As Integer,_ ' расположение по Y
cx As Integer,_ ' ширина окна
cy As Integer,_ ' высота окна
hParent As HWND,_ ' хендл родительского окна
nID As Integer,_ ' идентификатор контрола Up-Down
hInst As HINSTANCE,_ ' хендл приложения
hBuddy As HWND,_ ' хендл приклепляемого контрола
nUpper As Integer,_ ' верхняя граница диапазона значений
nLower As Integer,_ ' нижняя граница диапазона значений
nPos As Integer _ ' стартовое значение
) As HWND

По декларации должно быть понятно, что и куда прописывать.

Для того чтобы выставить\изменить диапазоны, нужно послать сообщение UDM_SETRANGE и в параметре LPARAM передать макрос:

MAKELPARAM(valMax, valMin)


Для того чтобы установить текущее значение, нужно послать сообщение UDM_SETPOS (для 16х битных чисел) или UDM_SETPOS32 (для 32х битных чисел) и в параметре LPARAM передать новое значение.

Для того чтобы получить текущее значение, нужно послать сообщение UDM_GETPOS. Параметры WPARAM и LPARAM при этом должны быть равны нулю.

Отлавливаются события контрола в сообщениях WM_VSCROLL , WM_HSCROLL (при стиле UDS_HORZ) и WM_NOTIFY. Важно отметить, что сообщение WM_NOTIFY обрабатывается в первую очередь. В результате есть возможность отменить\изменить значение до того, как придут сообщения WM_VSCROLL , WM_HSCROLL. При отлове сообщения WM_NOTIFY с кодом извщения UDN_DELTAPOS в параметре LPARAM оказывается структура NM_UPDOWN:

Type NM_UPDOWN
    hdr As NMHDR ' вложенная структура NMHDR , в параметре code которой проверяют извещение UDN_DELTAPOS
    iPos As Integer ' текущее состояние до изменения
    iDelta As Integer ' целое число, на которое изменится число (дельта)
End Type


Из комментариев к декларации структуры должно быть все предельно ясно, но в любом случае, в примере ниже, для понимания я использовал отлов событий.

Сообщения для контрола (расширенная инфомация ЗДЕСЬ):

  • UDM_GETACCEL - Возвращает информацию для ускорения вверх-вниз
  • UDM_GETBASE - Определение текущей системы счисления (десятичная или шестнадцатеричная), используемой для контрола
  • UDM_GETBUDDY - Возвращает хендл , пркрепленный к контролу
  • UDM_GETPOS - Возвращает текущую позицию (макс. 16-bit)
  • UDM_GETPOS32 - Возвращает текущую позицию (макс. 32-bit)
  • UDM_GETRANGE - Возвращает максимальный и минимальный диапазоны значений (16-bit)
  • UDM_GETRANGE32 - Возвращает максимальный и минимальный диапазоны значений (32-bit)
  • UDM_GETUNICODEFORMAT - Возвращает флаг определящий использования Unicode символов
  • UDM_SETACCEL - Устанавливает информацию для ускорения вверх-вниз
  • UDM_SETBASE - Установка текущей системы счисления (десятичная или шестнадцатеричная), используемой для контрола
  • UDM_SETBUDDY - Устанавливает хендл , для приклепления к контролу
  • UDM_SETPOS - Устанавливает текущую позицию (макс. 16-bit)
  • UDM_SETPOS32 - Устанавливает текущую позицию (макс. 32-bit)
  • UDM_SETRANGE - Устанавливает максимальный и минимальный диапазоны значений (16-bit)
  • UDM_SETRANGE32 - Устанавливает максимальный и минимальный диапазоны значений (32-bit)
  • UDM_SETUNICODEFORMAT - Устанавливает флаг определящий использования Unicode символов

Стили для контрола:

  • UDS_ALIGNLEFT - Размещение Up-Down справа от приклепленного окна
  • UDS_ALIGNRIGHT - Размещение Up-Down справа от приклепленного окна
  • UDS_ARROWKEYS - Управление стрелками на клавиатуре
  • UDS_AUTOBUDDY - Родительское окно выбирается автоматически
  • UDS_HORZ - Горизонтальное расположение
  • UDS_NOTHOUSANDS - Используется вместе со стилем
  • UDS_SETBUDDYINT. Указывает, что при отображении текущего значения не нужно разделять разряды тысяч десятичной точкой
  • UDS_SETBUDDYINT - Автоматически изменяется текст в приклепленном окне
  • UDS_WRAP - Сквозная прокрутка - при достижении максимума, начинаем опять с нуля и наоборот
#INCLUDE "windows.bi"
#INCLUDE "win/commctrl.bi"
InitCommonControls()
#DEFINE UDN_DELTAPOS (UDN_FIRST-1)
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 UpDown,Edit

    Select Case msg
        Case WM_CREATE
            Edit = CreateWindowEx(0,"edit","",WS_VISIBLE+WS_CHILD+WS_CLIPSIBLINGS,_
            10,10,80,20,hwnd,Cast(HMENU,1),0,0)
            UpDown = CreateWindowEx(0,"msctls_updown32","",_
            WS_VISIBLE+WS_CHILD+UDS_ALIGNRIGHT+UDS_AUTOBUDDY+UDS_SETBUDDYINT+WS_CLIPSIBLINGS,_
            0,0,0,0,hwnd,Cast(HMENU,2),0,0)
        Case WM_NOTIFY
            Dim hdr As NMHDR Ptr = Cast(NMHDR Ptr,LPARAM)
            If hdr->code = UDN_DELTAPOS Then

                Dim NMUP As NM_UPDOWN Ptr = Cast(NM_UPDOWN Ptr,LPARAM)
                Dim iPos As Integer = NMUP->iDelta+NMUP->iPos

                If NMUP->iDelta+NMUP->iPos > 100 Then
                    iPos = 100
                Elseif NMUP->iDelta+NMUP->iPos <0 Then
                    iPos = 0
                Else
                    iPos = NMUP->iDelta+NMUP->iPos
                Endif
                'Получаем значения
                ? "Value before change = ";NMUP->iPos
                ? "Value before change = ";iPos
                ' Устанавливаем новое значение
                SendMessage(UpDown,UDM_SETPOS,0,NMUP->iPos+10)
            Endif
        Case WM_VSCROLL
            ? "Value in message WM_VSCROLL = ";SendMessage(UpDown,UDM_GETPOS,0,0)
        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,"Up-Down контрол",_
WS_VISIBLE Or WS_OVERLAPPEDWINDOW ,10,10,300,200,0,0,Hinst,0)

While GetMessage(@msg,0,0,0)
    TranslateMessage(@msg)
    DispatchMessage(@msg)
Wend

up_down.png

содержание | назад | вперед