C ++ Builder:使用BorderStyle bsNone创建一个可移动和可调整大小的TForm

时间:2011-08-24 15:23:42

标签: winapi c++builder vcl

我想要一个带有BorderStyle = bsNone(没有边框,没有标题)的TForm,但它仍然是可调整大小和可移动的。我已经想出了如何处理可调整大小的部分,但我仍然坚持让它可以移动。

/**
*   Overrides standard CreateParams method to create a TForm with BorderStyle
*    bsNone but is nevertheless movable and resizable
**/
void __fastcall CreateParams(TCreateParams &Params)
{
    BorderStyle = bsNone;
    TForm::CreateParams(Params);
    //set flag WS_EX_STATICEDGE
    //for more details on this flag, see http://msdn.microsoft.com/en-us/library/ms632680(v=vs.85).aspx
    Params.ExStyle = Params.ExStyle ^ 0x00020000L;
    //set flag WS_SIZEBOX
    //for more details on this flag, see http://msdn.microsoft.com/en-us/library/ff700543(v=VS.85).aspx
    Params.Style = Params.Style ^ 0x00040000L;
}

这可能只是找到正确的标志。有什么想法吗?

2 个答案:

答案 0 :(得分:5)

允许表单移动的最佳方法是模拟单击并拖动标题栏时表单的移动方式。由于您的窗口没有标题栏,当Windows需要知道鼠标光标在您的表单的哪个部分时,您撒谎并告诉Windows它确实在标题栏上方。之后,移动工作正常,因为默认行为开始了。

要执行此操作,请回复WM_NCHITTEST messageoverriding the form's WndProc method可轻松完成此操作。此消息在几种情况下发送(不仅仅是鼠标点击或移动),因此在收到此消息时不要假设用户正在执行的操作。通过将消息结果设置为HTCAPTION来处理它,该值表示位置在标题栏上方。

需要注意的重要事项是:

  • 将为表单获取的每条消息调用此方法;这里不要做任何缓慢或复杂的事情。
  • 始终让WndProc的默认继承实现处理该消息。这对于大多数消息来说都是必不可少的,因为你只想改变这个消息的行为,如果你不调用继承的植入,根本不会发生消息,但是对于这个消息也很重要,因为你不知道什么代码需要发送此消息。即,您想要添加程序如何响应此而不是替换它。这是您拦截/添加的所有邮件处理的一般良好指南。 WndProc文档也提到了这一点。
  • 您可以通过检查鼠标坐标将表单区域设置为可拖动位。在下面的代码中,只有表单的前100个像素可以拖动。

示例代码:

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;
        }
    }
}

答案 1 :(得分:4)

尝试将此代码放入Form OnMouseDown事件处理程序:

ReleaseCapture();
this->Perform(WM_SYSCOMMAND, 0xF012, 0);