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

发布于 2024-11-30 23:42:01 字数 774 浏览 2 评论 0原文

我想要一个 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;
}

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

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, but I'm stuck with getting it movable.

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

It's probably only a matter of finding the correct flags. Any ideas?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

仅此而已 2024-12-07 23:42:01

允许窗体移动的最佳方法是模仿单击并拖动标题栏时窗体的移动方式。由于您的窗口没有标题栏,因此当 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;
        }
    }
}

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:

  • This method will be called for every message the form gets; don't do anything slow or complex here.
  • Always let the default inherited implementation of 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.
  • You can set a region of the form to be the draggable bit by checking the mouse coordinates. In the below code, only the top 100 pixels of the form will be draggable.

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;
        }
    }
}
檐上三寸雪 2024-12-07 23:42:01

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

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

Try to place this code to Form OnMouseDown event handler:

ReleaseCapture();
this->Perform(WM_SYSCOMMAND, 0xF012, 0);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文