FMX跨平台应用移动TMenuItem后丢失OnClick事件问题
Delphi FMX跨平台菜单迁移问题:顶层菜单项OnClick失效
问题背景
我开发了一款支持Windows和macOS的Delphi FMX跨平台应用,Windows平台使用TMenuBar,macOS平台使用TMainMenu。设计阶段统一使用TMainMenu,在Windows平台启动主窗体时,通过以下代码将TMainMenu的菜单项移至TMenuBar:
procedure TPartViewer.CopyMenu(MenuBar: TMenuBar); var smi: TMenuItem; begin while MainMenu1.ItemsCount > 0 do begin smi := TMenuItem(MainMenu1.items[0]); MenuBar.AddObject(smi); end; end;
问题现象
顶层菜单项的OnClick事件失效,其余功能均正常:菜单可正常展开,下层菜单项功能完全正常。我原本通过顶层菜单项的OnClick事件触发下层菜单项的启用/禁用逻辑。
排查结果
经追踪发现,问题源于FMX.Platform.Win未收到WM_LBUTTONUP消息,但奇怪的是WM_RBUTTONUP消息可正常触发OnClick事件。尝试重新为OnClick事件绑定新方法也无效,而当菜单项留在TMainMenu中时,功能完全正常。
思考方向?
改进方案
问题核心在于缺失MouseUp事件——没有MouseUp就无法触发OnClick,但MouseDown事件是正常的。由于MouseUp是公共属性而非发布属性,因此遍历顶层菜单项,若存在OnClick事件则将其转换为MouseDown事件:
// 用于存储事件的小型组件 type TEventHolder = class(TComponent) public Notify: TNotifyEvent; end; // 转换事件处理函数 procedure TPartViewer.FixMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Single); begin TEventHolder(TMenuItem(Sender).TagObject).Notify(sender); end; procedure TPartViewer.CopyMenu(MenuBar: TMenuBar); var smi: TMenuItem; holder: TEventHolder; begin while MainMenu1.ItemsCount > 0 do begin smi := TMenuItem(MainMenu1.items[0]); if assigned(smi.OnClick) then begin smi.OnMouseDown := FixMouseDown; holder := TEventHolder.Create(self); holder.Notify := smi.OnClick; smi.TagObject := holder; // 清空原事件,避免后续修复后触发两次 smi.OnClick := nil; end; MenuBar.AddObject(smi); end; end;
内容的提问来源于stack exchange,提问作者Bill F
相关产品推荐
相关产品推荐

