Нуждающийся
Регистрация: 09.11.2005
Сообщений: 69
Написано одно полезное сообщение
|
Вот, нарыл наконец-то исходник по работе с кнопками.
За орфографические ошибки, если есть, звиняюсь заранее - писал давно, неграмотный был
Тут все раскоментированно, думаю понятно будет )
Graphics 640,480,16,2
SetBuffer BackBuffer()
SetFont(LoadFont("Arial Cyr",22))
Global MX=0,MY=0,Mdown1=False
Function UpdateMouse()
MX=MouseX()
MY=MouseY()
MDown1=MouseDown(1)
End Function
;тип кнопка
Type TButtons
;позиция начала и позиция конца
Field x,y,x2,y2
;текст кнопки
Field Title$
;ИД номер или номер события закрепленного за этой нопкой
Field id
;группа или экран к которому относится эта кнопка
Field group
;цвет текста кнопки(нужно для эффектов)
Field col
;переменная фокуса, нужна чтобы кнопка срабатывала только после отжатия.
;Например нажал на кнопку и передумал - просто неотжимая кнопку убрать
;с нее указатель мыши, и она не сработает.
Field focuse
End Type
;функция для создания новой кнопки. Тип функции указываем как тип Кнопка, так как мы будем возвращать обьект кнопка с таким типом
;параметры функции:
;номер события или ИД номер
;Текст кнопки
;позиция на экране
;группа(или экран) к которой(ому) будет относиться кнопка
Function NewButton.TButtons(id,Title$,x,y,group=0)
;создаем новый объект кнопка в памяти
But.TButtons=New TButtons
;инициализируем его поля
But\id=id
But\Title=Title
But\x=x
But\y=y
but\group=group
but\col=0
but\focuse=False
;позиция конца отсчитывается от позиции начала и зависит от длины текста кнопки
But\x2=x+StringWidth(title)
But\y2=y+StringHeight(title)
;возвращаем обьект из функции
;Нужно например для работы с индивидуальной кнопкой
Return but
End Function
;функция обновления кнопок
;Параметры функции:
;группа (или экран) кнопок которую(ый) надо обновить.
;По умолчанию эта нулевая группа.
Function UpdateButtons(group=0)
;переменная нужная для хранения результата обновления кнопок.
;Нужна для того чтобы результат можно было возвратить в конце функции, не прервав
;обновления кнопок
Local out=0
;перебираем весь список кнопок
For But.TButtons=Each TButtons
;если у текущей кнопки из списка группа равна указанной в параметрах функции
;то обновляем ее
If but\group=group Then
;проверяем позицию указателя мыши и позицию кнопки
;Если указатель мыши дальше чем начало кнопки и ближе чем конец кнопки
;(вспомним что координаты начинаются с левого верхнего угла)
;то указатель находится над кнопкой
If (MX>But\x) And (MX<but\x2) And (MY>but\y) And (MY<but\y2) Then
;далее проверяем, если при этом кнопка мыши нажата(т.е мы нажали на кнопку)
If Mdown1 Then
;активируем флаг кнопки - фокус
;раз мы на нее нажали, значит мы сфокусировались :) на этой кнопке и
;надо ей это сообщить
But\Focuse=True
Else
;если кнопку отжали или еще не нажимали, то
;увеличиваем "цвет"(но правильнее сказать - интенсивность цвета)
;Увеличиваться он будет до тех пор пока любой из цветовых компонент
;не достигнет максимального - 255.
If but\col<155 Then but\col=but\col+5
;если на кнопке был установлен фокус (тоесть мы ее уже нажимали)
If But\focuse Then
;записываем ИД номер кнопки в переменную результата
out=but\id
;сбрасываем цвет, иначе после перехода на другой экран
;(обновления другой группы кнопок), у этой кнопки останется
;цвет активации, и мы это увидим начав обновлять эту кнопку заного
but\col=0
End If
End If
Else
;ну а если мы убрали мышь с кнопки то обнуляем фокус кнопки
;тем самым говоря что мы не хотим чтобы кнопка сработала, или просто убрали
But\Focuse=False
;уменьшаем "цвет" кнопки до нуля, создавая эффект плавного гашения
If but\col>0 Then but\col=but\col-5
End If
;а пока все эти события происходят или не происходят
;устанавливаем цвет по умолчанию и прорисовываем текст
;кнопки. Сюда можно так же добавить прорисовку картинки кнопки
; и проч. мишуры :)
Color 100+but\col,100+but\col,100
Text but\x,but\y,but\title
End If
Next
;ну и когда бы пробежались по списку, возвращаем из функции результат
;Если бы мы сразу (как только произошла активация кнопки) возвращали результат
;то оператор return вышел ыб из функции не давая возможности нарисоваться и обновиться
; остальным кнопкам, которые находятся дальше по списку
Return out
End Function
;Функция обновления индивидуальной кнопки, точно такая же как и предыдущая,
;только пробегаться по списку тут мы не будем, ведь у нас уже есть ссылка на нужную кнопку,
;передаваемая через параметры функции. Поэтому рассматривать я ее не буду.
Function UpdateButton(but.TButtons)
Local out=0
If MX>But\x And MX<but\x2 And MY>but\y And MY<but\y2 Then
If Mdown1 Then
But\Focuse=True
Else
If but\col<155 Then but\col=but\col+5
If But\focuse Then
but\col=0
but\focuse=False
Return True
End If
End If
Else
but\focuse=False
If but\col>0 Then but\col=but\col-5
End If
Color 100+but\col,100+but\col,100
Text but\x,but\y,but\title
Return False
End Function
;ну а эта функция-заглушка, вместо нее может быть что угодно.
Function DrawEnything()
Color 100,100,100
Rect 10,10,615,400,0
End Function
;Здесь идуду константы событий или ИД номера кнопок.
Const MM_MAIN=0;главное событие, когда обновляются все кнопки нулевой группы
Const MM_NEWGAME=1;событие обновления экрана "новая игра"
Const MM_OPTIONS=2;событие обновления экрана "опции"
Const MM_ABOUT=3;событие обновления экрана "о программе"
Const MM_QUIT=4;событие выхода из программы
;Почему у следующих констант такие странные номера?
;Потому что эти события описаные этими константами относятся к событию вызова экрана опции
;у которого номер события равен 2. И воспользовавшись структурой многоуровнего списка
;( Word все знаем?:) ) я поименовал эти константы как подконстанты. Так удобнее.
Const MM_GRAPHS=21;событие обновления подэкрана графика, экрана опции
Const MM_SOUNDS=22;событие обновления подэкрана звуки, экрана опции
Const MM_CTRLS=23;событие обновления подэкрана управление, экрана опции
;##########################################
;Пришло время создавать наши кнопки
;Думаю из названия понятно какие кнопки к чему относятся
;Обратите внимание на кнопки которым проставлены номера групп (последний параметр)
NewButton(MM_NEWGAME,"Новая игра",60,200)
NewButton(MM_OPTIONS,"Опции",60,220)
;эта кнопка не будет обновляться в главном экране
;так как ее группа 2, а главный экран это нулевая группа
;(которую кстате не обязательно указывать так как она по умолчанию)
NewButton(MM_GRAPHS,"Графика",200,200,2)
;эта кнопка тоже
NewButton(MM_SOUNDS,"Звуки",200,220,2)
;и эта кнопка
NewButton(MM_CTRLS,"Управление",200,240,2)
NewButton(MM_ABOUT,"О программе",60,240)
NewButton(MM_QUIT,"Выход",60,260)
;кнопка назад будет использоватся в нескольких экранах и не относиться
;к конкретной группе кнопок, потому поставим ей группу номер 1, еще никем не использованную.
;А так же сохраняем эту кнопку в переменной, для того чтобы обновлять ее отдельно от остальных кнопок
;ИД номер (или номер события) в таком случае не имеет значения, лишь бы он был отличен от нуля
;Ведь как известно булевское значение true это значение отличное от нуля, а false это нуль.
;А нам нужна только проверка - была нажата эта кнопкак или нет.
ButBack.TButtons=NewButton(1,"Назад",560,440,1)
;##########################################
;ну и гоавный цикл конечно, где находиться основная логика работы меню
While Not KeyDown(1)
Cls
;читаем мышь, чтоб знать где находиться указатель мыши. Кстате
;в эту функцию можно поместить прорисовку собственного указателя
;но при этом е следует поместить в самом конце, чтобы указатель прорисовывался
;самым последним и был поверх всех кнопок.
UpdateMouse()
;Тут мы проверям переменную главных событий
Select MainEvent
;по умолчанию функция обновления кнопок возвращает нуль, поэтому
;мы "повесили" событие обновления главного экрана на константу равную нулю
Case MM_MAIN
;обновляем все кнопки нулевой группы, соответственно на экране
;будут рисоваться только они, и если мы нажали на какую-нибудь
;кнопку то вункция возвратить значение отличное от нуля, и равное
;значению ИД номера прикрепленного к этой кнопке.
MainEvent=UpdateButtons()
;если это значение равно константе обновления экрана "новая игра"
Case MM_NEWGAME
;рисуем что-нибудь. Это что-нибудь может быть еще одним экраном
;(группой кнопок) с выбором уровня сложности. Достаточно создать
;дополнительную константу хранящуюю номер этого события, создать
;кнопки с нужным текстом и нужно группой и добавить обработку
;сюда, в новую ветку оператора select
DrawEnything()
;обновляем кнопку "назад", чтобы можно было возвратиться обратно.
;в данном случае мы возвращаемся обратно на главный экран (ведь
;от него мы ушли всего на один экран). Для этого достаточно обнулить
;или присвоить значение константы события обновления главного экрана
;переменной хранящей все происходящие события. При этом оператор
;Select сам перейдет к выполению нужно ветки.
If UpdateButton(ButBack) Then MainEvent=MM_MAIN
;если произошло событие - нажата кнопка "опции"
Case MM_OPTIONS
;обновляем кнопки принадлежащие группе (экрану) "опции"
;и результат записываем во временную переменную.
;Это нужно чтобы возвращаемое по умолчанию функцией обновления кнопкок
;значение нуля, не затерло значение события хранимого переменной событий.
;Иначе мы бы сразу возвратились на обновление главного меню, ведь нуль это
;как-раз таки это событие
event=UpdateButtons(MM_OPTIONS)
;если промежуточная переменная не равна нулю, тоесть мы нажали на какую-то
;кнопку на экране "опции", то мы записываем это событие.
If event Then
MainEvent=event
End If
;так же не забываем обновлять кнопку "назад"
If UpdateButton(ButBack) Then MainEvent=MM_MAIN
;тут аналогично экрану "новая игра"
Case MM_ABOUT
DrawEnything()
If UpdateButton(ButBack) Then MainEvent=MM_MAIN
;если происходит событие - нажата кнопка "Выход"
;вызываем оператор exit который выходит из главного цикла
;и таким образом завершается работа меню
Case MM_QUIT
Exit
;аналогично экрану "новая игра"
Case MM_GRAPHS
DrawEnything()
If UpdateButton(ButBack) Then MainEvent=MM_OPTIONS
;тоже самое
Case MM_SOUNDS
DrawEnything()
If UpdateButton(ButBack) Then MainEvent=MM_OPTIONS
;ну и тут тоже
Case MM_CTRLS
DrawEnything()
If UpdateButton(ButBack) Then MainEvent=MM_OPTIONS
End Select
Flip
Wend
End
Если будет время, то накатаю про остальную работу с меню.
|