Dragging a Form by its body

Moving a window is not new! We move windows by its title bar at the top. But what if we want to move a window/form by dragging its body? Could we remove the title bar of our form and have fancy interface going on? Yes. And here’s how…

Imagine you are creating a cool interface for an MP3 Player. For the intended coolness, you got rid of the title bar of the form. Instead you have a roundish form shape with a titlebar looking area. You want the user to be able to move the form by dragging the whole form. How can you do that? We’ll see how…

Quick Tutorial

Start Lazarus. Create a new project (Project -> New Project -> Application -> OK).

Switch to code view by pressing F12. Find the first var clause and add these variables:

1
2
3
4
var
...
  MouseIsDown: boolean;
  PX, PY: integer;

Now switch to form view (F12) and make sure the form is selected. Then add the following code to its OnMouseDown Event. (Go to Object Inspector -> Events tab -> OnMouseDown -> […] and enter the following code):

1
2
3
4
5
  if Button = mbLeft then begin
    MouseIsDown := True;
    PX := X;
    PY := Y;
  end;

Similarly, add the following code to its OnMouseMove event:

1
2
3
  if MouseIsDown then begin
    SetBounds(Left + (X - PX), Top + (Y - PY), Width, Height);
  end;

We use SetBounds() for shortcut. We can also use:

1
2
Form1.Left := Form1.Left + (X - PX);
Form1.Top := Form1.Top + (Y - PY);

Add the following code on its OnMouseUp Event:

1
MouseIsDown:=False;

Run it now (F9 or Run -> Run). Move the form to test your code.

Explanation:

Here are some short explanation behind the code. If you need more detailed explanation, please use the comment form below to ask.

The magic lies in the code in the MouseMove event:

1
2
3
  if MouseIsDown then begin
    SetBounds(Left + (X - PX), Top + (Y - PY), Width, Height);
  end;

We are calculating the difference of how much the mouse has travelled with (X - PX). PX is the X where the mouse was down (or where the drag has started). So, how much the mouse has moved? Answer: Current X - Previous X.

If the we drag the form 100 pixels rightwards, then the difference would be 100 (X-PX=100). Then we add the difference (100) to its Left property to really move it. Easy!

Y - PY is similar. It works with the vertical distance of how much the form has been dragged up or down.

Enhancement

You can now set the form’s BorderStyle property to bsNone. This will remove the title bar and only keep the form’s main area/body. You can use a TImage for a cool background/skin, as you wish. Don’t forget to keep a Close button to close the form! Or else, you won’t be able to quit the program!

You can see a simple utilization of the code above to create a custom looking form border. You can improve it more with your ideas.

How did I make the Close and Minimize buttons work? The button image is from the background image. There must be some invisible component to do that, right? :-) No. I have created some “invisible hotspots” by creating a bunch of TLabels and making their Caption blank. Then you can double click it and enter any command. You can create invisible components with this method.

Downloads

You can download the source code for the tutorial project and executable/EXE files from the links below: