我想要一个带有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;
}
这可能只是找到正确的标志。有什么想法吗?
答案 0 :(得分:5)
允许表单移动的最佳方法是模拟单击并拖动标题栏时表单的移动方式。由于您的窗口没有标题栏,当Windows需要知道鼠标光标在您的表单的哪个部分时,您撒谎并告诉Windows它确实在标题栏上方。之后,移动工作正常,因为默认行为开始了。
要执行此操作,请回复WM_NCHITTEST
message,overriding the form's WndProc
method可轻松完成此操作。此消息在几种情况下发送(不仅仅是鼠标点击或移动),因此在收到此消息时不要假设用户正在执行的操作。通过将消息结果设置为HTCAPTION
来处理它,该值表示位置在标题栏上方。
需要注意的重要事项是:
WndProc
的默认继承实现处理该消息。这对于大多数消息来说都是必不可少的,因为你只想改变这个消息的行为,如果你不调用继承的植入,根本不会发生消息,但是对于这个消息也很重要,因为你不知道什么代码需要发送此消息。即,您想要添加程序如何响应此而不是替换它。这是您拦截/添加的所有邮件处理的一般良好指南。 WndProc
文档也提到了这一点。示例代码:
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);