VB禁止移动窗口

–VB禁止移动窗口–

禁止一个窗口被移动最简单的方法是设置Form的Moveable属性为False,这样就无法拖动标题栏来改变窗口的位置了,同时系统菜单的“移动”命令变成了灰色,除此之外,还有两种方法也可禁止移动窗口。

1.拦截拖动标题栏的消息

当用户在标题栏的空白处上按下会产生WM_NCLBUTTONDOWN消息和HTCAPTION附加消息,我们可以拦截这个消息来防止用户通过拖动标题栏来移动窗口,此外还要拦截系统菜单的“移动”命令,所以我们还要处理WM_SYSCOMMAND消息,代码如下:

‘Form1中
‘———————————————————–
Private Sub Form_Load()
Me.Show
hWindow = Me.hWnd
OldWindowProc = SetWindowLong(hWindow, GWL_WNDPROC, AddressOf WindowProc)
End Sub

Private Sub Form_Unload(Cancel As Integer)
Call SetWindowLong(hWindow, GWL_WNDPROC, OldWindowProc)
End Sub

‘Module1中
‘———————————————————–
Option Explicit
Declare Function GetWindowLong Lib “user32” Alias “GetWindowLongA” (ByVal hWnd As Long, ByVal nIndex As Long) As Long
Declare Function SetWindowLong Lib “user32” Alias “SetWindowLongA” (ByVal hWnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Declare Function CallWindowProc Lib “user32” Alias “CallWindowProcA” (ByVal lpPrevWndFunc As Long, ByVal hWnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long

Public Const GWL_WNDPROC = (-4)
Public Const WM_NCLBUTTONDOWN = &HA1
Public Const WM_SYSCOMMAND = &H112
Public Const HTCAPTION = 2
Public Const SC_MOVE = &HF010&

Public hWindow As Long
Public OldWindowProc As Long

‘子类消息
Public Function WindowProc(ByVal hWnd As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long

‘拦截拖动标题栏消息
If uMsg = WM_NCLBUTTONDOWN And wParam = HTCAPTION Then Exit Function

‘拦截系统菜单的“移动”消息
If uMsg = WM_SYSCOMMAND And wParam = SC_MOVE Then Exit Function

WindowProc = CallWindowProc(OldWindowProc, hWnd, uMsg, wParam, lParam)

End Function

2.修改窗口结构全面禁止移动窗口

上面两种方法都可以禁止移动一个窗口,但是这种方法只能欺骗用户,而无法欺骗操作系统,即它不能防止用户通过其它第三方工具来改变一个窗口的位置,如调用MoveWindow或SetWindowPos函数来改变一个窗口的位置,然而下面这种方法就可以。

当一个窗口开始移动时会产生WM_MOVE与WM_WINDOWPOSCHANGING消息,移动结束后又会产生WM_MOVING和WM_WINDOWPOSCHANGED消息,其中WM_WINDOWPOSCHANGING消息是正在移动时产生的,我们可以拦截到这个消息,然后改变窗口位置结构的值,来控制窗口的位置与大小。

代码:
‘Form1中
‘———————————————————
Private Sub Form_Load()
Me.Show
hWindow = Me.hWnd
OldWindowProc = SetWindowLong(hWindow, GWL_WNDPROC, AddressOf WindowProc)
End Sub

Private Sub Form_Unload(Cancel As Integer)
Call SetWindowLong(hWindow, GWL_WNDPROC, OldWindowProc)
End Sub

‘Module1中
‘———————————————————
Option Explicit
Declare Function GetWindowLong Lib “user32” Alias “GetWindowLongA” (ByVal hWnd As Long, ByVal nIndex As Long) As Long
Declare Function SetWindowLong Lib “user32” Alias “SetWindowLongA” (ByVal hWnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Declare Function CallWindowProc Lib “user32” Alias “CallWindowProcA” (ByVal lpPrevWndFunc As Long, ByVal hWnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Declare Function GetWindowRect Lib “user32” (ByVal hWnd As Long, lpRect As RECT) As Long
Declare Sub CopyMemory Lib “kernel32” Alias “RtlMoveMemory” (pDest As Any, pSource As Any, ByVal ByteLen As Long)

Public Const GWL_WNDPROC = (-4)
Public Const WM_WINDOWPOSCHANGING = &H46

Public Type WINDOWPOS
    hWnd As Long
    hWndInsertAfter As Long
    x As Long
    y As Long
    cx As Long
    cy As Long
    flags As Long
End Type

Public Type RECT
    Left As Long
    Top As Long
    Right As Long
    Bottom As Long
End Type

Public hWindow As Long
Public OldWindowProc As Long
Public DeMoveWindow As Boolean

‘消息处理
Public Function WindowProc(ByVal hWnd As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long

Dim wPos As WINDOWPOS
Dim wRect As RECT

‘拦截窗口位置改变的消息
If uMsg = WM_WINDOWPOSCHANGING Then
    CopyMemory wPos, ByVal lParam, Len(wPos)
    GetWindowRect hWnd, wRect
    wPos.x = wRect.Left
    wPos.y = wRect.Top
    CopyMemory ByVal lParam, wPos, Len(wPos)
End If

WindowProc = CallWindowProc(OldWindowProc, hWnd, uMsg, wParam, lParam)

End Function

好了,现在这个窗口已经无法移动了,同理,你还可以修改cx和cy属性来限制窗口的宽度和高度。

发表评论

您的电子邮箱地址不会被公开。