菜单项要带图标,就得走 Image 参数。往文字里塞一个 emoji,Windows 上它要么是灰的,要么位置跑到文字那一列去,两头不落好。

这是我在七亿批量远程管理工具里加「SSH 运维 AI 助手」那阵子踩的。说是坑,其实一开始我没当回事——功能全通:点下去弹对话窗,连上 SSH,一条条跑命令,回显都正常。图标难看算什么问题。

那天的版本号从 V95 一路跳到 V113,一天 18 个版本,边用边冒,冒一个补一个。图标这件属于少数几个「不影响功能、但每天看着难受」的。具体哪一版改的记不清了,反正在那天那堆版本里。

问题出在这一行:

var item = new ToolStripMenuItem("🤖 AI 助手", null, OnAiAssistantClick);

第二个参数给的是 null,就是没有图。于是 🤖 变成普通文字的一部分,跟着标题一起排版,落在文字列开头,左边那列图标栏空着。WinForms 的 ToolStripMenuItem 渲染时图标列和文字列分开算,你不给 Image,它不会自己去文字里认一个图标出来。

颜色也不对。Windows 上 emoji 要彩色得走 Segoe UI Emoji 那套彩色字形,菜单项这种 GDI/GDI+ 的老绘制路径拿到的是单色轮廓,最后就是一个灰黑色的机器人头,跟旁边几个 16×16 的彩色 PNG 摆一起,像贴了张打印出来的证件照。

我第一反应是 DPI 缩放糊了,毕竟菜单图标就 16×16。盯着看了半天,才注意到第二个参数是 null——问题根本不在画质。

后来不找了,自己画。一个 32×32 的 Bitmap,Graphics 开 AntiAlias:蓝色圆角矩形当头,GraphicsPath 加四段 Arc;顶上一根橙色短天线,末端一个小圆球;脸是浅色圆角面板;眼睛两个深色椭圆,嘴一段弧。

item.Image = bmp;   // 32×32 画,16×16 显示

第一版天线画在头的正中间,出来像个天线宝宝。第二版挪到偏左,才有点像机器人。凑近看边缘还是有点毛,但至少它归位了,颜色也跟旁边一套。

emoji 在聊天框里是表情,在菜单里就是一个字符。菜单要图,就给 Image,给个真的位图,别指望字体替你干活——这条我后来写进了自己的备忘,因为差不多的错在别处也犯过。七亿批量远程管理工具的主机列表右键菜单现在挂着那一项,蓝头橙天线,算是融进去了。

右键菜单这东西,装的东西一多就乱。之前 7eZip 那边索性做了个右键菜单管理,能少塞就少塞。显示层也是,AI 对话框那个 RichTextBox 回完话一片黑、滚一下才出来,同样是画完没刷对。桌面程序这点麻烦:界面天天摆在你眼前,别扭一点,你就得看一年。

用法在七亿批量远程管理工具的说明书里。图标这种小节,说明书不会写,我也没打算加。

顺带一句,这东西是免费的,Windows 上跑,RDP 九宫格、SSH 终端、SFTP、FTP 都在一个窗口里。服务器我们自己在 七亿网络 这边卖,韩国、香港节点都有。