Показать сообщение отдельно
Старый 04.02.2010, 15:55   #1
Жека
Дэвелопер
 
Регистрация: 04.09.2005
Адрес: Красноярск
Сообщений: 1,376
Написано 491 полезных сообщений
(для 886 пользователей)
Пример 1. Обработка мышки. Класс TMouse

Обновил пример. Что нового:
- обработка колёсика мышки
- возможность обрабатывать все доступные кнопки мышки - состояния хранятся в массиве
- методы для получения значений полей класса, чтобы "случайно" не присвоить значение
- получение скоростей перемещения
- сброс нажатий (flush)

Количество кнопок для обработки указывается при создании экземпляра мышки:
Global mouse:TMouse = TMouse.fnCreate(3)
Получение состояний - по номеру кнопки:
If(mouse.fnKeyUp(1) = True)
----------------------------------------------------------------

Что можно сделать, используя данный класс:

• Определение текущих координат мышки (X, Y, Z)
• Определение момента нажатия кнопок мыши (hit)
• Определение нажатого состояния кнопок мыши (down)
• Определение момента отпускания кнопок мышки (up)
• Определение координат последнего щелчка (для каждой кнопки)
• Ограничение области перемещения мышки в виде прямоугольника
• Установка фиксированной позиции мышки для текущего прохода цикла

Работа показана на примере программы, рисующей отрезки.

Суть – при нажатии левой кнопки мышки создаётся отрезок, первая часть которого принимает координаты щелчка, а вторая «привязывается» к текущим координатам мышки. Удерживая нажатой левую кнопку мышки, можно изменять положение конца отрезка. При отпускании кнопки рисование текущего отрезка завершается, и он добавляется в список.

На экране показывается дополнительная информация о состоянии мышки.

По нажатию на пробел включается/отключается ограничение на передвижение мышки. При включённом рисуется ограничивающий прямоугольник.

Примечание: нет обработки колёсика мышки (кому надо - добавят легко).

Скриншот:
Нажмите на изображение для увеличения
Название: mouse1.jpg
Просмотров: 1407
Размер:	19.9 Кб
ID:	8976

Исходный код:

Strict

Framework brl.d3d7max2d
Import brl.pngloader



'параметры экрана
Global screenW = 600
Global screenH = 700
Global screenD = 0
Local screenHertz = 75
Local screenFlags = GRAPHICS_BACKBUFFER


'заголовок окна приложения
AppTitle = "Использование класса TMouse"

'создаем окно
SetGraphicsDriver(D3D7Max2DDriver())
Graphics (screenW, screenH, screenD, screenHertz, screenFlags)


'флаг для условия выхода из игрового цикла 
Global onRunning = True

'кнопки
Global keyEsc, keySpace, keyClose


'прячем стандартный курсор и ставим в середину окна
HideMouse()
MoveMouse(screenW * 0.5, screenH * 0.5)

'создаем "мышку" для обработки нажатий и прочего
Global mouse:TMouse = TMouse.fnCreate(3)
Local img:TImage = LoadImage("pointer.png")
mouse.fnSetPointer(img)
mouse.fnSetBounds(250, 200, 255, 300, False)


Local cntHit1, cntHit2, cntUped1, cntUped2


Global painter:TPainter = New TPainter


'главный цикл
While (onRunning = True)
	
	'получаем новые нажатия кнопок
	fnCheckKeyInput()
	
	'если нажали на крестик "закрыть" или Esc - выход
	If(keyEsc = True Or keyClose = True)
		onRunning = False
		Exit
	EndIf

	'вкл/выкл ограничивающий прямоугольник
	If(keySpace = True) mouse.onUseBounds = Not(mouse.onUseBounds)
	
	'обновляем мышку
	mouse.fnUpdate()
	'рисуем ограничивающий прямоугольник
	mouse.fnDrawBounds()
	
	If(mouse.fnKeyHit(1) = True)
		cntHit1:+1
		'тут что-нибудь делаем по нажатию левой кнопки мыши
	EndIf
	
	If(mouse.fnKeyHit(2) = True) cntHit2:+1
	If(mouse.fnKeyUp(1) = True) cntUped1:+1
	If(mouse.fnKeyUp(2) = True) cntUped2:+1
	
	SetColor(255, 255, 255)
	
	DrawText("cntHit1 = " + cntHit1, 20, 20)
	DrawText("cntHit2 = " + cntHit2, 20, 40)
	
	DrawText("mouseDown(1) = " + mouse.fnKeyDown(1), 20, 80)
	DrawText("mouseDown(2) = " + mouse.fnKeyDown(2), 20, 100)
	
	DrawText("cntUped1 = " + cntUped1, 20, 140)
	DrawText("cntUped2 = " + cntUped2, 20, 160)
	
	DrawText("curX = " + mouse.x, 20, 200)
	DrawText("curY = " + mouse.y, 20, 220)
	
	DrawText("hitX(1) = " + mouse.fnGetHitX(1), 20, 260)
	DrawText("hitY(1) = " + mouse.fnGetHitY(1), 20, 280)
	
	DrawText("Space - on/off bound rect", 20, 320)
	
	painter.fnUpdate(mouse.x, mouse.y)
	painter.fnDraw()
	
	'рисуем мышку
	mouse.fnDraw()
	
	Flip(0)
	Cls()
			
