C#仿QQ抽屉式窗体的设计方法:创建特殊窗体

目录

1.WindowFromPoint函数

2.GetParent函数

3.实例

(1) 图片集合编辑器

(2)Form1.Designer.cs

(3)Form1.cs

4.生成效果 


        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);}#endregionprivate 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);#endregionpublic Form1(){InitializeComponent();}#region 运行本程序需要声明的变量private IntPtr CurrentHandle;   //记录鼠标当前状态下控件的句柄private int WindowFlag;         //标记是否对窗体进行拉伸操作 private int intOriHeight;#endregionprivate 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;                  //返回当前的句柄}#endregionprivate 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.生成效果 

        生成的窗体默认停留在窗体顶部,并且隐藏的。鼠标滑动到其停住的区域该窗体就会弹出。此时可以拖动窗体到左、右、下部,松开鼠标后窗体会停驻在左、右、下部。操作窗体上的最大化、关闭按钮,可以让窗体最大化和关闭。还可以操作窗体的边框,向左、下、右拖动放大缩小窗体;鼠标点击任务栏的图标可以查找窗体当前的停靠位置。

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/2980744.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

MySQL创建数据库与表

要求&#xff1a; 1.在本机安装数据库 2.创建一个数据库db_classes 3.创建一行表db_hero 4.将四大名著中的常见人物插入这个英雄表 目录 要求&#xff1a; 过程&#xff1a; 结果&#xff1a; 命令总结&#xff1a; 过程&#xff1a; 1.安装数据库 http://t.csdnimg…

【软件工程】【第一章概述】d1

关键字&#xff1a; 什么是软件、软件危机、软件工程定义、软件生命周期、软件过程、瀑布模型

设计模式学习笔记 - 开源实战四(中):剖析Spring框架中用来支持扩展的设计模式

概述 上篇文章&#xff0c;学习了 Spring 框架背后蕴含的设计思想&#xff0c;比如约定优于配置、低侵入松耦合、模块化轻量级等等。这些设计思想可以借鉴到其他框架开发中&#xff0c;在大的设计层面提高框架的代码质量。 除了上篇文章降到的设计思想&#xff0c;实际上&…

《R语言与农业数据统计分析及建模》学习——ggplot2绘图基础

一、农业科研数据可视化常用图形及用途 1、数据可视化的重要性 通过可视化&#xff0c;我们可以更直观地理解和分析数据的特征和趋势。 2、常用图表类型及其概述 散点图&#xff1a;用于展示两个变量之间的关系&#xff0c;可用于观察数据的分布、趋势和异常值。 折线图&…

[SWPUCTF 2022 新生赛]1z_unserialize

function __destruct()这是类的析构函数。在 PHP 中&#xff0c;析构函数会在对象被销毁时自动调用。 $a($this->lly): 将 $this->lly 的值作为参数传递给 $a 所代表的函数。 由题目可知&#xff0c;实现nss反序列化的同时&#xff0c;会触发__destruct()的魔术方法将l…

【数据结构(邓俊辉)学习笔记】向量03——常规向量

文章目录 0.概述1.元素访问2.置乱器3.判等器与比较器4.无序查找4.1 判等器4.2 顺序查找4.3 实现4.4 复杂度 5. 插入5.1 算法实现5.2 复杂度分析 6. 删除6.1 区间删除6.2 单元删除6.3 复杂度 7. 唯一化7.1 实现7.2 正确性7.3 复杂度 8. 遍历8.1 实现8.2 复杂度 9. 总结 0.概述 …

【树莓派学习】开发环境配置

【树莓派学习】开发环境配置 ​ Raspberry Pi OS作为基于Linux的系统&#xff0c;其默认网络配置在国内的网络环境下容易出现访问慢甚至无法连接等问题&#xff0c;不便于我们的学习&#xff0c;同时&#xff0c;树莓派上C/C的使用需要单独安装WiringPi。本文主要介绍如何更改…

探索开源的容器引擎--------------Docker容器操作

目录 一、Docker 容器操作 1.1容器创建 1.2查看容器的运行状态 1.3启动容器 1.4创建并启动容器 1.4.1当利用 docker run 来创建容器时&#xff0c; Docker 在后台的标准运行过程是&#xff1a; 1.4.2在后台持续运行 docker run 创建的容器 1.4.3创建容器并持续运行容器…

PYTHON用[邻接列表]及[邻接矩阵]来存储无向图

# 图可以根据边的性质进行分类&#xff1a;# 有向图&#xff08;Directed Graph&#xff09;&#xff1a;在有向图中&#xff0c;边是有方向性的&#xff0c;从一个节点指向另一个节点。这意味着从节点 A 到节点 B 的边与从节点 B 到节点 A 的边可以是不同的&#xff0c;或者根…

parallels desktop19出来了吗?2024最新版本有哪些新功能

