The information in this article applies to:
- Standard and Professional Editions of Microsoft Visual Basic for
Windows, versions 2.0, 3.0
SUMMARY
This article shows by example how to implement the Windows API
SendMessage function with the WM_SYSCOMMAND message so that you can
move a form with the mouse when that form has no caption or titlebar.
MORE INFORMATION
The WM_SYSCOMMAND message is sent when a user chooses a command from the
System menu (sometimes referred to as the Control menu) or when the user
chooses the Maximize or Minimize button. It is also sent when a user
clicks the window's Titlebar or Caption; this is a special case of the
Move command in the System menu. When you click the title bar, the value
sent by WM_SYSCOMMAND is &HF012. However, when you choose the Move
command from the Control menu, the value sent is SC_MOVE = &HF010.
A problem arises, however, if you set the ControlBox, MinButton, and
MaxButton properties to false and remove the Caption of the form (by
setting the Caption property to "" or an empty string) because then
there's no way for your user to move the form.
You can work around this problem by creating a hot spot -- a label or
image control -- that when clicked will send the WM_SYSCOMMAND message.
By sending the WM_SYSCOMMAND message, you give your users a way to move
the form. This works regardless of the borderstyle property setting of
the form.
NOTE: If the form has a menu attached to it, a title bar or caption area is
supplied by default, so the technique in this article would be redundant.
Step-by-Step Example
- Start a new project in Visual Basic (ALT, F, N). Form1 is created by
default.
- Set the ControlBox, MinButton, and MaxButton properties of Form1 to
False.
- Add a label (Label1) to the form.
- Add a new module (ALT, F, M), and add the following declarations to the
module.
Type POINTAPI ' Used for GetCursor - gets mouse location
X As Integer ' in screen coordinates.
Y As Integer
End Type
Type ConvertPOINTAPI ' Used by WM_SYSCOMMAND - converts mouse location.
xy As Long
End Type
' Enter the following Declare statement as one, single line:
Declare Function Sendmessage Lib "User" (ByVal hwnd As Integer,
ByVal wMsg As Integer, ByVal wParam As Integer,
ByVal lParam As Any) As Long
Declare Sub GetCursorPos Lib "User" (lpPoint As POINTAPI)
Global Const WM_LBUTTONUP = &H202
Global Const WM_SYSCOMMAND = &H112
Global Const MOUSE_MOVE = &HF012
- Place the following code in the Form_Load() event of Form1:
Sub Form_Load()
Form1.Caption = ""
Label1.Caption = "Click Here to Move the Form"
Label1.BorderStyle = 1 ' Place a border around the label.
Label1.AutoSize = True
' Position the label at the top of the form:
Label1.Move 0, 0, Me.ScaleWidth
End Sub
- Add the following code to the Label1_MouseDown() event:
Sub Label1_MouseDown ()
Dim mpos As POINTAPI
Dim p As ConvertPOINTAPI
Dim ret As Integer
Call GetCursorPos(mpos) ' Get the current position of the cursor
LSet p = mpos ' and convert it for SendMessage calls.
' Send LButtonUp to finish the impending LButtonDown.
' This line of code will invoke the Label1_MouseUp() event,
' so be careful what code you place in that event:
ret = Sendmessage(Me.hWnd, WM_LBUTTONUP, 0, p.xy)
' NOTE: If you are using a control that has a Window Handle
'(hWnd) as your hot spot, then that control is receiving the
' mouse messages and you need to send the WM_LBUTTONUP message
' to that control, not the form. Therefore, you would need
' to change the above line of code to read:
'
' ret = SendMessage(MyControl.hWnd, WM_LBUTTONUP, 0, p.xy)
'
' where MyControl is the control you are using as the hot spot
' Now tell the form someone is clicking the window caption:
ret = Sendmessage(Me.hWnd, WM_SYSCOMMAND, MOUSE_MOVE, p.xy)
End Sub
- Press the F5 key to run the code. Click the label to move the form.
|