C++ Builder嵌入TCard的子窗体TMainMenu点击后子菜单显示错位问题
问题根源
VCL的菜单系统默认计算子菜单弹出坐标时,会将菜单所在窗体视为顶级窗口计算坐标,不会叠加子窗体作为控件嵌入父容器后的坐标偏移,所以会出现子菜单偏移到屏幕左上角对应位置的问题。
优先推荐的解决方案(无需自定义绘制菜单)
两种方案可直接解决坐标识别问题:
方案1:手动同步父窗口句柄
在你原有的嵌入代码基础上,增加一行WinAPI的SetParent调用,让系统正确识别窗体的层级关系,90%以上的同类嵌入窗体菜单偏移问题都可以通过这个方式解决:
EmbeddedForm->Parent = ACard; SetParent(EmbeddedForm->Handle, ACard->Handle); // 新增这行,同步Win32窗口层级 EmbeddedForm->BorderStyle = bsNone; EmbeddedForm->Align = alClient; EmbeddedForm->Show();
方案2:将TMainMenu移到顶级父窗体
如果方案1无效,可以把放在EmbeddedForm上的TMainMenu组件移动到承载TCard的顶级父窗体上,菜单的点击逻辑绑定保持和原有子窗体的逻辑关联即可,顶级窗体的菜单系统计算坐标时会自动识别正确的屏幕位置,不会出现偏移。
如果你需要继续使用原有的DrawItem修改坐标的方案
要调用基类protected的DrawItem方法,只需要继承TMainMenu类把protected方法提升为public即可,无需自行实现绘制逻辑:
- 自定义继承类:
class TPublicDrawMainMenu : public TMainMenu { public: // 直接把基类的protected方法暴露为public using TMainMenu::DrawItem; };
- 将你EmbeddedForm上的
MainMenu1组件的类替换为自定义的TPublicDrawMainMenu - 即可在你的DrawItem事件中修改坐标后直接调用基类绘制:
void __fastcall TEmbeddedForm::File1DrawItem(TObject *Sender, TCanvas *ACanvas, TRect &ARect, bool Selected) { // 修正坐标,比如叠加子窗体本身在父容器中的偏移 POINT formOffset = ACard->ClientToScreen(Point(0,0)); ARect.Offset(formOffset.x, formOffset.y); // 直接调用基类的绘制逻辑 dynamic_cast<TPublicDrawMainMenu*>(MainMenu1)->DrawItem(Sender, ACanvas, ARect, Selected); }
内容的提问来源于stack exchange,提问作者iplayfast
相关产品推荐
相关产品推荐