Parallels Desktop 19已经发布。以下是关于Parallels Desktop 19的相关信息&#xff1a; 发布时间&#xff1a;Parallels Desktop 19是在近期发布的一款虚拟机软件&#xff0c;具体发布时间为2023年下半年。 功能特点&#xff1a; 针对搭载苹果芯片的Mac进行了优化&#xff0c…

微信小程序webview和小程序通讯

1.背景介绍 1.1需要在小程序嵌入vr页面&#xff0c;同时在vr页面添加操作按钮与小程序进行通信交互 1.2 开发工具&#xff1a;uniapp开发小程序 1.3原型图 功能&#xff1a;.点击体验官带看跳转小程序的体验官带看页面 功能&#xff1a;点击立即咨询唤起小程序弹窗打电话 2.…

Python 基于 OpenCV 视觉图像处理实战 之 OpenCV 简单人脸检测/识别实战案例 之五 简单进行车牌检测和识别

Python 基于 OpenCV 视觉图像处理实战 之 OpenCV 简单人脸检测/识别实战案例 之五 简单进行车牌检测和识别 目录 Python 基于 OpenCV 视觉图像处理实战 之 OpenCV 简单人脸检测/识别实战案例 之五 简单进行车牌检测和识别 一、简单介绍 二、简单进行车牌检测和识别实现原理 …

Jmeter之Beanshell详解

一、 Beanshell概念 Beanshell: BeanShell是一种完全符合Java语法规范的脚本语言,并且又拥有自己的一些语法和方法;BeanShell是一种松散类型的脚本语言(这点和JS类似);BeanShell是用Java写成的,一个小型的、免费的、可以下载的、嵌入式的Java源代码解释器,具有对象脚本语言特性…

[Algorithm][前缀和][模板 一维前缀和][模板 二维前缀和][寻找数组中心下标][除自身以外数组的乘积] + 前缀和原理 + 前缀和模板

目录 0.原理讲解1.[模板]一维前缀和1.题目链接2.模板代码实现 2.[模板]二维前缀和1.题目链接2.算法原理讲解3.模板代码实现 3.寻找数组的中心下标1.题目链接2.算法原理详解3.代码实现 4.除自身以外数组的乘积1.题目链接2.算法原理详解3.代码实现 0.原理讲解 前缀和&#xff1a;…

Esp8266 - USB开关分享(开源)

文章目录 简介推广自己gitee项目地址:嘉立创项目地址&#xff1a;联系我们 功能演示视频原理图嘉立创PCB开源地址原理图PCB预览 固件烧录代码编译烧录1. 软件和驱动安装2. 代码编译1. 安装所需要的依赖库文件2. 下载源代码3. 烧录代码 使用说明1. 设备配网2. 打开设备操作页面3…

【深度学习】YOLOv5,烟雾和火焰,目标检测,防火检测,森林火焰检测

文章目录 数据收集和数据标注查看标注好的数据的脚本下载yolov5创建 dataset.yaml训练参数开始训练yolov5n训练训练后的权重下载gradio部署 数据收集和数据标注 搜集数据集2w张。 pip install labelme labelme 然后标注矩形框和类别。 下载数据请看这里&#xff1a; https:…

【SpringCloud】Consul-服务注册中心及配置中心快速入门

【SpringCloud】Consul-服务注册中心及配置中心快速入门 文章目录 【SpringCloud】Consul-服务注册中心及配置中心快速入门1. 下载安装及启动2. 服务注册2.1 引入依赖2.2 yml配置2.3 启动类配置2.4 测试 3. 服务配置3.1 引入依赖3.2 yml配置3.3 创建配置文件3.4 动态刷新配置3.…

2024深圳杯(东三省)数学建模挑战赛D题:音板的振动模态分析与参数识别思路代码成品论文分析

​ 更新完整代码和成品完整论文 《2024深圳杯&东三省数学建模思路代码成品论文》↓↓↓ https://www.yuque.com/u42168770/qv6z0d/zx70edxvbv7rheu7?singleDoc# 问题重述 深圳杯&#xff08;东三省&#xff09;数学建模挑战赛2024D题&#xff1a;音板的振动模态分析与…

Docker常用命令(镜像、容器、网络)

一、镜像 1.1 存出镜像 将镜像保存成为本地文件 格式&#xff1a;docker save -o 存储文件名 存储的镜像docker save -o nginx nginx:latest 1.2 载入镜像 将镜像文件导入到镜像库中 格式&#xff1a;docker load < 存出的文件或docker load -i 存出的文件…

WordPress自动采集发布AutoPostPro汉化版插件

WP-AutoPostPro 是一款极为出色的WordPress自动采集发布插件&#xff0c;其显著优势在于能够从任何网站抓取内容并自动将其发布到你的WordPress网站上。它实现了对任何网页内容的自动采集和发布&#xff0c;整个采集过程完全自动化&#xff0c;无需手动操作。 项 目 地 址 &…