这几天做的一个程序,搞的相当苦恼!
要再父窗体内嵌套子窗体,而父窗体又不是顶级窗体,又不能设置MDI多文档,还得要能拖动!
搞了好几天,问了很多人,没有什么好的解决方式。
这几天自己研究了下,发现了一个比较折中的方式。就是父窗体内容嵌套其他容器,将子窗体填充到该容器中。
(但是这个还是有缺陷的,因为容器背景色的问题)
废话不多说 我用的容器时Panel,窗体一共两个,父窗体CarApplyListing 子窗体CarApplyMain
1.首先申明子窗体所需要的变量
/// <summary>
/// 是否已经移动本窗体
/// </summary>
private bool isMove = false;
/// <summary>
/// 是否第一次移动
/// </summary>
private bool firstMove = true;
/// <summary>
/// 默认坐标(0,0)
/// </summary>
Point p = new Point(0, 0);
2.在子窗体中添加两个事件(只要是为了子窗体在父窗体大小空间内拖动,否则它只能在容器的范围内容拖动)
一个是MouseCaptureChanged 这个是当窗体的鼠标焦点切换时触发
- /// <summary>
- /// 失去鼠标或者获得鼠标焦点
- /// </summary>
- /// <param name="sender"></param>
- /// <param name="e"></param>
- private void CarApplyMain_MouseCaptureChanged(object sender, EventArgs e)
- {
- Panel ccPanel = this.Parent as Panel; // 取得父容器
- ccPanel.Size = ccPanel.Parent.Size; // 获取Panel父容器大小
- // 记录Panel的原坐标,设置Panel的新坐标
- Point pPanel = ccPanel.Location;
- ccPanel.Location = p;
- if (firstMove || isMove)
- {
- // 第一次加载获知已经移动本窗体,设置本窗体位置为原Panel位置
- this.Location = pPanel;
- }
- isMove = false;
- }
另外一个是Move 这个当窗体移动时触发(本来想用LocationChange的,但是这个事件会造成子窗体乱跳)
- /// <summary>
- /// 窗体移动事件
- /// </summary>
- /// <param name="sender"></param>
- /// <param name="e"></param>
- private void CarApplyMain_Move(object sender, EventArgs e)
- {
- if (firstMove)
- {
- // 第一次加载 退出窗体移动事件
- firstMove = false;
- return;
- }
- if (this.Location != p && !isMove)
- {
- Panel ccPanel = this.Parent as Panel; // 取得父容器
- ccPanel.Size = this.Size; // 获取Panel父容器大小
- // 重新设置 窗体和其父容器的位置
- ccPanel.Dock = System.Windows.Forms.DockStyle.None;
- ccPanel.Location = this.Location;
- isMove = true;
- this.Location = p; // 重置窗体位置
- }
- }
3.在子窗体关闭时调用父窗体的方法
// 设置Panel隐藏
CarApplyListing car = this.Parent.Parent as CarApplyListing;
car.ClosePanel();
4.在父窗体中加入以下方法
- /// <summary>
- /// 显示摘要单据窗体
- /// </summary>
- /// <param name="frm">用车申请单窗体</param>
- public void ShowPanel(CarApplyMain frm)
- {
- carApplyMain = frm;
- // 移除Panel内的所有控件
- ccPanel.Controls.Clear();
- // 添加用车申请单窗体
- ccPanel.Controls.Add(carApplyMain);
- // 显示窗体
- if (carApplyMain == null || carApplyMain.IsDisposed)
- {
- carApplyMain = new CarApplyMain();
- carApplyMain.Show();
- }
- else
- {
- carApplyMain.WindowState = FormWindowState.Normal;
- carApplyMain.Activate();
- carApplyMain.Show();
- }
- // 设置Panel大小与窗体相同
- ccPanel.Size = new System.Drawing.Size(carApplyMain.Size.Width, carApplyMain.Size.Height);
- // 重新设置Panel的位置
- SetLocation();
- // 设置Panel显示
- ccPanel.Visible = true;
- }
- /// <summary>
- /// 隐藏摘要单据窗体
- /// </summary>
- public void ClosePanel()
- {
- // 隐藏Panel
- this.ccPanel.Visible = false;
- }
- /// <summary>
- /// 重新设置坐标
- /// </summary>
- public void SetLocation()
- {
- // 设置Panel 默认居中
- ccPanel.Top = (this.Height - ccPanel.Height) / 2;
- ccPanel.Left = (this.Width - ccPanel.Width) / 2;
- }
5.在父窗体内添加一个按钮,调用ShowPanel方法,把子窗体传进去就OK了。(此法最大的局限就是Panel,它最大化会把整个窗体都覆盖,有点丑就是了)