Simulink 自定义顶部菜单:一键显示所有 Scope 菜单栏
Simulink 自定义顶部菜单:一键显示所有 Scope 菜单栏
测试环境:MATLAB R2016b
注意:下面两个.m文件都需要放到 MATLAB path 中,否则 Simulink 找不到脚本。
最近在做自己的 Simulink 工具箱时,遇到一个小需求:
Scope 打开以后,有些菜单栏/工具栏默认不显示,用起来不太方便。
比如想缩放、保存图像、调整窗口这些操作,如果每次都手动处理就比较麻烦。
所以我在 Simulink 顶部菜单里加了一个自己的工具入口,用来一键打开当前模型中的所有 Scope,并把 Scope 窗口的菜单栏和工具栏显示出来。
最终效果就是:
Simulink 顶部菜单 -> TG工具箱 -> Scope Tools -> Show All Scope MenuBar
1. 创建 sl_customization.m
先创建一个 sl_customization.m 文件,放到 MATLAB path 下面。
这个文件的作用是给 Simulink 注册自定义菜单。
function sl_customization(cm)
cm.addCustomMenuFcn('Simulink:MenuBar', @nova_ecu_f4_menu);
end
function schemaFcns = nova_ecu_f4_menu(callbackInfo)
%#ok<INUSD>
% 顶层菜单
schemaFcns = { @nova_ecu_f4_top_menu };
end
function schema = nova_ecu_f4_top_menu(callbackInfo)
%#ok<INUSD>
schema = sl_container_schema;
% Simulink 顶部菜单显示的名字
schema.label = 'TG工具箱';
% tag 尽量唯一,避免和其他工具箱冲突
schema.tag = 'NovaECU:F4:TopMenu';
% 顶层菜单下面挂载的子菜单
schema.childrenFcns = { ...
@nova_ecu_f4_scope_tools_menu ...
};
end
function schema = nova_ecu_f4_scope_tools_menu(callbackInfo)
%#ok<INUSD>
schema = sl_container_schema;
% TG工具箱 -> Scope Tools
schema.label = 'Scope Tools';
schema.tag = 'NovaECU:F4:ScopeTools';
schema.childrenFcns = { ...
@nova_ecu_f4_show_scope_menubar_item ...
};
end
function schema = nova_ecu_f4_show_scope_menubar_item(callbackInfo)
%#ok<INUSD>
schema = sl_action_schema;
% TG工具箱 -> Scope Tools -> Show All Scope MenuBar
schema.label = 'Show All Scope MenuBar';
schema.tag = 'NovaECU:F4:ShowAllScopeMenuBar';
schema.callback = @nova_ecu_f4_show_scope_menubar_callback;
end
function nova_ecu_f4_show_scope_menubar_callback(callbackInfo)
model = '';
% 优先从当前菜单上下文里取模型
try
model = get_param(callbackInfo.model, 'Name');
catch
% 取不到就退回到当前模型
try
model = bdroot(gcs);
catch
model = '';
end
end
try
if isempty(model)
nova_scope_show_menubar;
else
nova_scope_show_menubar(model);
end
catch ME
errordlg(ME.message, 'NovaECU Scope Tool Error');
end
end
这里的几个名字可以自己改,比如:
schema.label = 'TG工具箱';
这个就是 Simulink 顶部菜单栏里显示的名字。
但是 schema.tag 建议尽量写得唯一一点,最好带上自己的工具箱前缀。
比如我这里用的是:
NovaECU:F4:TopMenu
这样可以减少和别的工具箱菜单冲突的可能。
2. 创建 nova_scope_show_menubar.m
再创建一个 nova_scope_show_menubar.m 文件,也放到 MATLAB path 下面。
这个文件负责真正处理 Scope 窗口。
function nova_scope_show_menubar(model)
if nargin < 1 || isempty(model)
try
model = bdroot(gcs);
catch
model = '';
end
end
oldHidden = get(0, 'ShowHiddenHandles');
set(0, 'ShowHiddenHandles', 'On');
cleanupObj = onCleanup(@() set(0, 'ShowHiddenHandles', oldHidden)); %#ok<NASGU>
scopes = {};
% 找当前模型里的 Scope 模块
if ~isempty(model)
try
scopes = find_system(model, ...
'LookUnderMasks', 'all', ...
'FollowLinks', 'on', ...
'BlockType', 'Scope');
catch
scopes = {};
end
end
% 先把 Scope 全部打开
for i = 1:numel(scopes)
try
open_system(scopes{i});
catch
end
end
drawnow;
% Scope 本质上也是 figure 窗口
figs = findall(0, 'Type', 'figure');
count = 0;
for i = 1:numel(figs)
if local_is_scope_figure(figs(i), scopes)
try
set(figs(i), 'MenuBar', 'figure');
set(figs(i), 'ToolBar', 'figure');
count = count + 1;
catch
end
end
end
fprintf('[NovaECU] Scope windows updated: %d\n', count);
end
function tf = local_is_scope_figure(hFig, scopes)
tf = false;
try
tag = get(hFig, 'Tag');
catch
tag = '';
end
try
name = get(hFig, 'Name');
catch
name = '';
end
% R2016b 以及一些老版本 Scope 常见的 Tag
scopeTags = { ...
'SIMULINK_SIMSCOPE_FIGURE', ...
'Simulink_Scope_Figure', ...
'Scope' ...
};
for k = 1:numel(scopeTags)
if strcmpi(tag, scopeTags{k})
tf = true;
return;
end
end
% 兜底:根据 Scope block 的路径或者名称判断
for k = 1:numel(scopes)
blk = scopes{k};
try
blkName = get_param(blk, 'Name');
catch
blkName = '';
end
if isempty(name)
continue;
end
if strcmp(name, blk)
tf = true;
return;
end
if ~isempty(strfind(name, blk))
tf = true;
return;
end
if ~isempty(blkName) && strcmp(name, blkName)
tf = true;
return;
end
if ~isempty(blkName) && ~isempty(strfind(name, blkName))
tf = true;
return;
end
end
end
这里需要注意一点:
set(0, 'ShowHiddenHandles', 'On');
Scope 窗口有时候不是普通方式能直接找到的,所以这里临时打开 ShowHiddenHandles。
为了不影响 MATLAB 后续环境,脚本里用了 onCleanup,执行结束后会自动恢复原来的设置。
3. 刷新 Simulink 自定义菜单
两个文件都放好以后,在 MATLAB 命令行执行:
sl_refresh_customizations
然后重新打开 Simulink,顶部菜单里应该就能看到:
TG工具箱
点进去以后:
TG工具箱 -> Scope Tools -> Show All Scope MenuBar
点击后,当前模型里的 Scope 会被打开,并且菜单栏、工具栏会显示出来。
4. 常见问题
如果菜单没有出现,可以检查这几项:
sl_customization.m是否在 MATLAB path 中;- 修改完
sl_customization.m后,是否执行了sl_refresh_customizations; - 文件名是否写错,必须叫
sl_customization.m; - 如果还不行,可以重启 MATLAB 再试一次。
这个功能本身不复杂,但是放到自定义工具箱里还是挺方便的。
尤其是自己做 Simulink 工具箱时,把一些常用的小工具挂到菜单里,用起来会比每次手敲命令舒服很多。

浙公网安备 33010602011771号