Wend


End



'проверка состояния нажатых кнопок
Function fnCheckKeyInput()
	keyEsc = (KeyHit(KEY_ESCAPE) > 0)
	keySpace = (KeyHit(KEY_SPACE) > 0)
	keyClose = AppTerminate()
	
End Function



'класс мышки
Type TMouse
	Field x, y, z
	Field mHitX[], mHitY[]
	Field mHit[]
	Field mDown[]
	Field mUp[]
	Field pointer:TImage
	Field visible = True
	Field blockX, blockY, blockZ
	
	Field btnCount
	Field speedX, speedY, speedZ
	
	Field bx, by, bw, bh 'ограничивающая область
	Field onUseBounds
	
	Global k
	
	
	'"конструктор с параметром"
	Function fnCreate:TMouse(btnCnt = 3)
		Local m:TMouse = New TMouse
		m.btnCount = btnCnt
		m.mHit = New Int[btnCnt]
		m.mDown = New Int[btnCnt]
		m.mUp = New Int[btnCnt]
		m.mHitX = New Int[btnCnt]
		m.mHitY = New Int[btnCnt]
		Return m
	End Function
	
	
	'обновление
	Method fnUpdate()
		
		If(blockX = False)
			x = MouseX()
			speedX = MouseXSpeed()
		EndIf
		
		If(blockY = False)
			y = MouseY()
			speedY = MouseYSpeed()
		EndIf
		
		If(blockZ = False)
			z = MouseZ()
			speedZ = MouseZSpeed()
		EndIf
		
		blockX = False
		blockY = False
		blockZ = False
		
		'корректировка позиции
		fnCorrectPosByBounds()
		
		For k = 0 Until btnCount
			mUp[k] = mDown[k]
			mHit[k] = (MouseHit(k + 1) > 0)
			mDown[k] = MouseDown(k + 1)
			
			If(mHit[k] = True)
				mHitX[k] = x
				mHitY[k] = y
			EndIf
			
			If(mUp[k] = True And mDown[k] = False)
				mUp[k] = True
			Else
				mUp[k] = False
			EndIf
			
		Next
		
	End Method
	
	
	'корректировка позиции - возвращаем в допустимую область
	Method fnCorrectPosByBounds()
		If(onUseBounds = False) Return
		
		If(x < bx) x = bx
		If(y < by) y = by
		If(x > bx + bw) x = bx + bw
		If(y > by + bh) y = by + bh
		MoveMouse(x, y)
	
	End Method
		
	
	'блокировка на 1 ход в указанной позиции
	Method fnBlock(px, py, pz = -1)
				
		If(px >= 0)
			x = px
			blockX = True
		EndIf
		If(py >= 0)
			y = py
			blockY = True
		EndIf
		If(pz >= 0)
			z = pz
			blockZ = True
		EndIf
		
		MoveMouse(x, y)
		
	End Method
	
	
	'установка картинки указателя мыши
	Method fnSetPointer(img:TImage)
		pointer = img
	End Method
	
	
	'рисование
	Method fnDraw(dx = 0, dy = 0)
		If(visible = False Or pointer = Null) Return
		
		SetAlpha(1)
		SetColor(255, 255, 255)
		DrawImage(pointer, x + dx, y + dy)
		
	End Method
	
	
	'рисование ограничивающего прямоугольника
	Method fnDrawBounds()
		If(onUseBounds = True)
			SetColor(155, 155, 155)
			DrawLine(bx, by, bx + bw, by)
			DrawLine(bx + bw, by, bx + bw, by + bh)
			DrawLine(bx + bw, by + bh, bx, by + bh)
			DrawLine(bx, by + bh, bx, by)
		EndIf
	End Method
	
	
	'показать указатель
	Method fnShow()
		visible = True
	End Method
	
	
	'скрыть указатель
	Method fnHide()
		visible = False
	End Method
	
	
	'ограничивающая область
	Method fnSetBounds(px, py, pw, ph, use = True)
		bx = px
		by = py
		bw = pw
		bh = ph
		onUseBounds = use
	End Method
	
	
	'проверка - щелчок кнопки
	Method fnKeyHit(button)
		If(button < 1 Or button > btnCount) Return False
		Return mHit[button - 1]
	End Method
	
	
	'проверка - удержание нажатой кнопки
	Method fnKeyDown(button)
		If(button < 1 Or button > btnCount) Return False
		Return mDown[button - 1]
	End Method
	
	
	'проверка - отпускание кнопки
	Method fnKeyUp(button)
		If(button < 1 Or button > btnCount) Return False
		Return mUp[button - 1]
	End Method
	
	
	'Х-координата последнего нажатия кнопки
	Method fnGetHitX(button = 1)
		If(button < 1 Or button > btnCount) Return - 1
		Return mHitX[button - 1]
	End Method
	
	
	'У-координата последнего нажатия кнопки
	Method fnGetHitY(button = 1)
		If(button < 1 Or button > btnCount) Return - 1
		Return mHitY[button - 1]
	End Method
	
	
	'возвращение координаты Х
	Method fnGetX()
		Return x
	End Method
	
	
	'возвращение координаты Y
	Method fnGetY()
		Return y
	End Method
	
	
	'возвращение координаты Z
	Method fnGetZ()
		Return z
	End Method
	
	
	'возвращение скорости по Х
	Method fnGetSpeedX()
		Return speedX
	End Method
	
	
	'возвращение скорости по Y 
	Method fnGetSpeedY()
		Return speedY
	End Method
	
	
	'возвращение скорости по Z
	Method fnGetSpeedZ()
		Return speedZ
	End Method
	
	
	'сброс состояний всех кнопок
	Method fnFlush()
		FlushMouse()
		For k = 0 Until btnCount
			mHit[k] = False
			mDown[k] = False
			mUp[k] = False
		Next
	End Method
	
