一个类似QQ窗体自动上卷的程序


QQ窗体上滑的效果,主要通过处理鼠标消息实现的。

有三种消息需要处理:

左键弹起:判断窗体的上边,是否在屏幕上边线以上,是则调整窗体的Y坐标为0.

鼠标移出窗体:判断窗体左上角Y坐标是否为0

鼠标进入窗体:判断窗体是否已经上滑,如果已经上滑,需要还原窗体。

移动窗体的时候,计算出Y轴上需要移动的距离,然后分成10次移动,每次间隔50ms,以达到连续移动的效果。

代码如下: 

类QQ窗体
using System;
using System.Drawing;
using System.Windows.Forms;
using System.Runtime.InteropServices;

namespace FormHideLikeQQ
{
    public partial class QQForm : Form
    {
        public QQForm()
        {
            InitializeComponent();
        }

        /// <summary>
        /// 鼠标弹起时,如果上边缘超过上顶端线。将其移动到顶端线上
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void QQForm_MouseUp()
        {
            if (this.Location.Y < 0)
            {
                MoveForm(new Point(this.Location.X, 0));
            }
        }

        /// <summary>
        /// 如果上边缘在上顶端线上,鼠标离开则上滑窗体
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void QQForm_MouseLeave()
        {
            if (this.Location.Y == 0)
            {
                MoveForm(new Point(this.Location.X, 5 - this.Size.Height));
            }
        }
     
        /// <summary>
        /// 窗体移动函数,有缓慢移动特效。
        /// </summary>
        /// <param name="newPos"></param>
        private void MoveForm(Point newPos)
        {
            //500ms内移动完
            Point currentPos = this.Location;
            double step = (newPos.Y - this.Location.Y) / 10.0;
            for (int i = 1; i <= 10; i++)
            {
                this.Location = new Point(this.Location.X, (int)(currentPos.Y + step * i));
                System.Threading.Thread.Sleep(50);
            }
        }

        /// <summary>
        /// 鼠标进入窗体的响应事件
        /// </summary>
        private void QQForm_MouseEnter()
        {
            if (this.Location.Y == (5 - this.Size.Height))
            {
                MoveForm(new Point(this.Location.X, 0));
            }
        }

        [DllImport("user32")]
        public static extern bool TrackMouseEvent(TRACKMOUSEEVENT lpEventTrack);

        [StructLayout( LayoutKind.Sequential,CharSet=CharSet.Ansi)]
        public struct TRACKMOUSEEVENT {
        public long cbSize;
        public long dwFlags;
        public long hwndTrack;
        public long dwHoverTime;
        }

        private const int WM_MOUSEHOVER = 0x2a1;
        private const int WM_MOUSELEAVE = 0x2a3;
        private const int WM_MOUSEMOVE = 0x200;
        private const int TME_HOVER = 0x1;
        private const int WM_LBUTTONUP = 0x202;
        private const int WM_LBUTTONDOWN = 0x201;
        private const int VK_LBUTTON = 0x01; 

        /// <summary>
        /// 消息处理函数
        /// </summary>
        /// <param name="m"></param>
        protected override void WndProc(ref Message m)
        {
            base.WndProc(ref m);

            switch (m.Msg)
            {
                case WM_LBUTTONDOWN:
                    {
                        if (m.WParam.ToInt32() == VK_LBUTTON)
                        {
                            this._mouseDownPos = GetPointFromLPARAM(m.LParam.ToInt32());
                        }
                    }
                    break;
                case WM_LBUTTONUP:
                    QQForm_MouseUp();
                    break;
                case WM_MOUSELEAVE:
                    QQForm_MouseLeave();
                    break;
                case WM_MOUSEHOVER:
                    QQForm_MouseEnter();
                    break;
                case WM_MOUSEMOVE:
                    {
                        TRACKMOUSEEVENT msevnt = new TRACKMOUSEEVENT();
                        msevnt.cbSize = Marshal.SizeOf(typeof(TRACKMOUSEEVENT));
                        msevnt.dwFlags = TME_HOVER;
                        msevnt.hwndTrack = (long)this.Handle;
                        msevnt.dwHoverTime = 300;

                        if (m.WParam.ToInt32() == VK_LBUTTON)
                        {
                            Point newCursor = GetPointFromLPARAM(m.LParam.ToInt32());
                            this.Location = new Point(this.Location.X + newCursor.X - this._mouseDownPos.X,
                                this.Location.Y + newCursor.Y - this._mouseDownPos.Y);
                        }
                    }
                    break;
                default:
                    break;
            }
        }
       
        /// <summary>
        /// 获得低16位值
        /// </summary>
        /// <param name="lParam"></param>
        /// <returns></returns>
        public static int GET_X_LPARAM(int lParam) { return (lParam & 0xffff); }

        /// <summary>
        /// 获得高16位值
        /// </summary>
        /// <param name="lParam"></param>
        /// <returns></returns>
        public static int GET_Y_LPARAM(int lParam) { return (lParam >> 16); }
        /// <summary>
        /// 解析出鼠标的新坐标(相对于窗体的坐标)
        /// </summary>
        /// <param name="lParam"></param>
        /// <returns></returns>
        public static Point GetPointFromLPARAM(int lParam)
        { return new Point(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)); }

        private Point _mouseDownPos = new Point();

        private void button1_Click(object sender, EventArgs e)
        {
            this.Close();
        }
    }
}

工程文件:/Files/FiredFish/FormHideLikeQQ

相关内容