C# 將MDI窗口嵌入普通窗口


模塊化的開發,將模塊合並到一起的時候,遇到了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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM