当前位置: 代码网 > it编程>编程语言>C# > C#实现仿QQ抽屉式窗体的设计方法

C#实现仿QQ抽屉式窗体的设计方法

2024年05月26日 C# 我要评论
前言qq软件对于绝大多数的人来说再熟悉不过了,它以使用方便、界面美观及功能完善而著称。主要通过使用api函数windowfrompoint和getparent实现仿qq的抽屉式窗体:1.windowf

前言

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抽屉式窗体的资料请关注代码网其它相关文章!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com