C#实现仿QQ抽屉式窗体的设计方法
作者:wenchm
QQ软件对于绝大多数的人来说再熟悉不过了,它以使用方便、界面美观及功能完善而著称,本文给大家介绍了C#实现仿QQ抽屉式窗体的设计方法,主要通过使用API函数WindowFromPoint和GetParent实现仿QQ的抽屉式窗体,需要的朋友可以参考下
前言
QQ软件对于绝大多数的人来说再熟悉不过了,它以使用方便、界面美观及功能完善而著称。
主要通过使用API函数WindowFromPoint和GetParent实现仿QQ的抽屉式窗体:
1.WindowFromPoint函数
该函数用于获得包含指定点坐标的窗口的句柄。语法格式如下:
[DlIImport("user32.dll")] //需要引入user32.dll动态链接库 public static extern int WindowFromPoint(int xPoint,int yPoint) //获得包含指定点坐标的窗口的句柄 参数说明 xPoint:被检测点的横坐标。 yPoint:被检测点的纵坐标。 目返回值:为包含指定点坐标的窗口的句柄,若包含指定点坐标的窗口不存在,则返回值为null;若该坐标对应的点在静态文本控件之上,则返回值是在该静态文本控件下面的窗口的句柄。
2.GetParent函数
该函数用于获取指定句柄的父级。语法格式如下:
[DllImport("user32.dll",ExactSpelling =true,CharSet =CharSet.Auto)]//需要引入user32.dll动态链接库 public static extern IntPtr GetParent(IntPtr hWnd); //获取指定句柄的父级 参数说明 hWnd:指定窗口的句柄。 返回值:若果函数执行成功,则返回指定窗口句柄的父级;若函数执行失败,则返回值为null。
3.实例
本实例仿照QQ软件界面的基本操作设计了一个抽屉式的窗体:在该窗体中单击任意按钮,程序将显示被单击按钮对应的列表,同时隐藏其他两个按钮对应的列表;用鼠标拖曳该窗体到屏幕的任意边缘,窗体会自动隐藏到该边缘内,当鼠标划过隐藏窗体的边缘时,窗体会显示出来;当鼠标离开窗体时,窗体再次被隐藏。
(1)图片集合编辑器
本实例没有使用资源管理器加载图片。本实例设计了一个imageList1控件,项目使用的图片都要设计到imageList1的图像集合编辑器中。
(2)Form1.Designer.cs
namespace _190 { partial class Form1 { /// <summary> /// Required designer variable. /// </summary> private System.ComponentModel.IContainer components = null; /// <summary> /// Clean up any resources being used. /// </summary> /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> protected override void Dispose(bool disposing) { if (disposing && (components != null)) { components.Dispose(); } base.Dispose(disposing); } #region Windows Form Designer generated code /// <summary> /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// </summary> private void InitializeComponent() { components = new System.ComponentModel.Container(); System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Form1)); button1 = new Button(); button2 = new Button(); button3 = new Button(); listView1 = new ListView(); imageList1 = new ImageList(components); JudgeWinMouPosition = new System.Windows.Forms.Timer(components); HideWindow = new System.Windows.Forms.Timer(components); SuspendLayout(); // // button1 // button1.Dock = DockStyle.Top; button1.Location = new Point(0, 0); button1.Name = "button1"; button1.Size = new Size(153, 23); button1.TabIndex = 0; button1.Text = "我的好友"; button1.UseVisualStyleBackColor = true; button1.Click += Button1_Click; // // button2 // button2.Dock = DockStyle.Bottom; button2.Location = new Point(0, 262); button2.Name = "button2"; button2.Size = new Size(153, 23); button2.TabIndex = 1; button2.Text = "黑名单"; button2.UseVisualStyleBackColor = true; button2.Click += Button2_Click; // // button3 // button3.Dock = DockStyle.Bottom; button3.Location = new Point(0, 239); button3.Name = "button3"; button3.Size = new Size(153, 23); button3.TabIndex = 2; button3.Text = "陌生人"; button3.UseVisualStyleBackColor = true; button3.Click += Button3_Click; // // listView1 // listView1.Dock = DockStyle.Fill; listView1.Location = new Point(0, 23); listView1.Name = "listView1"; listView1.Size = new Size(153, 216); listView1.TabIndex = 3; listView1.UseCompatibleStateImageBehavior = false; // // imageList1 // imageList1.ColorDepth = ColorDepth.Depth32Bit; imageList1.ImageStream = (ImageListStreamer)resources.GetObject("imageList1.ImageStream"); imageList1.TransparentColor = Color.Transparent; imageList1.Images.SetKeyName(0, "01.jpg"); imageList1.Images.SetKeyName(1, "02.png"); imageList1.Images.SetKeyName(2, "03.jpg"); imageList1.Images.SetKeyName(3, "04.jpg"); imageList1.Images.SetKeyName(4, "05.png"); imageList1.Images.SetKeyName(5, "06.jpg"); // // JudgeWinMouPosition // JudgeWinMouPosition.Tick += JudgeWinMouPosition_Tick; // // HideWindow // HideWindow.Tick += HideWindow_Tick; // // Form1 // AutoScaleDimensions = new SizeF(7F, 17F); AutoScaleMode = AutoScaleMode.Font; BackgroundImageLayout = ImageLayout.Stretch; ClientSize = new Size(153, 285); Controls.Add(listView1); Controls.Add(button3); Controls.Add(button2); Controls.Add(button1); Name = "Form1"; StartPosition = FormStartPosition.CenterScreen; Text = "仿QQ抽屉式窗体"; Load += Form1_Load; LocationChanged += Form1_LocationChanged; Resize += Form1_Resize; ResumeLayout(false); } #endregion private Button button1; private Button button2; private Button button3; private ListView listView1; private ImageList imageList1; private System.Windows.Forms.Timer JudgeWinMouPosition; private System.Windows.Forms.Timer HideWindow; } }
(3)Form1.cs
// 仿QQ抽屉式窗体 using System.Runtime.InteropServices; namespace _190 { public partial class Form1 : Form { #region 声明本程序中用到的API函数 //获取当前鼠标下可视化控件的函数 [LibraryImport("user32.dll")] public static partial int WindowFromPoint(int xPoint, int yPoint); //获取指定句柄的父级函数 [LibraryImport("user32.dll")] public static partial IntPtr GetParent(IntPtr hWnd); //获取屏幕的大小 [LibraryImport("user32.dll", EntryPoint = "GetSystemMetrics")] private static partial int GetSystemMetrics(int mVal); #endregion public Form1() { InitializeComponent(); } #region 运行本程序需要声明的变量 private IntPtr CurrentHandle; //记录鼠标当前状态下控件的句柄 private int WindowFlag; //标记是否对窗体进行拉伸操作 private int intOriHeight; #endregion private void Form1_Load(object sender, EventArgs e) { intOriHeight = Height; DesktopLocation = new Point(794, 0); //为当前窗体定位 JudgeWinMouPosition.Enabled = true; //计时器JudgeWinMouPosition开始工作 listView1.Clear(); listView1.LargeImageList = imageList1; listView1.Items.Add("小猪", "小猪", 0); listView1.Items.Add("小狗", "小狗", 1); listView1.Items.Add("娇娇", "娇娇", 2); } public int OriHeight { get { return intOriHeight; } } /// <summary> /// 我的好友 /// </summary> private void Button1_Click(object sender, EventArgs e) { listView1.Dock = DockStyle.None; button1.Dock = DockStyle.Top; button2.Dock = DockStyle.Bottom; button3.Dock = DockStyle.Bottom; button3.SendToBack(); listView1.BringToFront(); listView1.Dock = DockStyle.Bottom; listView1.Clear(); listView1.Items.Add("小猪", "小猪", 0); listView1.Items.Add("小狗", "小狗", 1); listView1.Items.Add("娇娇", "娇娇", 2); } /// <summary> /// 陌生人 /// </summary> private void Button3_Click(object sender, EventArgs e) { listView1.Dock = DockStyle.None; button2.Dock = DockStyle.Top; button1.Dock = DockStyle.Top; button1.SendToBack(); button3.Dock = DockStyle.Bottom; listView1.Dock = DockStyle.Bottom; listView1.Clear(); listView1.Items.Add("北风", "北风", 3); } /// <summary> /// 黑名单 /// </summary> private void Button2_Click(object sender, EventArgs e) { listView1.Dock = DockStyle.None; button3.Dock = DockStyle.Top; //设置button3按钮绑定到窗体的上边缘 button2.Dock = DockStyle.Top; //设置button2按钮绑定到窗体的上边缘 button2.SendToBack(); //保证button2在button3的后面 button1.Dock = DockStyle.Top; button1.SendToBack(); //保证button1在button2的后面 listView1.Dock = DockStyle.Bottom; listView1.Clear(); listView1.Items.Add("冰雨", "冰雨", 5); } /// <summary> /// 判断当前窗体处于哪个状态 /// </summary> private void HideWindow_Tick(object sender, EventArgs e) { switch (Convert.ToInt32(WindowFlag.ToString())) { case 1: //当窗体处于最上端时 if (Top < 3) //当窗体与容器工作区的上边缘的距离小于5px时 Top = -(Height - 2); //设定当前窗体距容器工作区上边缘的值 break; case 2: //当窗体处于最左端时 if (Left < 3)//当窗体与容器工作区的左边缘的距离小于5px时 Left = -(Width - 2); //设定当前窗体据容器工作区左边缘的值 break; case 3: //当窗体处于最右端时 if ((Left + Width) > (GetSystemMetrics(0) - 3)) //当窗体与容器工作区的右边缘的距离小于5px时 Left = GetSystemMetrics(0) - 2; //设定当前窗体距容器工作区左边缘的值 break; case 4: //当窗体处于最低端时 if (Bottom > Screen.AllScreens[0].Bounds.Height - 3)//当窗体与容器工作区的下边缘的距离小于5px时 Top = Screen.AllScreens[0].Bounds.Height - 5; //设定当前窗体距容器工作区上边缘之间的距离 break; } } private void JudgeWinMouPosition_Tick(object sender, EventArgs e) { if (Top < 3) //当本窗体距屏幕的上边距小于3px时 { if (Handle == MouseNowPosition(Cursor.Position.X, Cursor.Position.Y))//当鼠标在该窗体上时 { WindowFlag = 1; //设定当前的窗体状态 HideWindow.Enabled = false; //设定计时器HideWindow为不可用状态 Top = 0; //设定窗体上边缘与容器工作区上边缘之间的距离 } else //当鼠标没在窗体上时 { WindowFlag = 1; //设定当前的窗体状态 HideWindow.Enabled = true; //启动计时器HideWindow } } //当本窗体距屏幕的上边距大于3px时 else { //当本窗体在屏幕的最左端或者最右端、最下端时 if (Left < 3 || (Left + Width) > (GetSystemMetrics(0) - 3) || (Top + Height) > (Screen.AllScreens[0].Bounds.Height - 3)) { if (Left < 3) //当窗体处于屏幕左侧时 { if (Handle == MouseNowPosition(Cursor.Position.X, Cursor.Position.Y)) //当鼠标在该窗体上时 { Height = Screen.AllScreens[0].Bounds.Height - 40; Top = 3; WindowFlag = 2; //设定当前的窗体状态 HideWindow.Enabled = false;//设定计时器HideWindow为不可用状态 Left = 0; //设定窗体的左边缘与容器工作区的左边缘之间的距离 } else //当鼠标没在该窗体上时 { WindowFlag = 2; //设定当前的窗体状态 HideWindow.Enabled = true;//设定计时器HideWindow为可用状态 } } if ((Left + Width) > (GetSystemMetrics(0) - 3)) //当窗体处于屏幕的最右侧时 { if (Handle == MouseNowPosition(Cursor.Position.X, Cursor.Position.Y))//当鼠标处于窗体上时 { Height = Screen.AllScreens[0].Bounds.Height - 40; Top = 3; WindowFlag = 3; //设定当前的窗体状态 HideWindow.Enabled = false; //设定计时器HideWindow为不可用状态 Left = GetSystemMetrics(0) - Width; //设定该窗体与容器工作区左边缘之间的距离 } else //当鼠标离开窗体时 { WindowFlag = 3; //设定当前的窗体状态 HideWindow.Enabled = true; //设定计时器HideWindow为可用状态 } } //当窗体距屏幕最下端的距离小于3px时 if ((Top + Height) > (Screen.AllScreens[0].Bounds.Height - 3)) { if (Handle == MouseNowPosition(Cursor.Position.X, Cursor.Position.Y)) //当鼠标在该窗体上时 { WindowFlag = 4; //设定当前的窗体状态 HideWindow.Enabled = false;//设定计时器HideWindow为不可用状态 Top = Screen.AllScreens[0].Bounds.Height - Height;//设定该窗体与容器工作区上边缘之间的距离 } else { if ((Left > Width + 3) && (GetSystemMetrics(0) - Right) > 3) { WindowFlag = 4; //设定当前的窗体状态 HideWindow.Enabled = true; //设定计时器HideWindow为可用状态 } } } } } } #region 获取鼠标当前状态下控件的句柄 /// <summary> /// 获取鼠标当前状态下控件的句柄 /// </summary> /// <param name="x">当前鼠标的X坐标</param> /// <param name="y">当前鼠标的Y坐标</param> /// <returns></returns> public IntPtr MouseNowPosition(int x, int y) { IntPtr OriginalHandle;//声明保存原始句柄的变量 OriginalHandle = WindowFromPoint(x, y);//获取包含鼠标原始位置的窗口的句柄 CurrentHandle = OriginalHandle; //设置当前句柄 while (OriginalHandle != 0) //循环判断鼠标是否移动 { CurrentHandle = OriginalHandle; //记录当前的句柄 OriginalHandle = GetParent(CurrentHandle);//更新原始句柄 } return CurrentHandle; //返回当前的句柄 } #endregion private void Form1_LocationChanged(object sender, EventArgs e) { if (Left > 3 && Right < (GetSystemMetrics(0) - 3)) { if (Height == Screen.AllScreens[0].Bounds.Height - 40) { Height = OriHeight; } } } private void Form1_Resize(object sender, EventArgs e) { listView1.Height = Height - button3.Height * 3 - 30; } } }
4.生成效果
生成的窗体默认停留在窗体顶部,并且隐藏的。鼠标滑动到其停住的区域该窗体就会弹出。此时可以拖动窗体到左、右、下部,松开鼠标后窗体会停驻在左、右、下部。操作窗体上的最大化、关闭按钮,可以让窗体最大化和关闭。还可以操作窗体的边框,向左、下、右拖动放大缩小窗体;鼠标点击任务栏的图标可以查找窗体当前的停靠位置。
以上就是C#实现仿QQ抽屉式窗体的设计方法的详细内容,更多关于C#仿QQ抽屉式窗体的资料请关注脚本之家其它相关文章!