Author: Felipe Machado
This article shows a technique to drag a form without caption other than responding
to NC_HITTEST messages. This technique can also be used to accomplish the dragging
of Windowed controls inside the form.
Answer:
The code bellow was created when I was writting a component to allow the dragging
of forms without captions. First I found code using the NC_HITTEST message, but the
technique presented here offers a lot of other possibilities since it can be
applied to any windowed control (not only forms), and will allow you to move them
on the form with only 2 or 3 lines of code.
It consists of sendind a WM_SYSCOMMAND message to the desired window (remember that
all windowed controls are considered windows on the Windows OS :-) with the correct
parameters set, and the window will behave as if the user had started dragging the
window by clicking on its caption (this works even with windows without captions,
like text boxes.)
The funny part was that this parameter for the WM_SYSCOMMAND message isn't
documented (it isn't on my Windows SDK help). I've discovered it while debugging an
application. I've put a handler for the WM_SYSCOMMAND message and was showing on
the screen all the values for its parameters and to my surprise, when I started to
drag the form the value $F012 poped-up. Then I tried to send it to the form and it
didn't worked. After a while I figure out how to do it correctly and the code for
this follows:
Put the code bellow on the OnMouseDown handler for any form:
1
2 procedure TForm1.FormMouseDown(Sender: TObject;
3 Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
4 begin
5 if Button = mbLeft then
6 begin
7 ReleaseCapture;
8 Perform(WM_SYSCOMMAND, $F012, 0);
9 end;
10 end;
You can also put this code on the OnMouseDown of a single panel or a group of
panels, effectively creating a new drag point for the form. When the user tries to
drag the panel you send the message above to the form and a dragging operation will
start. It is easier to accomplish this with this method than using the NC_HITTEST
message:
11
12 procedure TForm1.Panel1MouseDown(Sender: TObject;
13 Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
14 begin
15 if Button = mbLeft then
16 begin
17 ReleaseCapture;
18 Perform(WM_SYSCOMMAND, $F012, 0);
19 end;
20 end;
21
22 //If you write
23
24 Panel1.Perform(WM_SYSCOMMAND, $F012, 0)
the panel will start moving inside the form as if it was itself a form. When you
release the mouse it will stay were you left it (no additional code required).
This code can be much useful sometimes, but it is very very simple. Hope you liked
it.
I played a bit with the code modifying the $F000 Part.
$F000 (Center cursor on the form)
$F001 (Resize from left)
$F002 (Resize from right)
$F003 (Resize from up)
$F004 (Lock the bottom right corner of the form, the up left corner move for
resize)
$F005 (Same from bottom left corner)
$F006 (Lock up right and left border, resize other)
$F007 (Lock up and right border, resize other border)
$F008 (Lock left and up border and resize other)
$F009 (Drag from anywhere)
$F010 (Put cursor centered at the upper order)
$F020 (Auto-Minimize Form)
$F030 (Auto-Maximize Form)
$F040 (Stop! You don't want that, it will lock all mouse click and make
you reboot)
$F148 (Activate ScreenSaver)
$F13E (Activate StartButton)
|