撩妹小工具 MarvellousMouse

chendaxian發表於2022-03-27

前言

之前在知乎閒逛看有意思的專案的時候,發現一個前輩曾做過一個在滑鼠周圍隨機生成愛心的小程式,閒來無聊實現了一版隨機生成彩色小球的(因為沒有女朋友,只是練練手)。最近疫情在網上撩了一個小妹妹,她知道這個程式之後,讓我給她做一個“格桑花”版的。我想著應該差不多,就改了改程式碼。好感度+1(不一定有),但是妹汁送我一杯奶茶,嘻嘻。話不多說,下面介紹一下。


實現

總的思路很簡單,就是獲取滑鼠的位置,然後再滑鼠周圍隨機進行動畫。實現主要分為這幾個函式。

            InitProperty();    //初始化動畫配置,放到多大,透明度多少,持續時間
            InitGraph();      //初始化需要放大的樣式,只要繼承FrameworkElement類就可以了
            MaxmizeAndTransparenceWindow();       //視窗設定,設定全屏,還有一個坑(放大比)
            StartMarvellousMouse();       //核心程式碼,隨機生成小球

1.初始化屬性

這裡動畫主要是樣式放大的一些設定:長寬,透明度。是WPF比較基礎的類FrameworkElement的屬性。

           private void InitProperty()
        {
            MyStoryBoard = new Storyboard();
            //MyStoryBoard.RepeatBehavior = RepeatBehavior.Forever;
            DAWidth = new DoubleAnimation();
            DAWidth.From = 0;
            DAWidth.To = 2 * Radius;
            DAWidth.Duration = new Duration(TimeSpan.FromMilliseconds(DurationTime));
            DAHeight = new DoubleAnimation();
            DAHeight.From = 0;
            DAHeight.To = 2 * Radius;
            DAHeight.Duration = new Duration(TimeSpan.FromMilliseconds(DurationTime));
            DAOpacity = new DoubleAnimation();
            DAOpacity.From = 0;
            DAOpacity.To = 0.7;
            DAOpacity.Duration = new Duration(TimeSpan.FromMilliseconds(DurationTime));
            MyStoryBoard.Children.Add(DAWidth);
            MyStoryBoard.Children.Add(DAHeight);
            MyStoryBoard.Children.Add(DAOpacity);
        }

2.初始化樣式

這裡一開始是使用WPF的自定義控制元件比如ellipse,等。後來給妹汁做格桑花的時候,突然想到:圖片不就是天然的FrameworkElement嘛,所以理論上啥樣式都已放進圖片並顯示。順帶說一句,圖片資源獲取網上搜一下,然後在Google活bing的識圖裡面找類似的。
很難找到背景透明的圖(比如帶白底),可以用ps工具,或者網上的去底色工具或網址(我直接百度搜了個網址就可以用)。反正圖片放大的也不大,略微丟失一點邊邊角角無傷大雅。

        private void InitGraph()
        {
            var elements =ElementProvider.GetElements<MyImage>();
            if (elements != null)
            {
                foreach (var item in elements)
                {
                    this.canvas.Children.Add(item);
                }
            }
            NumofGrap = this.canvas.Children.Count;
        }


3.螢幕最大化及一些設定

這裡的一個坑就是,不是所有的螢幕都是100%放大,在一些筆記本上可能解析度調的超級高,然偶後放大到200%,所以滑鼠位置會有問題。這裡計算了下放大比,然後滑鼠的XY乘以係數。

        private void MaxmizeAndTransparenceWindow()
        {
            this.Width = SystemParameters.PrimaryScreenWidth;
            this.Height = SystemParameters.PrimaryScreenHeight;
            var hdc = GetDC(GetDesktopWindow());
            int ResolutionHeight = GetDeviceCaps(hdc, 10);        //高
            int ResolutionWidth = GetDeviceCaps(hdc, 8);       //寬
            ScaleX = (double)(ResolutionWidth / Width);
            ScaleY = (double)(ResolutionHeight / Height);
            this.Top = 0;
            this.Left = 0;
            this.WindowStyle = WindowStyle.None;
            this.ResizeMode = ResizeMode.NoResize;
            this.Topmost = true;
        }

4.核心顯示

就是不停地獲取滑鼠位置,然後隨機再滑鼠周圍生成圖案。這裡因為是死迴圈瘋狂更新,所以記憶體會爆炸。所以設定執行緒需要休息一會會再傳送(及時1ms也足夠了)。

        private void StartMarvellousMouse()
        {
            POINT lpPoint;
            var widthProperty = new PropertyPath("Width");
            var heightProperty = new PropertyPath("Height");
            var opacityProperty = new PropertyPath("Opacity");
            new Thread(() =>
            {
                while (true)
                {
                    for (int i = 0; i < NumofGrap; i++)
                    {
                        GetCursorPos(out lpPoint);
                        Dispatcher.BeginInvoke(new Action(() =>
                        {
                            if (i == NumofGrap) return;           //防止迴圈i=NumofGrap的時候,ui執行緒正好訪問
                            var item = (FrameworkElement)this.canvas.Children[i];
                            Canvas.SetLeft(item, (lpPoint.X - Radius + RandomDistance) / ScaleX);
                            Canvas.SetTop(item, (lpPoint.Y - Radius + RandomDistance) / ScaleY);
                            //item.Fill = RandomColor;
                            Storyboard.SetTarget(DAWidth, item);
                            Storyboard.SetTargetProperty(DAWidth, widthProperty);
                            Storyboard.SetTarget(DAHeight, item);
                            Storyboard.SetTargetProperty(DAHeight, heightProperty);
                            Storyboard.SetTarget(DAOpacity, item);
                            Storyboard.SetTargetProperty(DAOpacity, opacityProperty);
                            MyStoryBoard.Begin();
                        }));
                        Thread.Sleep((int)DurationTime / NumofGrap);
                    }
                }

            }).Start();
        }

最後預祝我能追到妹汁吧,感謝。

程式碼開源:git@github.com:liuchuomidi/MarvellousMouse.git

相關文章