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

mor*_*ort 1 winapi vcl c++builder

我想要一个带有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;
}
Run Code Online (Sandbox Code Playgroud)

这可能只是找到正确的标志.有任何想法吗?

小智 5

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

ReleaseCapture();
this->Perform(WM_SYSCOMMAND, 0xF012, 0);
Run Code Online (Sandbox Code Playgroud)

  • 最好提供一个 `WM_NCHITTEST` 处理程序返回 HTCAPTION,其中表单应该是可移动的,而不是一个未记录的技巧。 (2认同)

Dav*_*vid 5

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

为此,您可以响应WM_NCHITTEST消息,这可以通过覆盖表单的WndProc方法轻松完成.此消息在几种情况下发送(不仅仅是鼠标点击或移动),因此在收到此消息时不要假设用户正在执行的操作.通过将消息结果设置为来处理它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;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)