对于拖拽,我一直没有一个明确的认识,今天发现了这个问题,马上着手解决(发现问题与解决问题的无缝结合,不能放到明天),认识到自己哪里不会是一种学问,解决更是一种学问。
首先,我站在巨人的肩膀上-----先百度一个例子,通过例子理解更好一点。但这个巨人有点让我失望,网上并没有太完善的说明,但是还是得到了启示。下面通过我的学习历程来理解拖拽!(那就让我当一个小巨人吧~~~~)
说到拖拽,涉及到两个事件:DragDrop、DragOver,必须把控件的DragMode属性设为1(1为自动,默认为0手动)才可以发生,该控件不再接收Click事件和MouseDown事件。(有人用到MouseDown和MouseUp来记录位置,用这两个事件的说明他根本没理解拖拽的用法!)。
我们先来看看DragDrop事件(以窗体的为例)
Private Sub Form_DragDrop(Source As Control, X As Single, Y As Single) End Sub
这个事件是在拖拽到目的位置松开鼠标时发生的。
还要先介绍一下Drag方法:控件.Drag整数,整数范围为0,1,2含义分别为:0取消拖动操作,1开始拖动操作,2结束操作。(放在MouseUp中用于通知拖放结束,这都源自于资料,开始我也不知道,但实际测试发现不加也可以。。。。)
要使用一个事件,必须先了解他的参数。Source永远是指的被拖拽的对象(即代替按住不放的控件),X,Y从表面理解应该是位置,网上的资料这样说:参数X、Y为松开鼠标按钮时光标的位置。看似没什么问题,于是我写了如下代码:
Private Sub Command1_MouseUp(Button As Integer, Shift As Integer, X As Single, Y As Single)
Command1.Drag 2
End Sub
Private Sub Command1_DragDrop(Source As Control, X As Single, Y As Single)
Source.Move X, Y
Print X, Y
End Sub
理解是:在松开鼠标时触发DragDrop事件,Source代表被拖拽的按钮对象,x、y是松开鼠标时的光标坐标,理论上按钮是应该换位置的,但实际情况是按钮不动。
继续查阅资料,是这样说的:拖动对象的DragDrop事件不是用来存放有关放开对象时执行某些指令的地方。而应将这些指令放到背景的DragDrop事件中或者拖动对象所放开的目标控件中。恍然大悟,原来这个事件处理是要放在背景控件或者目标控件中的,是激活的它人事件,而不是自己处理。
就是这一个不知道,引出了一系列问题。显然上边的代码是无法实现的,因为DragDrop事件要使用背景-----窗体的。但当我点击按钮时它的位置会变,为什么???感觉告诉我问题就出在X、Y这两个位置参数上!可以这样理解:当我点击按钮时,相当于以按钮为背景,同时按钮又是一个被拖拽的对象,所以触发了按钮的DragDrop事件,此时Source代表的又是本按钮,所以位置发生了变化。再看看点击完按钮的位置,基本上是到窗体的左上角。一个瞬间的猜测:这个X、Y位置参数是在背景控件或者目标控件的位置,是一个相对的位置!马上来验证一下,我们点按钮的左上角,在按钮里左上角据相当于窗体的左上角,它们的坐标是都是(0,0),这时候我们会发现按钮马上移动到了窗体左上角(0,0)的位置!继续点,很清晰的看出:光标相对于按钮左上角的坐标就是按钮左上角在窗体上的坐标。(单位都是缇)。这说明我们的猜测是正确的!每个控件内部左上角坐标都为(0,0),拖拽时光标在背景的相对位置或者目标控件的相对位置将直接反映在被拖拽对象在背景的位置。为了更好的理解,可以试试下边的例子:
Private Sub Command2_DragDrop(Source As Control, X As Single, Y As Single)
Source.Move X, Y
End Sub
Private Sub Command1_MouseUp(Button As Integer, Shift As Integer, X As Single, Y As Single)
Command1.Drag 2
End Sub
当我们把按钮1拖拽到按钮2上时,触发了目标控件按钮2的DragDrop事件,此时X、Y是光标在按钮2的相对位置,Source是被托对象按钮1,此时按钮1在背景(窗体)的位置就是光标相对于按钮2的位置。
有了以上深刻的理解和认识,我们再来研究拖拽思路就很清晰了。于是网络上的代码就可以很好的理解。
Private Sub Form_DragDrop(Source As Control, X As Single, Y As Single) Source.Move (X - Source.Width / 2), (Y - Source.Height / 2) End Sub Private Sub Command1_MouseUp(Button As Integer, Shift As Integer, X As Single, Y As Single) Command1.Drag 2 End Sub
相信你现在一看就懂了!还是提示一下Source.Move (X - Source.Width / 2), (Y - Source.Height / 2)个人认为不是很好,因为拖拽按钮时只有光标在按钮正中间时,拖拽才是准确的,其他情况虽然不是很准,但基本也可以了,如果我改进的话,我会第一时间贴出的。。。。。
如果我们继续观察,力求完美,依然会发现问题!问题是:当拖拽控件(按钮)时,如果光标不出按钮的范围,它是不动的,这与我们的期望是不符的!这时候我们有了上边的研究作为基础,可以很轻易的解决这个问题!完美代码如下:
Private Sub Command1_DragDrop(Source As Control, X As Single, Y As Single)
Command1.Left = Command1.Left - (Source.Width / 2 - X)
Command1.Top = Command1.Top - (Source.Height / 2 - Y)
End Sub
Private Sub Form_DragDrop(Source As Control, X As Single, Y As Single)
Source.Move (X - Source.Width / 2), (Y - Source.Height / 2)
End Sub
Private Sub Command1_MouseUp(Button As Integer, Shift As Integer, X As Single, Y As Single)
Command1.Drag 2
End Sub
如果弄懂了我所说的,可以看出只不过是多了一个按钮的DragDrop事件。在光标不出按钮时,相当于以按钮为背景,按钮又为对象,此时不触发窗体的DragDrop事件,而是触发按钮的DragDrop事件,所以加以处理就可以了!(很完美,拖哪到哪,随便怎么拖!具体运算方法就留给读者了,不多解释了)
最后,我们要学会自己发现问题,不能仅仅满足于别人的见解,发散思维,设想出多种情况,通过发现问题与解决问题,才能使印象深刻,知识成网,达到不需要记忆,永远也不会忘记的效果!