在 MDI 父視窗使用 DevExpress XtraTabbedMdiManager 管理子視窗,同時放置 Janus Ribbon 控件作為選單。執行時拋出 System.InvalidOperationException: 窗口句柄已存在,堆疊追蹤指向 Janus 內部 NativeWindow.AssignHandle。
兩套控件庫在視窗建立階段皆嘗試子類化(Subclass)MDI 父視窗的視窗程序(WndProc),導致句柄重複指派衝突。設計時期 XtraTabbedMdiManager.MdiParent 已設定,使其在 InitializeComponent 期間即介入視窗建立流程,與 Janus Ribbon 的初始化時機撞車。
xtraTabbedMdiManager.MdiParent 設為 (無) / null。InitializeComponent() 之後、Load 事件之前,以程式碼指派:public MainForm()
{
InitializeComponent();
// 關鍵:延遲至元件初始化完成後再指派
xtraTabbedMdiManager1.MdiParent = this;
}
Janus Ribbon 在設計器初始化時已完成其視窗鉤子掛載。若 DevExpress 同步介入會搶占句柄。延遲指派讓 Janus 先完成初始化,DevExpress 再安全接管 MDI 客戶區管理,雙方各司其職,不再衝突。
當多個第三方控件庫皆需子類化同一視窗時,避免在設計器階段同時啟用。採用「設計器不綁定、運行期延遲綁定」策略,可解決絕大多數句柄衝突問題。
一行程式碼、調整一個時機,解決困擾許久的控件庫共存難題。記住:初始化順序決定成敗。