VB程序中移动无标题框窗体
编程爱好者
很多VB的初学者在编程中,经常会因为不能使用自定义风格的界面而苦恼,不无外乎因为无标题框窗体的拖动功能无法实现。今天,我就以一个例子一步一步地为大家讲解两种拖动无标题框窗体的巧妙方法,供大家参考。
一、准备工作
先利用VB的IMAGE控件与窗体的属性,做一个什么功能都没有的“假”的金山毒霸(图1),呵呵!

建立一个新的窗体,将窗体的Borderstyle属性设置为None,使它没有标题框,然后加入两个IMAGE控件,将IMA
GE的PICTURE属性设置为先前准备的图片。在这个示例里面,我将把它的属性设置为已经准备好的金山毒霸标题框图案和窗体图案!然后将其TOP与LEFT属性全设置为“0”,使IMAGE控件与窗体的位置对齐,成为如图1的外形。
好了,上面的准备工作做完,就可以正式编程实现拖动了!
二、程序实现
在这里笔者要讲述两种实现方法,希望大家能自由选择,灵活运用!
(一)专业型
所谓专业型,是指直接使用Windows的API函数调用来完成。对于初学者来说,总是觉得API函数很复杂,即使对着一本厚厚的工具书勉强把程序写完,也很难明白其中的原理,所以这种方法比较适合讲究程序的工整和效率的专职程序员。
先使用VB自带的API浏览器(图2),查询函数 ReleaseCapture()、SendMessage()的声明; ReleaseCapture()函数的作用是当前的应用程序释放鼠标,而SendMessage()函数的作用则是调用一个窗口的窗口函数,将一条消息发给那个窗口。SendMessage()函数使用时一定要等到消息处理完毕,否则该函数不会有返回值,处理完毕后它返回的类型的是LONG(长整型),而且值由具体的消息所决定;它可以使用的参数有hwnd、wMsg、wParam、lParam;

参数hwnd ,长整型(LONG),指要接收消息的那个窗口的句柄; 参数wMsg ,长整型(LONG),是消息的标志符;参数wParam,长整型(LONG),具体值取决于消息;参数lParam,任意类型(ANY),具体值也是取决于消息。
在本篇里要使用到的常数有:WM_SYSCOMMAND=&H112、SC_MOVE=&HF010&、HTCAPTION=2
这些Windows自带的常数通常是系统指定的值,有的是内存地址,有的代表中断号......
将使用API VIEW的声明,通过剪贴板复制到以下内容:
“Private Declare Function ReleaseCapture Lib "user32"
() As Long
Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd & _ As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long
Private Const WM_SYSCOMMAND = &H112
Private Const SC_MOVE = &HF010&
Private Const HTCAPTION = 2 “
粘贴到FORM1的通用区,这一堆字符串就是刚才提到的函数和常数的声明了。 然后在image1的 MOUSEMO
VE 事件里添加如下代码:
Private Sub image1_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single)
Me.MousePointer = 99
ReleaseCapture
SendMessage Me.hwnd, WM_SYSCOMMAND, SC_MOVE + HTCAPTION, Me.MousePointer = 0
End Sub
如此这般,第一种移动方法就完成了!
(二)初学者型
所谓初学者型,是指模仿VB的消息传递机制,通过传递变量来完成。在Form1_Mousedown事件、Form1_Mousem
ove事件、Form1_Mouseup事件中通过变量的传递,层层调用。由于程序看起来比较“绕”人,还请大家仔细分析!
1.通用区
通用区是变量传递的第一站,指定MOUSEXYDOWN为Boolean值,为下一个事件,即MOUSEDOWN事件提供触发条件。它的作用是:指定即将使用的变量名称,MX 和MY参数的作用则是记录当下一个事件MOUSEDOWN发生时,鼠标左键释放点的坐标。
在窗体的通用部分定义如下:
Option Explicit
'使用参数变量的类型定义
Dim MouseXYDown As Boolean
Dim Mx As Single
Dim MY As Single
2.触发IMAGE1_MOUSEDOWN事件
系统窗体移动时,靠的是鼠标左键在窗体标题框的上方按下来作为触发条件。一样的道理,想通过IMAGE1控件来移动窗体,那么事件代码肯定还得填写在代替标题框的IMAGE1控件里的IMAGE1_MOUSEDOWN触发事件中。
触发IMAGE1_MOUSED
OWN事件是变量传递的第二站。意思是如果鼠标左键按下,那么MOUSEXYDOWN的Boolean值为TRUE,而变量MOUSEXYDOWN又是下一个事件,即MOUSEMOVE事件的触发条件;而同样在这个事件中被触发的事件还有给MX、MY变量赋值,即当前鼠标点击点的坐标X、Y的值。变量MX、MY中保存的值,是作为下一步计算窗体在屏幕中移动的坐标而准备的数据。
Private Sub IMAGE1_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single)
If Button = 1 Then '如果在FORM1上按下鼠标左键
MouseXYDown = True
Mx = X
MY = Y
End If
End Sub
3.MOUSEMOVE事件
这是变量传递的第三站,也是关键环节。逻辑是这样的:如果条件变量MOUSEXYDOWN为TRUE时,则窗体LEFT (左边界)的值等于LEFT的值加上鼠标由点击点坐标(MX)与鼠标左键释放点坐标(X)的差;TOP值等于TOP的值加上鼠标由点击点坐标(MY)与放开点坐标(Y)的差,并使用了窗体的MOVE事件将窗体移动到了计算后得出的坐标。
’MOUSEMOVE事件
Private Sub image1_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
If MouseXYDown = True Then
Me.Move Left + (X - Mx), Top + (Y - MY)
End If
End Sub
4.MOUSEUP事件
这是变量传递的终点站,MouseXYDown变量的“万流归宗”!一个拖动事件完成后,因为是使用自定义变量来模仿消息的传递,程序用检测MOUSEXYDOWN变量是否为“TRUE”的方法来判断你是否点击了“IMAGE1”控件,也就是你自制窗体的“标题框”,当条件为真时才执行移动窗体的指令。所以置MOUSEXYDOWN的值为“FALSE”是必要的,否则当你发现自己精心自制窗体会被鼠标赶得满屏幕乱跑时,你就哭笑不得了。
'MOUSEUP事件
Private Sub image1_MouseUp(Button As Integer, Shift As Integer, X As Single, Y As Single)
MouseXYDown = False
End Sub
三、方法比较
使用 API函数的优点是效率比较高,但笔者个人认为,在如今Windows API内部消息传递满天飞的编程时代,相比之下后面的实现方法更简单明了,比较适合VB初学者使用!而后一种方法的缺点是,如果你做的是比较大的项目的话,就比较容易将这三个变量遗忘。
以上程序下载网址:http://www.cpcw.com/xz/46chengxu.rar(由于下载人数较多,建议使用下载软件下载)