Как посадить пассажира в лодку простым перетаскиванием
Для ребенка, играющего в эту игру, вряд ли на первых порах будет понятно, почему щелчок по объекту приводит к его перемещению в лодку. Интуитивно, более разумным действием, приводящим к посадке объекта в лодку, было бы прямое перетаскивание объекта в лодку из его текущего положения на берегу. Реализацией такого способа перемещения объекта мы сейчас и займемся. При этом мы не будем тащить сам объект, хотя и это не трудно было бы сделать, а используем технику, основанную на специальном объекте DataObject, входящем в состав библиотеки MSForms. Эта техника хороша тем, что она позволяет опустить перетаскиваемый объект точно в лодку. Всякая попытка опустить объект где-либо в другом месте приведет к неуспеху операции перетаскивания. Момент, когда цель перетаскивания достигнута, и можно отпустить нажатую до этого кнопку мыши, определяется тем, что изменяется внешний вид курсора (появляется значок "+"), что и позволяет точно опустить объект в нужное место. Реализацию этого довольно сложного сп особа перетаскивания обеспечивают обработчики трех событий. Первое из этих событий связано с самим перетаскиваемым объектом. В тот момент, когда над объектом нажимается левая кнопка мыши с целью начать его перетаскивать или копировать в точку назначения, возникает событие "MouseMove". В обработчике этого события и следует создать новый объект класса DataObject, определить некоторые его свойства и вызвать метод StartDrag. Этот метод работает совсем не так, как большинство обычных методов. Его действие оканчивается в тот момент, когда завершится операция перетаскивания. В качестве результата метод возвращает 0, если операция закончилась неуспехом, и ненулевое значение в противном случае. Заметьте, что во время перетаскивания, то есть еще до того, как StartDrag завершит работу, будут возникать другие события и, следовательно, будут работать другие обработчики событий. Два таких события будут возникать, когда перетаскиваемый объект достигает точки назначения, точнее, области назначения. В этот момент у целевого объекта возникает событие BeforeDragOver. Обработчик этого события изменяет внешний вид курсора, что является сигналом достижения цели назначения и позволяет отпустить нажатую кнопку мыши. Обработчик второго события у целевого объекта BeforeDropOrPaste и реализует операцию опускания объекта. Если все завершится благополучно, то успехом заканчивает свою работу и метод StartDrag, которому возвращается управление. Подробнее обо всех деталях работы с этим объектом можно прочитать в моей книге, ссылка на соответствующее место в которой была уже сделана. После всех этих пояснений можно привести и обработчики соответствующих событий, реализующих операции по перетаскиванию объектов в лодку:
Для ребенка, играющего в эту игру, вряд ли на первых порах будет понятно, почему щелчок по объекту приводит к его перемещению в лодку. Интуитивно, более разумным действием, приводящим к посадке объекта в лодку, было бы прямое перетаскивание объекта в лодку из его текущего положения на берегу. Реализацией такого способа перемещения объекта мы сейчас и займемся. При этом мы не будем тащить сам объект, хотя и это не трудно было бы сделать, а используем технику, основанную на специальном объекте DataObject, входящем в состав библиотеки MSForms. Эта техника хороша тем, что она позволяет опустить перетаскиваемый объект точно в лодку. Всякая попытка опустить объект где-либо в другом месте приведет к неуспеху операции перетаскивания. Момент, когда цель перетаскивания достигнута, и можно отпустить нажатую до этого кнопку мыши, определяется тем, что изменяется внешний вид курсора (появляется значок "+"), что и позволяет точно опустить объект в нужное место. Реализацию этого довольно сложного сп особа перетаскивания обеспечивают обработчики трех событий. Первое из этих событий связано с самим перетаскиваемым объектом. В тот момент, когда над объектом нажимается левая кнопка мыши с целью начать его перетаскивать или копировать в точку назначения, возникает событие "MouseMove". В обработчике этого события и следует создать новый объект класса DataObject, определить некоторые его свойства и вызвать метод StartDrag. Этот метод работает совсем не так, как большинство обычных методов. Его действие оканчивается в тот момент, когда завершится операция перетаскивания. В качестве результата метод возвращает 0, если операция закончилась неуспехом, и ненулевое значение в противном случае. Заметьте, что во время перетаскивания, то есть еще до того, как StartDrag завершит работу, будут возникать другие события и, следовательно, будут работать другие обработчики событий. Два таких события будут возникать, когда перетаскиваемый объект достигает точки назначения, точнее, области назначения. В этот момент у целевого объекта возникает событие BeforeDragOver. Обработчик этого события изменяет внешний вид курсора, что является сигналом достижения цели назначения и позволяет отпустить нажатую кнопку мыши. Обработчик второго события у целевого объекта BeforeDropOrPaste и реализует операцию опускания объекта. Если все завершится благополучно, то успехом заканчивает свою работу и метод StartDrag, которому возвращается управление. Подробнее обо всех деталях работы с этим объектом можно прочитать в моей книге, ссылка на соответствующее место в которой была уже сделана. После всех этих пояснений можно привести и обработчики соответствующих событий, реализующих операции по перетаскиванию объектов в лодку:
Листинг 6.7.
(html, txt)
Заметьте, для четырех перемещаемых объектов: человека, волка, козы и капусты написаны четыре обработчика события MouseMove. Каждый из них создает свой объект DataObject, запоминает в его свойстве Text название перемещаемого объекта и запускает метод StartDrag. Но цель у всех этих объектов одна - лодка. У объекта Boat два обработчика событий, вне зависимости от числа пассажиров лодки. Обработчик события BeforeDragOver для всех перемещаемых объектов один и тот же, поскольку его задача изменить вид курсора при попадании перемещаемого объекта в область назначения. Обработчик события BeforeDropOrPaste более сложный. Он должен произвести разбор случаев и определить, какой именно объект прибыл в точку назначения и соответствующим образом расположить его в лодке. Анализ свойства Text, объекта DataObject, переданного в качестве параметра обработчику событий, позволяет провести разбор случаев. После этих предварительных замечаний приведем тексты самих обработчиков:
Листинг 6.8.
(html, txt)
На этом закончим рассмотрение задачи посадки пассажиров в лодку и перейдем к рассмотрению следующей задачи.
Private Sub Man_MouseMove( ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single) Dim Effect As Integer 'MyDataObject используется при перетаскивании объектов Dim MyDataObject As DataObject
If Button = 1 Then Set MyDataObject = New DataObject MyDataObject.SetText "Man" Effect = MyDataObject.StartDrag If Effect = 0 Then 'перетаскиваемый объект не достиг цели 'Сообщение о неуспехе MsgBox Prompt:=Mes1 + vbCrLf + Mes7 + Mes8 _ + vbCrLf + Mes12, Buttons:=vbCritical + vbOKOnly, Title:=Mes13 End If End If End Sub Private Sub Wolf_MouseMove(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single) Dim Effect As Integer 'MyDataObject используется при перетаскивании объектов Dim MyDataObject As DataObject
If Button = 1 Then Set MyDataObject = New DataObject MyDataObject.SetText "Wolf" Effect = MyDataObject.StartDrag If Effect = 0 Then 'перетаскиваемый объект не достиг цели 'Сообщение о неуспехе MsgBox Prompt:=Mes1 + vbCrLf + Mes7 + Mes9 _ + vbCrLf + Mes12, Buttons:=vbCritical + vbOKOnly, Title:=Mes13 End If End If End Sub Private Sub Goat_MouseMove(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
Dim Effect As Integer 'MyDataObject используется при перетаскивании объектов Dim MyDataObject As DataObject
If Button = 1 Then Set MyDataObject = New DataObject MyDataObject.SetText "Goat" Effect = MyDataObject.StartDrag If Effect = 0 Then 'перетаскиваемый объект не достиг цели 'Сообщение о неуспехе MsgBox Prompt:=Mes1 + vbCrLf + Mes7 + Mes10 _ + vbCrLf + Mes12, Buttons:=vbCritical + vbOKOnly, Title:=Mes13 End If End If End Sub Private Sub Cabbage_MouseMove(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single) Dim Effect As Integer 'MyDataObject используется при перетаскивании объектов Dim MyDataObject As DataObject
If Button = 1 Then Set MyDataObject = New DataObject MyDataObject.SetText "Cabbage" Effect = MyDataObject.StartDrag If Effect = 0 Then 'перетаскиваемый объект не достиг цели 'Сообщение о неуспехе MsgBox Prompt:=Mes1 + vbCrLf + Mes7 + Mes11 _ + vbCrLf + Mes12, Buttons:=vbCritical + vbOKOnly, Title:=Mes13 End If End If End Sub
Листинг 6.7.
Заметьте, для четырех перемещаемых объектов: человека, волка, козы и капусты написаны четыре обработчика события MouseMove. Каждый из них создает свой объект DataObject, запоминает в его свойстве Text название перемещаемого объекта и запускает метод StartDrag. Но цель у всех этих объектов одна - лодка. У объекта Boat два обработчика событий, вне зависимости от числа пассажиров лодки. Обработчик события BeforeDragOver для всех перемещаемых объектов один и тот же, поскольку его задача изменить вид курсора при попадании перемещаемого объекта в область назначения. Обработчик события BeforeDropOrPaste более сложный. Он должен произвести разбор случаев и определить, какой именно объект прибыл в точку назначения и соответствующим образом расположить его в лодке. Анализ свойства Text, объекта DataObject, переданного в качестве параметра обработчику событий, позволяет провести разбор случаев. После этих предварительных замечаний приведем тексты самих обработчиков:
Private Sub Boat_BeforeDragOver(ByVal Cancel As MSForms.ReturnBoolean, ByVal Data As MSForms.DataObject, ByVal X As Single, ByVal Y As Single, ByVal DragState As MSForms.fmDragState, ByVal Effect As MSForms.ReturnEffect, ByVal Shift As Integer) 'Достигнута цель перетаскиваемого объекта.Изменяется внешний вид курсора. Cancel = True Effect = fmDropEffectCopy End Sub
Private Sub Boat_BeforeDropOrPaste(ByVal Cancel As MSForms.ReturnBoolean, ByVal Action As MSForms.fmAction, ByVal Data As MSForms.DataObject, ByVal X As Single, ByVal Y As Single, ByVal Effect As MSForms.ReturnEffect, ByVal Shift As Integer) 'Достигнута цель перетаскиваемого объекта.Объект можно опустить в точку назначения. Cancel = True Effect = fmDropEffectCopy 'Разбор случае. Анализ прибывшего объекта и вызов процедуры его размещения в лодке If Data.GetText = "Man" Then ManInBoat ElseIf Data.GetText = "Wolf" Then WolfInBoat ElseIf Data.GetText = "Goat" Then GoatInBoat Else: CabbageInBoat End If End Sub
Листинг 6.8.
На этом закончим рассмотрение задачи посадки пассажиров в лодку и перейдем к рассмотрению следующей задачи.