C#如何实现类似QQ那样靠边隐藏的功能
2015-01-17 15:13
741 查看
http://www.cnblogs.com/yechensi/archive/2009/08/02/1537145.html
C#如何实现类似QQ那样靠边隐藏的功能
你想过为自己的程序添加靠边隐藏的功能吗?还在为计算窗体的大小及位置而烦恼吗?想这么简单的轻松调用吗?
DockWindow.FormDockTemplate m_oDockFormTemplate = new DockWindow.FormDockTemplate(this);
不用吃惊,您只需要在你的窗体初始化的时候(也就是窗体构造函数里添加上述这一行代码)您的程序就可以轻松拥有靠边自动隐藏的功能。
下面我就给各位共享一个我自己经常用的靠边停靠的窗体类,详细见如下代码:
FormDockTemplate.cs文件:
view plaincopy to clipboardprint?
using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Windows.Forms;
namespace DockWindow
{
public class FormDockTemplate : NativeWindow
{
#region 私有字段
/// <summary>
/// 父级窗口实例
/// </summary>
private Form parentForm = null;
/// <summary>
/// 窗口实例的启动信息
/// </summary>
private FormStartInfo m_oFormStartInfo = null;
/// <summary>
/// 当前窗口可以停靠的方式
/// </summary>
private Enu_FormDockStyle m_iDockStyle = Enu_FormDockStyle.None;
/// <summary>
/// 窗口停靠检测的定时器
/// </summary>
private Timer m_tmrHideWindow = null;
/// <summary>
/// 自动感知的矩形区域
/// </summary>
private Rectangle m_rcLeft = Rectangle.Empty;
private Rectangle m_rcTop = Rectangle.Empty;
private Rectangle m_rcRight = Rectangle.Empty;
private Rectangle m_rcBottom = Rectangle.Empty;
/// <summary>
/// 感知区域的容差值,也就是当鼠标移动进入距边缘几个象素时进行自动捕获
/// </summary>
private int m_iSensitiveAreaTolerantPixel = 4;
#endregion
#region 字段属性
/// <summary>
/// 当前窗口的鼠标位置
/// </summary>
Point CurrentMousePos
{
get
{
//获取当前鼠标的屏幕坐标
User32.POINT ptMousePos = new User32.POINT();
User32.GetCursorPos(ref ptMousePos);
return new Point(ptMousePos.X, ptMousePos.Y);
}
}
Rectangle FormTitleRect
{
get { return new Rectangle(parentForm.Location, new Size(parentForm.Width, parentForm.Height - parentForm.ClientRectangle.Height)); }
}
/// <summary>
/// 感应区域的容差设置,距离屏幕边缘多少象素时,开始自动感知
/// </summary>
public int TolerantPixel
{
get { return m_iSensitiveAreaTolerantPixel; }
set { m_iSensitiveAreaTolerantPixel = value; }
}
#endregion
#region 构造函数
/// <summary>
/// 构造函数
/// </summary>
/// <param name="frmParent">父窗口对象</param>
public FormDockTemplate(Form frmParent)
: this(frmParent, 4)
{
}
/// <summary>
/// 构造函数
/// </summary>
/// <param name="frmParent">父窗口对象</param>
/// <param name="iTolerantPixel">自动感知容差象素(当Mouse距离屏幕边缘多少象素时自动感知)</param>
public FormDockTemplate(Form frmParent, int iTolerantPixel)
{
m_iSensitiveAreaTolerantPixel = iTolerantPixel;
parentForm = frmParent;
parentForm.HandleCreated += new EventHandler(parentForm_HandleCreated);
parentForm.HandleDestroyed += new EventHandler(parentForm_HandleDestroyed);
parentForm.Load += new EventHandler(parentForm_Load);
parentForm.Move += new EventHandler(parentForm_Move);
parentForm.Resize += new EventHandler(parentForm_Resize);
//初始化窗体的启动信息:如上次关闭时窗体的大小及位置
InitialFormStartInfo();
}
/// <summary>
/// 初始化窗体启动信息,通过反序列化完成
/// </summary>
void InitialFormStartInfo()
{
try
{
m_oFormStartInfo = new FormStartInfo(parentForm);
FormStartInfo.Deserialize(ref m_oFormStartInfo);
}
catch
{
m_oFormStartInfo.FormLocation = parentForm.Location;
m_oFormStartInfo.FormSize = new Size(parentForm.Width, parentForm.Height);
}
}
#endregion
#region 窗体事件处理
void parentForm_Load(object sender, EventArgs e)
{
//初始化感知区域
InitialDockArea();
//初始化时设置窗口大小及位置
parentForm.Location = m_oFormStartInfo.FormLocation;
parentForm.Size = m_oFormStartInfo.FormSize;
//定时器初始化
m_tmrHideWindow = new Timer();
m_tmrHideWindow.Interval = 100;
m_tmrHideWindow.Enabled = true;
m_tmrHideWindow.Tick += new EventHandler(m_tmrHideWindow_Tick);
}
void parentForm_Resize(object sender, EventArgs e)
{
m_oFormStartInfo.FormSize = parentForm.Size;
}
void parentForm_Move(object sender, EventArgs e)
{
//当左键按下时并且当前鼠标位置处于窗口标题栏区域内,则认为是合法窗口移动,启用自动感知功能
if (Control.MouseButtons == MouseButtons.Left && FormTitleRect.Contains(CurrentMousePos))
{
SetFormDockPos();
}
}
void parentForm_HandleDestroyed(object sender, EventArgs e)
{
//销毁定时器
m_tmrHideWindow.Enabled = false;
m_tmrHideWindow.Stop();
m_tmrHideWindow.Dispose();
//窗口关闭时,保存窗口的大小位置及停靠信息
if (m_iDockStyle == Enu_FormDockStyle.None)
{
m_oFormStartInfo.FormLocation = parentForm.Location;
m_oFormStartInfo.FormSize = parentForm.Size;
}
FormStartInfo.Serialize(m_oFormStartInfo);
//释放本类关联的窗口句柄
ReleaseHandle();
}
void parentForm_HandleCreated(object sender, EventArgs e)
{
AssignHandle(((Form)sender).Handle);
}
void m_tmrHideWindow_Tick(object sender, EventArgs e)
{
if (m_oFormStartInfo.DockStyle != Enu_FormDockStyle.None)
{
//为了提升显示效率,只有处于如下两种情况时,才需要重新显示窗体
//1、窗体可见但鼠标已经移出窗体外
//2、窗体不可见但鼠标已经移入窗体内
bool bNeedReshow = (m_oFormStartInfo.FormVisible && IsMouseOutForm()) ||
(!m_oFormStartInfo.FormVisible && !IsMouseOutForm());
if (bNeedReshow)
m_oFormStartInfo.ShowDockWindow(parentForm.Handle, !IsMouseOutForm());
}
}
#endregion
#region 私有函数
private void InitialDockArea()
{
//获取屏幕可用区域
User32.RECT rectWorkArea = new User32.RECT();
User32.SystemParametersInfo((uint)User32.Enu_SystemParametersInfo_Action.SPI_GETWORKAREA, 0, ref rectWorkArea, 0);
Rectangle rcWorkArea = new Rectangle(rectWorkArea.left, rectWorkArea.top, rectWorkArea.right - rectWorkArea.left, rectWorkArea.bottom - rectWorkArea.top);
Rectangle rcScreenArea = Screen.PrimaryScreen.Bounds;
//容差值,表示鼠标移动到边界若干象素里即可以自动感知停靠位置
m_rcLeft = new Rectangle(rcWorkArea.Left, rcWorkArea.Top, m_iSensitiveAreaTolerantPixel, rcWorkArea.Height);
m_rcTop = new Rectangle(rcWorkArea.Left, rcWorkArea.Top, rcWorkArea.Width, m_iSensitiveAreaTolerantPixel);
m_rcRight = new Rectangle(rcWorkArea.Width - rcWorkArea.Left - m_iSensitiveAreaTolerantPixel, rcWorkArea.Top, m_iSensitiveAreaTolerantPixel, rcWorkArea.Height);
m_rcBottom = new Rectangle(rcScreenArea.Left, rcScreenArea.Bottom - rcScreenArea.Top - m_iSensitiveAreaTolerantPixel, rcScreenArea.Width, m_iSensitiveAreaTolerantPixel);
}
/// <summary>
/// 鼠标按下时未放开的时候,设置窗体停靠时的位置
/// </summary>
void SetFormDockPos()
{
m_iDockStyle = Enu_FormDockStyle.None;
//根据不同的停靠方式来重置窗体位置
if (m_rcLeft.Contains(CurrentMousePos))
{
parentForm.Location = m_rcLeft.Location;
parentForm.Height = m_rcLeft.Height;
m_iDockStyle = Enu_FormDockStyle.Left;
}
else if (m_rcTop.Contains(CurrentMousePos))
{
parentForm.Location = new Point(parentForm.Location.X, m_rcTop.Top);
m_iDockStyle = Enu_FormDockStyle.Top;
}
else if (m_rcRight.Contains(CurrentMousePos))
{
parentForm.Location = new Point(m_rcRight.Right - parentForm.Width, m_rcRight.Top);
parentForm.Height = m_rcRight.Height;
m_iDockStyle = Enu_FormDockStyle.Right;
}
else if (m_rcBottom.Contains(CurrentMousePos))
{
parentForm.Location = new Point(parentForm.Location.X, m_rcBottom.Bottom - parentForm.Height);
m_iDockStyle = Enu_FormDockStyle.Bottom;
}
m_oFormStartInfo.DockStyle = m_iDockStyle;
m_oFormStartInfo.FormLocation = parentForm.Location;
}
/// <summary>
/// 表明当前鼠标位置是否已经移出窗体外
/// </summary>
/// <returns></returns>
private bool IsMouseOutForm()
{
//获取当前鼠标的屏幕坐标
User32.POINT ptMousePos = new User32.POINT();
User32.GetCursorPos(ref ptMousePos);
Point ptClientCursor = new Point(ptMousePos.X, ptMousePos.Y);
User32.RECT rcFormClient = new User32.RECT();
User32.GetWindowRect(this.Handle, ref rcFormClient);
Rectangle rcFormBound = new Rectangle(rcFormClient.left, rcFormClient.top, rcFormClient.right - rcFormClient.left, rcFormClient.bottom - rcFormClient.top);
return !rcFormBound.Contains(ptClientCursor);
}
#endregion
}
}
下面在贴上在此过程中引用的一些API函数:
User32.cs文件:
view plaincopy to clipboardprint?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
namespace DockWindow
{
class User32
{
[StructLayout(LayoutKind.Sequential)]
public struct POINT
{
public int X;
public int Y;
}
[StructLayout(LayoutKind.Sequential)]
public struct RECT
{
public int left;
public int top;
public int right;
public int bottom;
}
public enum Enu_SystemParametersInfo_Action
{
SPI_GETWORKAREA = 0x0030
}
[DllImport("User32.dll")]
public static extern bool GetCursorPos(ref POINT lpPoint);
[DllImport("User32.dll")]
public static extern bool SystemParametersInfo(uint uiAction, uint uiParam, ref RECT lpRect, uint fWinIni);
[DllImport("User32.dll")]
public static extern bool GetWindowRect(IntPtr hwnd, ref RECT lpRect);
}
}
C#如何实现类似QQ那样靠边隐藏的功能
你想过为自己的程序添加靠边隐藏的功能吗?还在为计算窗体的大小及位置而烦恼吗?想这么简单的轻松调用吗?
DockWindow.FormDockTemplate m_oDockFormTemplate = new DockWindow.FormDockTemplate(this);
不用吃惊,您只需要在你的窗体初始化的时候(也就是窗体构造函数里添加上述这一行代码)您的程序就可以轻松拥有靠边自动隐藏的功能。
下面我就给各位共享一个我自己经常用的靠边停靠的窗体类,详细见如下代码:
FormDockTemplate.cs文件:
view plaincopy to clipboardprint?
using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Windows.Forms;
namespace DockWindow
{
public class FormDockTemplate : NativeWindow
{
#region 私有字段
/// <summary>
/// 父级窗口实例
/// </summary>
private Form parentForm = null;
/// <summary>
/// 窗口实例的启动信息
/// </summary>
private FormStartInfo m_oFormStartInfo = null;
/// <summary>
/// 当前窗口可以停靠的方式
/// </summary>
private Enu_FormDockStyle m_iDockStyle = Enu_FormDockStyle.None;
/// <summary>
/// 窗口停靠检测的定时器
/// </summary>
private Timer m_tmrHideWindow = null;
/// <summary>
/// 自动感知的矩形区域
/// </summary>
private Rectangle m_rcLeft = Rectangle.Empty;
private Rectangle m_rcTop = Rectangle.Empty;
private Rectangle m_rcRight = Rectangle.Empty;
private Rectangle m_rcBottom = Rectangle.Empty;
/// <summary>
/// 感知区域的容差值,也就是当鼠标移动进入距边缘几个象素时进行自动捕获
/// </summary>
private int m_iSensitiveAreaTolerantPixel = 4;
#endregion
#region 字段属性
/// <summary>
/// 当前窗口的鼠标位置
/// </summary>
Point CurrentMousePos
{
get
{
//获取当前鼠标的屏幕坐标
User32.POINT ptMousePos = new User32.POINT();
User32.GetCursorPos(ref ptMousePos);
return new Point(ptMousePos.X, ptMousePos.Y);
}
}
Rectangle FormTitleRect
{
get { return new Rectangle(parentForm.Location, new Size(parentForm.Width, parentForm.Height - parentForm.ClientRectangle.Height)); }
}
/// <summary>
/// 感应区域的容差设置,距离屏幕边缘多少象素时,开始自动感知
/// </summary>
public int TolerantPixel
{
get { return m_iSensitiveAreaTolerantPixel; }
set { m_iSensitiveAreaTolerantPixel = value; }
}
#endregion
#region 构造函数
/// <summary>
/// 构造函数
/// </summary>
/// <param name="frmParent">父窗口对象</param>
public FormDockTemplate(Form frmParent)
: this(frmParent, 4)
{
}
/// <summary>
/// 构造函数
/// </summary>
/// <param name="frmParent">父窗口对象</param>
/// <param name="iTolerantPixel">自动感知容差象素(当Mouse距离屏幕边缘多少象素时自动感知)</param>
public FormDockTemplate(Form frmParent, int iTolerantPixel)
{
m_iSensitiveAreaTolerantPixel = iTolerantPixel;
parentForm = frmParent;
parentForm.HandleCreated += new EventHandler(parentForm_HandleCreated);
parentForm.HandleDestroyed += new EventHandler(parentForm_HandleDestroyed);
parentForm.Load += new EventHandler(parentForm_Load);
parentForm.Move += new EventHandler(parentForm_Move);
parentForm.Resize += new EventHandler(parentForm_Resize);
//初始化窗体的启动信息:如上次关闭时窗体的大小及位置
InitialFormStartInfo();
}
/// <summary>
/// 初始化窗体启动信息,通过反序列化完成
/// </summary>
void InitialFormStartInfo()
{
try
{
m_oFormStartInfo = new FormStartInfo(parentForm);
FormStartInfo.Deserialize(ref m_oFormStartInfo);
}
catch
{
m_oFormStartInfo.FormLocation = parentForm.Location;
m_oFormStartInfo.FormSize = new Size(parentForm.Width, parentForm.Height);
}
}
#endregion
#region 窗体事件处理
void parentForm_Load(object sender, EventArgs e)
{
//初始化感知区域
InitialDockArea();
//初始化时设置窗口大小及位置
parentForm.Location = m_oFormStartInfo.FormLocation;
parentForm.Size = m_oFormStartInfo.FormSize;
//定时器初始化
m_tmrHideWindow = new Timer();
m_tmrHideWindow.Interval = 100;
m_tmrHideWindow.Enabled = true;
m_tmrHideWindow.Tick += new EventHandler(m_tmrHideWindow_Tick);
}
void parentForm_Resize(object sender, EventArgs e)
{
m_oFormStartInfo.FormSize = parentForm.Size;
}
void parentForm_Move(object sender, EventArgs e)
{
//当左键按下时并且当前鼠标位置处于窗口标题栏区域内,则认为是合法窗口移动,启用自动感知功能
if (Control.MouseButtons == MouseButtons.Left && FormTitleRect.Contains(CurrentMousePos))
{
SetFormDockPos();
}
}
void parentForm_HandleDestroyed(object sender, EventArgs e)
{
//销毁定时器
m_tmrHideWindow.Enabled = false;
m_tmrHideWindow.Stop();
m_tmrHideWindow.Dispose();
//窗口关闭时,保存窗口的大小位置及停靠信息
if (m_iDockStyle == Enu_FormDockStyle.None)
{
m_oFormStartInfo.FormLocation = parentForm.Location;
m_oFormStartInfo.FormSize = parentForm.Size;
}
FormStartInfo.Serialize(m_oFormStartInfo);
//释放本类关联的窗口句柄
ReleaseHandle();
}
void parentForm_HandleCreated(object sender, EventArgs e)
{
AssignHandle(((Form)sender).Handle);
}
void m_tmrHideWindow_Tick(object sender, EventArgs e)
{
if (m_oFormStartInfo.DockStyle != Enu_FormDockStyle.None)
{
//为了提升显示效率,只有处于如下两种情况时,才需要重新显示窗体
//1、窗体可见但鼠标已经移出窗体外
//2、窗体不可见但鼠标已经移入窗体内
bool bNeedReshow = (m_oFormStartInfo.FormVisible && IsMouseOutForm()) ||
(!m_oFormStartInfo.FormVisible && !IsMouseOutForm());
if (bNeedReshow)
m_oFormStartInfo.ShowDockWindow(parentForm.Handle, !IsMouseOutForm());
}
}
#endregion
#region 私有函数
private void InitialDockArea()
{
//获取屏幕可用区域
User32.RECT rectWorkArea = new User32.RECT();
User32.SystemParametersInfo((uint)User32.Enu_SystemParametersInfo_Action.SPI_GETWORKAREA, 0, ref rectWorkArea, 0);
Rectangle rcWorkArea = new Rectangle(rectWorkArea.left, rectWorkArea.top, rectWorkArea.right - rectWorkArea.left, rectWorkArea.bottom - rectWorkArea.top);
Rectangle rcScreenArea = Screen.PrimaryScreen.Bounds;
//容差值,表示鼠标移动到边界若干象素里即可以自动感知停靠位置
m_rcLeft = new Rectangle(rcWorkArea.Left, rcWorkArea.Top, m_iSensitiveAreaTolerantPixel, rcWorkArea.Height);
m_rcTop = new Rectangle(rcWorkArea.Left, rcWorkArea.Top, rcWorkArea.Width, m_iSensitiveAreaTolerantPixel);
m_rcRight = new Rectangle(rcWorkArea.Width - rcWorkArea.Left - m_iSensitiveAreaTolerantPixel, rcWorkArea.Top, m_iSensitiveAreaTolerantPixel, rcWorkArea.Height);
m_rcBottom = new Rectangle(rcScreenArea.Left, rcScreenArea.Bottom - rcScreenArea.Top - m_iSensitiveAreaTolerantPixel, rcScreenArea.Width, m_iSensitiveAreaTolerantPixel);
}
/// <summary>
/// 鼠标按下时未放开的时候,设置窗体停靠时的位置
/// </summary>
void SetFormDockPos()
{
m_iDockStyle = Enu_FormDockStyle.None;
//根据不同的停靠方式来重置窗体位置
if (m_rcLeft.Contains(CurrentMousePos))
{
parentForm.Location = m_rcLeft.Location;
parentForm.Height = m_rcLeft.Height;
m_iDockStyle = Enu_FormDockStyle.Left;
}
else if (m_rcTop.Contains(CurrentMousePos))
{
parentForm.Location = new Point(parentForm.Location.X, m_rcTop.Top);
m_iDockStyle = Enu_FormDockStyle.Top;
}
else if (m_rcRight.Contains(CurrentMousePos))
{
parentForm.Location = new Point(m_rcRight.Right - parentForm.Width, m_rcRight.Top);
parentForm.Height = m_rcRight.Height;
m_iDockStyle = Enu_FormDockStyle.Right;
}
else if (m_rcBottom.Contains(CurrentMousePos))
{
parentForm.Location = new Point(parentForm.Location.X, m_rcBottom.Bottom - parentForm.Height);
m_iDockStyle = Enu_FormDockStyle.Bottom;
}
m_oFormStartInfo.DockStyle = m_iDockStyle;
m_oFormStartInfo.FormLocation = parentForm.Location;
}
/// <summary>
/// 表明当前鼠标位置是否已经移出窗体外
/// </summary>
/// <returns></returns>
private bool IsMouseOutForm()
{
//获取当前鼠标的屏幕坐标
User32.POINT ptMousePos = new User32.POINT();
User32.GetCursorPos(ref ptMousePos);
Point ptClientCursor = new Point(ptMousePos.X, ptMousePos.Y);
User32.RECT rcFormClient = new User32.RECT();
User32.GetWindowRect(this.Handle, ref rcFormClient);
Rectangle rcFormBound = new Rectangle(rcFormClient.left, rcFormClient.top, rcFormClient.right - rcFormClient.left, rcFormClient.bottom - rcFormClient.top);
return !rcFormBound.Contains(ptClientCursor);
}
#endregion
}
}
view plaincopy to clipboardprint? using System; using System.Collections.Generic; using System.Text; using System.IO; using System.Drawing; using System.Runtime.Serialization; using System.Runtime.Serialization.Formatters.Binary; using System.Windows.Forms; namespace DockWindow { public enum Enu_FormDockStyle { None = 0, Left = 1, Top = 2, Right = 3, Bottom = 4, } [Serializable] public class FormStartInfo { [NonSerialized] private Form m_frmDockWindow = null; private string m_strSerialFileName = string.Empty; private Size m_szFormSize = Size.Empty; private Point m_ptFormLocation = Point.Empty; private Enu_FormDockStyle m_iDockStyle = Enu_FormDockStyle.None; private bool m_bFormVisible = false; /// <summary> /// 构造函数 /// </summary> /// <param name="frmItem">停靠的窗体对象</param> public FormStartInfo(Form frmItem) { try { m_frmDockWindow = frmItem; if (null == frmItem) m_strSerialFileName = "StartInfo.dat"; else m_strSerialFileName = frmItem.Name + frmItem.Text + "_StartInfo.dat"; } catch { } } /// <summary> /// 窗体大小 /// </summary> public Size FormSize { get { return m_szFormSize; } internal set { m_szFormSize = value; } } /// <summary> /// 窗体位置坐标 /// </summary> public Point FormLocation { get { return m_ptFormLocation; } internal set { m_ptFormLocation = value; } } /// <summary> /// 停靠方式 /// </summary> public Enu_FormDockStyle DockStyle { get { return m_iDockStyle; } internal set { m_iDockStyle = value; } } /// <summary> /// 表示窗体是否自动隐藏 /// </summary> public bool FormVisible { get { return m_bFormVisible; } } /// <summary> /// 序列化此类的实例信息 /// </summary> /// <param name="frmStartInfo"></param> public static void Serialize(FormStartInfo frmStartInfo) { using (FileStream fs = new FileStream(frmStartInfo.m_strSerialFileName, FileMode.OpenOrCreate)) { BinaryFormatter bf = new BinaryFormatter(); bf.Serialize(fs, frmStartInfo); } } /// <summary> /// 反序列化此类的实例信息 /// </summary> /// <param name="frmStartInfo"></param> public static void Deserialize(ref FormStartInfo frmStartInfo) { FormStartInfo frmTemp = null; if (null == frmStartInfo) return; using (FileStream fs = new FileStream(frmStartInfo.m_strSerialFileName, FileMode.Open)) { BinaryFormatter bf = new BinaryFormatter(); frmTemp = (FormStartInfo)bf.Deserialize(fs); if (null != frmTemp) frmStartInfo = frmTemp; } } /// <summary> /// 显示或隐藏停靠窗口 /// </summary> public void ShowDockWindow(IntPtr hwnd, bool bVisible) { Point ptLocation = Point.Empty; Size szFormSize = Size.Empty; m_bFormVisible = bVisible; if (m_frmDockWindow == null) m_frmDockWindow = (Form)Control.FromHandle(hwnd); if (m_frmDockWindow == null) return; GetDockWindowClientRect(ref ptLocation, ref szFormSize, bVisible); m_frmDockWindow.TopMost = (m_iDockStyle != Enu_FormDockStyle.None); m_frmDockWindow.Location = ptLocation; m_frmDockWindow.Width = szFormSize.Width; m_frmDockWindow.Height = szFormSize.Height; } /// <summary> /// 根据当前窗体的停靠方式来计算出当前窗体的大小及位置 /// </summary> /// <param name="ptLocation">窗体位置</param> /// <param name="szFormSize">窗体大小</param> /// <param name="bDockWindowVisible">显示还是隐藏</param> private void GetDockWindowClientRect(ref Point ptLocation, ref Size szFormSize, bool bDockWindowVisible) { int iTorrentPixel = 0; int iWindowTitleHeight = SystemInformation.CaptionHeight; //获取屏幕可用区域 User32.RECT rectWorkArea = new User32.RECT(); User32.SystemParametersInfo((uint)User32.Enu_SystemParametersInfo_Action.SPI_GETWORKAREA, 0, ref rectWorkArea, 0); Rectangle rcWorkArea = new Rectangle(rectWorkArea.left, rectWorkArea.top, rectWorkArea.right - rectWorkArea.left, rectWorkArea.bottom - rectWorkArea.top); Rectangle rcScreenArea = Screen.PrimaryScreen.Bounds; if (m_ptFormLocation.X < 0) m_ptFormLocation.X = 0; if (m_ptFormLocation.Y < 0) m_ptFormLocation.Y = 0; if (!bDockWindowVisible) { switch (m_iDockStyle) { case Enu_FormDockStyle.None: ptLocation = m_ptFormLocation; szFormSize = m_szFormSize; break; case Enu_FormDockStyle.Left: ptLocation = new Point(m_ptFormLocation.X - m_szFormSize.Width + SystemInformation.FrameBorderSize.Width + iTorrentPixel, rcWorkArea.Top); szFormSize = new Size(m_szFormSize.Width, rcWorkArea.Height); break; case Enu_FormDockStyle.Top: ptLocation = new Point(m_ptFormLocation.X, rcWorkArea.Top - m_szFormSize.Height +SystemInformation.FrameBorderSize.Width + iTorrentPixel); szFormSize = m_szFormSize; break; case Enu_FormDockStyle.Right: ptLocation = new Point(rcWorkArea.Width - rcWorkArea.Left - SystemInformation.FrameBorderSize.Width - iTorrentPixel, rcWorkArea.Top); szFormSize = new Size(m_szFormSize.Width, rcWorkArea.Height); break; case Enu_FormDockStyle.Bottom: ptLocation = new Point(m_ptFormLocation.X, rcScreenArea.Bottom - rcScreenArea.Top - SystemInformation.FrameBorderSize.Width - iTorrentPixel); szFormSize = m_szFormSize; break; default: ptLocation = m_ptFormLocation; szFormSize = m_szFormSize; break; } } else { ptLocation = m_ptFormLocation; szFormSize = m_szFormSize; } } } } using System; using System.Collections.Generic; using System.Text; using System.IO; using System.Drawing; using System.Runtime.Serialization; using System.Runtime.Serialization.Formatters.Binary; using System.Windows.Forms; namespace DockWindow { public enum Enu_FormDockStyle { None = 0, Left = 1, Top = 2, Right = 3, Bottom = 4, } [Serializable] public class FormStartInfo { [NonSerialized] private Form m_frmDockWindow = null; private string m_strSerialFileName = string.Empty; private Size m_szFormSize = Size.Empty; private Point m_ptFormLocation = Point.Empty; private Enu_FormDockStyle m_iDockStyle = Enu_FormDockStyle.None; private bool m_bFormVisible = false; /// <summary> /// 构造函数 /// </summary> /// <param name="frmItem">停靠的窗体对象</param> public FormStartInfo(Form frmItem) { try { m_frmDockWindow = frmItem; if (null == frmItem) m_strSerialFileName = "StartInfo.dat"; else m_strSerialFileName = frmItem.Name + frmItem.Text + "_StartInfo.dat"; } catch { } } /// <summary> /// 窗体大小 /// </summary> public Size FormSize { get { return m_szFormSize; } internal set { m_szFormSize = value; } } /// <summary> /// 窗体位置坐标 /// </summary> public Point FormLocation { get { return m_ptFormLocation; } internal set { m_ptFormLocation = value; } } /// <summary> /// 停靠方式 /// </summary> public Enu_FormDockStyle DockStyle { get { return m_iDockStyle; } internal set { m_iDockStyle = value; } } /// <summary> /// 表示窗体是否自动隐藏 /// </summary> public bool FormVisible { get { return m_bFormVisible; } } /// <summary> /// 序列化此类的实例信息 /// </summary> /// <param name="frmStartInfo"></param> public static void Serialize(FormStartInfo frmStartInfo) { using (FileStream fs = new FileStream(frmStartInfo.m_strSerialFileName, FileMode.OpenOrCreate)) { BinaryFormatter bf = new BinaryFormatter(); bf.Serialize(fs, frmStartInfo); } } /// <summary> /// 反序列化此类的实例信息 /// </summary> /// <param name="frmStartInfo"></param> public static void Deserialize(ref FormStartInfo frmStartInfo) { FormStartInfo frmTemp = null; if (null == frmStartInfo) return; using (FileStream fs = new FileStream(frmStartInfo.m_strSerialFileName, FileMode.Open)) { BinaryFormatter bf = new BinaryFormatter(); frmTemp = (FormStartInfo)bf.Deserialize(fs); if (null != frmTemp) frmStartInfo = frmTemp; } } /// <summary> /// 显示或隐藏停靠窗口 /// </summary> public void ShowDockWindow(IntPtr hwnd, bool bVisible) { Point ptLocation = Point.Empty; Size szFormSize = Size.Empty; m_bFormVisible = bVisible; if (m_frmDockWindow == null) m_frmDockWindow = (Form)Control.FromHandle(hwnd); if (m_frmDockWindow == null) return; GetDockWindowClientRect(ref ptLocation, ref szFormSize, bVisible); m_frmDockWindow.TopMost = (m_iDockStyle != Enu_FormDockStyle.None); m_frmDockWindow.Location = ptLocation; m_frmDockWindow.Width = szFormSize.Width; m_frmDockWindow.Height = szFormSize.Height; } /// <summary> /// 根据当前窗体的停靠方式来计算出当前窗体的大小及位置 /// </summary> /// <param name="ptLocation">窗体位置</param> /// <param name="szFormSize">窗体大小</param> /// <param name="bDockWindowVisible">显示还是隐藏</param> private void GetDockWindowClientRect(ref Point ptLocation, ref Size szFormSize, bool bDockWindowVisible) { int iTorrentPixel = 0; int iWindowTitleHeight = SystemInformation.CaptionHeight; //获取屏幕可用区域 User32.RECT rectWorkArea = new User32.RECT(); User32.SystemParametersInfo((uint)User32.Enu_SystemParametersInfo_Action.SPI_GETWORKAREA, 0, ref rectWorkArea, 0); Rectangle rcWorkArea = new Rectangle(rectWorkArea.left, rectWorkArea.top, rectWorkArea.right - rectWorkArea.left, rectWorkArea.bottom - rectWorkArea.top); Rectangle rcScreenArea = Screen.PrimaryScreen.Bounds; if (m_ptFormLocation.X < 0) m_ptFormLocation.X = 0; if (m_ptFormLocation.Y < 0) m_ptFormLocation.Y = 0; if (!bDockWindowVisible) { switch (m_iDockStyle) { case Enu_FormDockStyle.None: ptLocation = m_ptFormLocation; szFormSize = m_szFormSize; break; case Enu_FormDockStyle.Left: ptLocation = new Point(m_ptFormLocation.X - m_szFormSize.Width + SystemInformation.FrameBorderSize.Width + iTorrentPixel, rcWorkArea.Top); szFormSize = new Size(m_szFormSize.Width, rcWorkArea.Height); break; case Enu_FormDockStyle.Top: ptLocation = new Point(m_ptFormLocation.X, rcWorkArea.Top - m_szFormSize.Height +SystemInformation.FrameBorderSize.Width + iTorrentPixel); szFormSize = m_szFormSize; break; case Enu_FormDockStyle.Right: ptLocation = new Point(rcWorkArea.Width - rcWorkArea.Left - SystemInformation.FrameBorderSize.Width - iTorrentPixel, rcWorkArea.Top); szFormSize = new Size(m_szFormSize.Width, rcWorkArea.Height); break; case Enu_FormDockStyle.Bottom: ptLocation = new Point(m_ptFormLocation.X, rcScreenArea.Bottom - rcScreenArea.Top - SystemInformation.FrameBorderSize.Width - iTorrentPixel); szFormSize = m_szFormSize; break; default: ptLocation = m_ptFormLocation; szFormSize = m_szFormSize; break; } } else { ptLocation = m_ptFormLocation; szFormSize = m_szFormSize; } } } }
下面在贴上在此过程中引用的一些API函数:
User32.cs文件:
view plaincopy to clipboardprint?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
namespace DockWindow
{
class User32
{
[StructLayout(LayoutKind.Sequential)]
public struct POINT
{
public int X;
public int Y;
}
[StructLayout(LayoutKind.Sequential)]
public struct RECT
{
public int left;
public int top;
public int right;
public int bottom;
}
public enum Enu_SystemParametersInfo_Action
{
SPI_GETWORKAREA = 0x0030
}
[DllImport("User32.dll")]
public static extern bool GetCursorPos(ref POINT lpPoint);
[DllImport("User32.dll")]
public static extern bool SystemParametersInfo(uint uiAction, uint uiParam, ref RECT lpRect, uint fWinIni);
[DllImport("User32.dll")]
public static extern bool GetWindowRect(IntPtr hwnd, ref RECT lpRect);
}
}
相关文章推荐
- C#如何实现类似QQ那样靠边隐藏的功能
- [VB.NET]请问类似QQ窗体靠边自动隐藏的效果如何实现?????
- richTextBox如何实现输入指定的字符显示一个表情图标?类似QQ那样?
- winform实现任务栏隐藏、通知栏图标及右键、类似QQ隐藏窗体等功能
- C#实现QQ靠边隐藏的功能
- C#实现QQ靠边隐藏的功能
- WPF程序也可以很轻松的实现类似QQ那样最小化到任务栏的功能。
- MFC 实现类似QQ自动靠边功能
- JS实现延迟隐藏功能的方法(类似QQ头像鼠标放上展示信息)
- Flex中如何实现类似像QQ登录框中那种“记住密码”、“自动登录”功能,还有如何实现文本框中记录最后一次输入的值?
- QQ揭秘:如何实现窗体靠边隐藏?【低调赠送:QQ高仿版GG 4.2 最新源码】
- C# 实现QQ那样靠边停靠自动隐藏
- brew中如何实现strtoint类似的功能
- Crystal Report 水晶报表如何实现类似表格单元格合并的功能
- C#类似QQ窗体抖动功能的实现
- Winform窗体实现类似停靠在屏幕边缘时自动隐藏的功能
- 类似qq登陆 记住密码功能的实现
- 如何用android实现类似windows的画板功能
- java web中实现同一帐号同一时间只能一个地点登陆(类似QQ登录的功能)
- 在.NET下如何用WebService实现身份认证,及如何跟踪用户的访问,如类似Possport的功能,不会还是用Session吧?