所谓悬挂窗口,就是类似QQ聊天工具的一个功能,当窗口放到桌面的上边界时自动收缩成一个小条隐藏起来;而一旦鼠标再次接触到上述边界的时候,窗口又会自动展开。
实现方法有两类,一是窗口内实现悬挂,在窗口内创建一个小的Panel,正常时不可见,在悬挂是显示,
悬挂时设置窗口标题栏不显示和窗口高度为该Panel高度;二是单独窗口悬挂,创建新的窗口作为悬挂时的显示条,同时隐藏掉主窗口。
一、窗口内实现悬挂
在LocationChanged事件内判断是否到桌面上边界,通过定时器判断当前鼠标位置(System.Windows.Forms.Control.MousePosition)是否离开窗口区域,或者进入窗口区域。
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; namespace Demo { /// <summary> /// 方法一:窗口内实现悬挂 /// </summary> public partial class Form1 : Form { public Form1() { InitializeComponent(); pnlHangBar.Visible = false; m_NomalHeight = Height; m_IsHange = false; timer1.Enabled = true; timer1.Interval = 200; timer1.Tick += new EventHandler(timer1_Tick); } /// <summary> /// 窗体正常高度 /// </summary> int m_NomalHeight = 0; /// <summary> /// 窗体是否处于悬挂状态 /// </summary> bool m_IsHange = false; /// <summary> /// 窗体被激活时触发 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void Form1_Activated(object sender, EventArgs e) { Text = "Activated:" +MousePosition.ToString(); } /// <summary> /// 窗体被停用时触发 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void Form1_Deactivate(object sender, EventArgs e) { Text = "Deactivate:" + MousePosition.ToString(); } /// <summary> /// 悬挂 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btnHang_Click(object sender, EventArgs e) { if (this.FormBorderStyle == FormBorderStyle.None) { this.FormBorderStyle = FormBorderStyle.Sizable; pnlHangBar.Visible = false; } else { this.FormBorderStyle = FormBorderStyle.None; pnlHangBar.Visible = true; this.Height = pnlHangBar.Height; m_IsHange = true; } } /// <summary> /// 窗体位置改变时触发,判断是否应该悬挂窗体 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void Form1_LocationChanged(object sender, EventArgs e) { if (Location.Y <= 0) { Top = 0; m_IsHange = true; } else { m_IsHange = false; } Text = "LocationChanged:" + MousePosition.ToString(); } /// <summary> /// 显示或悬挂窗体 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> void timer1_Tick(object sender, EventArgs e) { // 鼠标在屏幕的位置 lblMousePosition.Text = MousePosition.ToString(); lblMousePosition2.Text = "鼠标在屏幕的位置:" + MousePosition.ToString(); // 鼠标在窗体客户端内的位置 Point pClient = this.PointToClient(MousePosition); lblClientPosition.Text = "鼠标在窗体客户端内的位置:" + pClient.ToString(); // 窗体悬挂 if (pClient.X < 0 || pClient.X > Width || pClient.Y > Height) //在窗体客户区域之外时 { if (m_IsHange) { this.FormBorderStyle = FormBorderStyle.None; pnlHangBar.Visible = true; this.Height = pnlHangBar.Height; } } else //在窗体客户区域之内 { if (m_IsHange) { this.FormBorderStyle = FormBorderStyle.Sizable; pnlHangBar.Visible = false; this.Height = m_NomalHeight; } } } private void Form1_Resize(object sender, EventArgs e) { if(!m_IsHange) m_NomalHeight = this.Height; } } }
二、单独窗口悬挂
本来不想考虑第二种方式的,但是后来发现需要悬挂的窗口设置高度居然无效,是一个从DevComponents.DotNetBar.Office2007RibbonForm继承的窗口类。
实现思路基本一样,只是需要注意的是判断当前鼠标的位置需要分不同的窗口转换坐标,还有其他细节见代码。
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; namespace Demo { public partial class Form2 : Form { public Form2() { InitializeComponent(); timer1.Enabled = true; timer1.Interval = 500; } /// <summary> /// 窗体是否处于悬挂状态 /// </summary> bool m_IsHange = false; /// <summary> /// 悬挂标志窗口 /// </summary> FrmHideFlagForm m_HideFlagForm = new FrmHideFlagForm(); /// <summary> /// 窗体位置改变时触发,判断是否应该悬挂窗体 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void Form2_LocationChanged(object sender, EventArgs e) { if (Location.Y < 0) { Top = 0; m_IsHange = true; } else { m_IsHange = false; } SetHideFlagFormPos(); } /// <summary> /// 设置标志窗体的位置和大小 /// </summary> private void SetHideFlagFormPos() { m_HideFlagForm.Left = this.Left; m_HideFlagForm.Top = this.Top; m_HideFlagForm.Width = this.Width; m_HideFlagForm.Height = 10; } /// <summary> /// 显示或悬挂窗体 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void timer1_Tick(object sender, EventArgs e) { if (System.Windows.Forms.Control.MouseButtons == MouseButtons.Left) return; //在鼠标左键为按下时,认为窗口处在拖动状态,暂停鼠标位置的判断 ShowHideForm(); } /// <summary> /// 悬挂或者展开窗体 /// </summary> private void ShowHideForm() { Point pMousePosition = new Point(System.Windows.Forms.Control.MousePosition.X, System.Windows.Forms.Control.MousePosition.Y); Point pClientPosition = new Point(); int iHight = 0; if (this.Visible) { pClientPosition = PointToClient(pMousePosition); iHight = Height; } else { pClientPosition = m_HideFlagForm.PointToClient(pMousePosition); iHight = m_HideFlagForm.Height; } if (pClientPosition.X < 0 || pClientPosition.X > Width || pClientPosition.Y > iHight) //在窗体客户区域之外时 { if (m_IsHange && FormBorderStyle != FormBorderStyle.None) { FormBorderStyle = FormBorderStyle.None; this.Hide(); m_HideFlagForm.Show(); SetHideFlagFormPos(); } } else //在窗体客户区域之内 { if (m_IsHange && FormBorderStyle != FormBorderStyle.Sizable) { FormBorderStyle = FormBorderStyle.Sizable; m_HideFlagForm.Hide(); this.Show(); } } } /// <summary> /// 窗口大小改变事件 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void Form2_Resize(object sender, EventArgs e) { m_HideFlagForm.Left = Left; m_HideFlagForm.Width = Width; } } }
参考自:http://www.cnblogs.com/haiyabtx/archive/2012/09/21/2697202.html