I\'d like to have a TForm with BorderStyle = bsNone (no borders, no caption), which is nevertheless resizable and movable. I already figured out how to do the resizable part
Try to place this code to Form OnMouseDown event handler:
ReleaseCapture();
this->Perform(WM_SYSCOMMAND, 0xF012, 0);
The best way to allow a form to move is to mimic how a form moves when you click and drag the title bar. Since your window doesn't have a title bar, when Windows needs to know what part of your form the mouse cursor is over you lie and tell Windows that it is indeed over the title bar. After that, moving works normally since the default behaviour kicks in.
To do this, you respond to the WM_NCHITTEST message, which is easily done by overriding the form's WndProc method. This message is sent in several situations (not just mouse clicks or movement) so don't assume anything about what the user's doing when you get this message. Handle it by setting the message result to HTCAPTION
, a value indicating the position is over the title bar.
Important things to note are:
WndProc
handle the message. This is essential for most messages, since you only want to change the behaviour for this one and if you don't call the inherited implantation nothing will happen for the messages at all, but it's important for this one too since you don't know what code needs to be sent this message. I.e., you want to add to how your program responds to this, not replace it. This is a general good guideline for all message processing you intercept / add. The WndProc documentation mentions this too.Sample code:
void __fastcall TForm1::WndProc(Messages::TMessage& Message) {
TForm::WndProc(Message); // Inherited implementation
if (Message.Msg == WM_NCHITTEST) {
TWMNCHitTest& oMsg = reinterpret_cast<TWMNCHitTest&>(Message);
TPoint oPoint(oMsg.XPos, oMsg.YPos); // Screen coordinates
oPoint = ScreenToClient(oPoint); // Now in form-local coordinates
// It's in the title bar (caption) if it's in a rectangle at the top of the form
if ((oPoint.x > 0 && oPoint.x < ClientWidth) &&
(oPoint.y > 0 && oPoint.y < 100))
{
oMsg.Result = HTCAPTION;
}
}
}