模塊化的開發,將模塊合並到一起的時候,遇到了Mdi不能添加到其它窗口下的問題。
分兩種情況:
將mdi窗口A設成普通窗口B的子控件,需要將A的TopLevel設置成false,但是Mdi窗口的TopLevel必須為頂級;
將mdi窗口A設成mdi窗口B的子窗口,A.MdiParent = B,編譯時不通過,窗口不能既是mdi子級,又是mdi父級。
最后通過windows Api強制將mdi窗口A的parent設置成窗口B。
[DllImport("user32.dll", EntryPoint = "SetParent")] public static extern int SetParent(IntPtr hWndChild, IntPtr hWndNewParent); MDIParent1 form = new MDIParent1(); SetParent(form.Handle, this.Handle); form.Location = new Point(0, 0); form.Size = this.Size; form.Show();
通過SetParent將mdi窗口強行放到了普通的Form下。
調試的時候,界面上達到了預期的目標,但是發現了另一個新的問題。
焦點在mdi的子窗口上時,mdi窗口上的控件無效,點擊事件全部觸發不了;焦點在mdi的父窗口上時,mdi窗口的控件又“激活”了。而在單獨打開mdi窗口時,完全不存在這個問題。
查詢了一下msdn里面的SetParent的說明,發現了如下段:
“For compatibility reasons, SetParent does not modify the WS_CHILD or WS_POPUP window styles of the window whose parent is being changed. Therefore, it is not possible to change a window from parent to child or from child to parent.”
我的理解是,雖然用SetParent強制將普通窗口設置成mdi的父窗口,但是mdi的子級窗口的屬性卻沒有賦予。
解決的思路,調用另一個windows·Api SetWindowLong強制修改mdi的窗口屬性。
private const int GWL_STYLE = -16; private const int WS_CHILD = 0x40000000;//設置窗口屬性為child [DllImport("user32.dll", EntryPoint = "GetWindowLong")] public static extern int GetWindowLong(IntPtr hwnd, int nIndex); [DllImport("user32.dll", EntryPoint = "SetWindowLong")] public static extern int SetWindowLong(IntPtr hwnd, int nIndex, int dwNewLong); var s = GetWindowLong(form.Handle, GWL_STYLE); SetWindowLong(form.Handle, GWL_STYLE, s | WS_CHILD);
至此,問題算解決了。發一個效果圖:
補充一個bug:雖然解決了mdiParent獲取焦點的問題,后來發現mdiChild獲取焦點又不正常了。如果mdiChild,如上圖中的Form2界面上有TextBox控件時,修改TextBox的文字時,光標的位置,總是不正常。能力有限,尚待解決。
轉載注明出處:http://www.cnblogs.com/icyJ