End Type



'рисовалка линий
Type TPainter
	Field x0:Float, y0:Float
	Field lineWidth = 2
	Field curLine:TLine
	
	Global list:TList = New TList 'список для отрезков
	Global line:TLine
	Global linesCount
	
	
	'обновление
	Method fnUpdate(x:Float, y:Float)
		
		'при щелчке мыши создаём новую линию
		If(mouse.fnKeyHit(1) = True)
			curLine = TLine.fnCreate(x, y, x, y)
		EndIf
		
		'двигаем конец за мышкой
		If(curLine <> Null) curLine.fnSetEnd(x, y)
		
		'при отпускании кнопки мыши добавляем линию в список
		If(mouse.fnKeyUp(1) = True)
			list.AddLast(curLine)
			linesCount:+1
			curLine = Null
		EndIf
		
	End Method
	
	
	'рисование
	Method fnDraw()
		SetColor(255, 255, 255)
		SetLineWidth (lineWidth)
		For line = EachIn list
			line.fnDraw(x0, y0)
		Next
		line = Null
		
		If(curLine <> Null) curLine.fnDraw(x0, y0)
	End Method
	
	
	'сдвинуть начало координат
	Method fnMove(dx:Float, dy:Float)
		x0:+dx
		y0:+dy
	End Method
	
End Type



'линия
Type TLine
	Field x1:Float, x2:Float, y1:Float, y2:Float
	
	'конструктор с параметрами
	Function fnCreate:TLine(x1:Float, y1:Float, x2:Float, y2:Float)
		Local ln:TLine = New TLine
		ln.x1 = x1
		ln.y1 = y1
		ln.x2 = x2
		ln.y2 = y2
		Return ln
	End Function
	
	
	'установка начальных координат
	Method fnSetStart(x:Float, y:Float)
		x1 = x
		y1 = y
	End Method
	
	
	'установка конечных координат
	Method fnSetEnd(x:Float, y:Float)
		x2 = x
		y2 = y
	End Method
	
	
	'рисование
	Method fnDraw(x0:Float, y0:Float)
		DrawLine(x0 + x1, y0 + y1, x0 + x2, y0 + y2)
	End Method
	
End Type
Вложения
Тип файла: rar TMouse_src.rar (3.9 Кб, 790 просмотров)
Тип файла: rar TMouse_src_i_exe.rar (164.3 Кб, 792 просмотров)

Последний раз редактировалось Жека, 05.02.2010 в 07:48. Причина: Дополненил пример.
(Offline)
 
Ответить с цитированием
Эти 3 пользователя(ей) сказали Спасибо Жека за это полезное сообщение:
G.A.D (04.02.2010), Randomize (05.02.2010), SBJoker (09.02.2010)