Delphi 12.1无标题MDI子窗体WMHitTest失效问题求助
Delphi 12.1 MDI子窗体WM_NCHITTEST消息失效问题
问题描述
MDI子窗体通过重写CreateParams移除标题栏:
procedure CreateParams(var Params : TCreateParams) ; override ; procedure TFormChart.CreateParams(var Params : TCreateParams) ; begin inherited CreateParams(Params) ; Params.Style := (Params.Style) and (not ws_Caption) ; end ;
同时通过重写WM_NCHITTEST消息,让窗体上的标签模拟标题栏功能(点击拖动、双击最大化):
procedure WMHitTest(VAR Msg: TWMNcHitTest); Message WM_NCHITTEST; procedure TFormChart.WMHitTest(var Msg: TWMNcHitTest); begin Inherited; //ScripNameRect contains the coords of the label which acts as the form caption if PtInRect(ScripNameRect,ScreenToClient(Point(Msg.XPos,Msg.YPos))) then begin Msg.Result := HTCAPTION ; end; end;
该逻辑从Delphi 5到Delphi 11.3均正常运行,但升级到Delphi 12.1后,CreateParams仍正常生效(窗体无标题),但WMHitTest方法不再被调用。已知Delphi 12.1对MDI机制做了底层变更。
原因分析
Delphi 12.1调整了VCL MDI子窗体的消息路由:当子窗体移除ws_Caption样式后,WM_NCHITTEST这类非客户区消息不再直接发送给子窗体,而是由MDI父窗体的消息循环拦截处理,导致子窗体的重写方法无法触发。
解决方案
方案1:通过鼠标消息模拟标题栏行为
放弃依赖WM_NCHITTEST,直接拦截鼠标按下和双击消息来实现拖动和最大化功能:
// 声明消息处理方法 procedure WMLButtonDown(var Msg: TWMLButtonDown); message WM_LBUTTONDOWN; procedure WMLButtonDblClk(var Msg: TWMLButtonDblClk); message WM_LBUTTONDBLCLK; // 实现拖动逻辑 procedure TFormChart.WMLButtonDown(var Msg: TWMLButtonDown); begin inherited; if PtInRect(ScripNameRect, ScreenToClient(Point(Msg.XPos, Msg.YPos))) then begin ReleaseCapture; Perform(WM_SYSCOMMAND, SC_MOVE or HTCAPTION, 0); end; end; // 实现双击最大化/还原逻辑 procedure TFormChart.WMLButtonDblClk(var Msg: TWMLButtonDblClk); begin inherited; if PtInRect(ScripNameRect, ScreenToClient(Point(Msg.XPos, Msg.YPos))) then begin WindowState := IfThen(WindowState = wsMaximized, wsNormal, wsMaximized); end; end;
方案2:调整窗体样式保留消息触发
如果希望继续使用WM_NCHITTEST,可以修改CreateParams,保留ws_Caption但隐藏标题栏的可见元素:
procedure TFormChart.CreateParams(var Params: TCreateParams); begin inherited; // 保留ws_Caption以保证消息触发,移除边框和对话框框架 Params.Style := Params.Style and not (ws_Border or ws_DlgFrame); // 添加工具窗口扩展样式,隐藏标题栏文字和按钮 Params.ExStyle := Params.ExStyle or WS_EX_TOOLWINDOW; end;
这种方式能让WM_NCHITTEST继续触发,同时保持窗体无可见标题栏的效果,需要根据实际需求调整边框样式。
总结
方案1更稳定,不受MDI底层变更影响,适合大多数场景;方案2需根据窗体样式需求微调,兼容性略差。
内容的提问来源于stack exchange,提问作者Shekar Arumugam
相关产品推荐
相关产品推荐

