Visio Drawing Control 整合自訂右鍵選單有兩條路徑:攔截滑鼠事件彈出 WinForms ContextMenu,或在 PageSheet 寫入 Action 觸發 RUNADDONWARGS。前者完全自訂,後者保留內建選單(複製/貼上等)。本文完整對比兩種實作細節。
drawingControl.MouseUpEvent +=
new AxMicrosoft.Office.Interop.VisOcx.EVisOcx_MouseUpEventHandler(onDrawingControlMouseUp);
private void onDrawingControlMouseUp(object sender, EVisOcx_MouseUpEvent e) {
// 僅處理右鍵且未按 Ctrl
if (e.button == (int)VisKeyButtonFlags.visMouseRight
&& (e.keyButtonState & (int)VisKeyButtonFlags.visKeyControl) == 0) {
// Visio 座標 → 螢幕座標
Shape clicked = Utility.GetClickedShape(drawingControl, e.x, e.y);
if (clicked != null) {
e.cancelDefault = true; // 取消預設選單
Point screenPt = Utility.MapVisioToWindows(drawingControl, e.x, e.y);
shapeShortcutMenu.Show(this, screenPt);
}
}
}
Page page = VisioUtility.GetPage(visDoc, "饋線圖");
if (page != null) {
// 移除現有 Action 區段,避免重複
page.PageSheet.DeleteSection((short)VisSectionIndices.visSectionAction);
// 新增自訂選單項
VisioUtility.AddRightMouseAction(page.PageSheet,
"\"停電分析\"", // 選單標題
"RUNADDONWARGS(\"QUEUEMARKEREVENT\", \"/Drawing=停電分析\")", // 動作命令
true, false, false, false, true, true); // 啟用/勾選/分組/置底/標題公式/可見
}
public static void AddRightMouseAction(Shape targetShape, string menuCaption, string menuAction,
bool menuEnabled, bool menuChecked, bool beginGroup, bool addToBottom,
bool menuCaptionIsFormula, bool menuVisible) {
// 內部實作:在 targetShape 的 Actions 區段新增 Row,填寫 Action, Menu, Enabled 等 Cell
// Action Cell 公式即為 menuAction 參數
}
主程式需實作 IVisEventProc 監聽 MarkerEvent,解析 moreInfo 參數執行對應業務邏輯。
| 維度 | ContextMenu (方式一) | Action/RUNADDONWARGS (方式二) |
|---|---|---|
| 選單內容 | 完全自訂 | 自訂 + 內建 (複製/貼上/群組等) |
| 實作複雜度 | 需自行處理座標轉換、選取判斷 | 純 ShapeSheet 公式,無 UI 代碼 |
| 效能 | Managed 代碼略慢 | 原生處理,極快 |
| 圖示支援 | 完整支援 ImageList | 受限於 ShapeSheet 圖示機制 |
| 適用場景 | 複雜互動、動態選單項、需圖示 | 簡單靜態選單、需保留內建功能 |
兩種方式可共存:在特定 Shape 上用 Action,全域右鍵用 ContextMenu。