Тема: Меню
Показать сообщение отдельно
Старый 18.01.2006, 14:36   #14
Платон
Нуждающийся
 
Регистрация: 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
Если будет время, то накатаю про остальную работу с меню.
(Offline)
 
Ответить с цитированием