服务器之家:专注于服务器技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - C# - C#实现打造气泡屏幕保护效果

C#实现打造气泡屏幕保护效果

2021-12-08 13:08李sir C#

本文是介给大家介绍一个很好玩的小程序:气泡屏幕保护!类似于windows的屏保功能,有需要的朋友可以参考一下。

本文主要是介绍c#实现打造气泡屏幕保护效果,首先说一下制作要点:1 窗口要全屏置顶 2 模拟气泡的滚动和粘滞效果 3 支持快捷键esc退出

大致就是这3个要点了,其他还有一些细节我们在程序中根据需要再看,ok,开工!

首先是全屏置顶,因为是屏幕保护嘛,这个简单,在窗体的属性设置里把formborderstyle设置为none表示无边框,把showintaskbar设置为false表示不在任务栏出现,最后一个把windowstate设置为maximized表示最大化即可,当然可以设置topmost为true让窗口置顶,不过这个不是绝对的,如果有其他窗口也使用topmost的话会让我们失去焦点,所以我们要注册一个快捷键让程序可以退出!

模拟气泡我们可以用graphics类中的drawellipse方法来画一个圆,当然这个圆我们可以指定不同的颜色和大小,这里重点讲一下怎么模拟粘滞效果!

所谓粘滞效果相信大家到知道,胶体大家都见过吧?就是类似胶体那种有弹性并且可以在改变形状后回复原型的那种效果,当然这里要想模拟这个效果只能说是稍微类似,drawellipse方法中最后两个参数表示圆的大小,我们可以在这里做文章,由于循环的速度很快,我们只要动态改变圆的大小就可以产生类似粘滞的效果,当然这个改变大小的参数不能太大,否则就无效了!

我们在onpaint事件中写入如下代码来绘制一些圆:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
random ra = new random(); //初始化随机数
   bmp = new bitmap(clientsize.width,clientsize.height, e.graphics);
   graphics bmpgraphics = graphics.fromimage(bmp);
   // 绘制圆形     
  for (int i=1;i<=13;i++)//这里绘制13个圆形
   {
     bmpgraphics.drawellipse(new pen(color.fromname(colours[i]),2),//根据事先定义好的颜色绘制不同颜色的圆
      ballarray[i, 1], ballarray[i, 2], 70+ra.next(1, 10), 70+ra.next(1, 10));
      //注意上面的最后两个参数利用随机数产生粘滞效果
   }
   e.graphics.drawimageunscaled(bmp, 0, 0);
   bmpgraphics.dispose();
   bmp.dispose();//这里是非托管的垃圾回收机制,避免产生内存溢出

这样,通过以上代码就可以绘制出一些不同颜色的具有粘滞效果的圆来模拟气泡

下面是注册系统热键,有个api函数registerhotkey可以完成系统快捷键的注册,使用他之前我们要先引用一个系统的dll文件:user32.dll,然后对这个registerhotkey函数进行一下声明:

?
1
2
[dllimport("user32.dll")]//引用user32.dll
public static extern uint32 registerhotkey(intptr hwnd, uint32 id, uint32 fsmodifiers, uint32 vk); //声明函数原型

由于引用了一个dll文件,我们不要忘了在文件头加入dllimport的类声明using system.runtime.interopservices;然后在form1的构造函数中来注册一个系统热键,这里我们注册esc:registerhotkey(this.handle, 247696411, 0, (uint32)keys.escape); 通过以上步骤,我们就可以注册一个或多个系统热键,但是,注册系统热键后我们还不能立即使用,因为我们在程序中还无法对这个消息进行响应,我们重载一下默认的wndproc过程来响应我们的热键消息:

?
1
2
3
4
5
6
7
8
9
protected override void wndproc(ref message m)//注意是保护类型的过程
 {
     const int wm_hotkey = 0x0312;
 }
    if (m.msg == wm_hotkey & & m.wparam.toint32() == 247696411) //判断热键消息是不是我们设置的
       {
        application.exit();//如果消息等于我们的热键消息,程序退出
      }
    base.wndproc(ref m);//其他消息返回做默认处理

好了,通过以上一些步骤,我们就基本完成了这个屏幕保护程序的要点设计,其他的详细过程可以参考源码,程序运行的时候背景是透明的,这个也不难实现

1.this.backcolor = system.drawing.color.fromargb(((int)(((byte)(255)))), ((int)(((byte)(192)))), ((int)(((byte)(192)))));
2.this.transparencykey = system.drawing.color.fromargb(((int)(((byte)(255)))), ((int)(((byte)(192)))), ((int)(((byte)(192)))));

屏幕保护程序代码如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
using system;
using system.drawing;
using system.collections;
using system.componentmodel;
using system.windows.forms;
using system.runtime.interopservices;
/*
 屏幕保护程序
 使用技术:系统热键,随机数,graphics类绘制圆形
 编译环境:visualstudio 2005
 运行要求:安装.net framework 2.0 框架
 其他:使用esc退出
 
 说明:由于使用了循环控制图形位移,cpu占用在20%-30%左右
 程序具有自动垃圾回收机制避免造成内存溢出
 
 2009年3月15日
 */
namespace animatball
{
  /// <summary>
  /// summary description for form1.
  /// </summary>
  
  public class form1 : system.windows.forms.form
  {
 
    public int[,] ballarray = new int[20,20];
    public string[] colours = new string[16];
  
    public bitmap bmp;
 
    private system.windows.forms.timer timer1;
    private system.componentmodel.icontainer components;
    [dllimport("user32.dll")]
    public static extern uint32 registerhotkey(intptr hwnd, uint32 id, uint32 fsmodifiers, uint32 vk); //api
     //重写消息循环
    
    protected override void wndproc(ref message m)
     {
       const int wm_hotkey = 0x0312;
      
       if (m.msg == wm_hotkey && m.wparam.toint32() == 247696411) //判断热键
       {
         application.exit();
       }
 
       base.wndproc(ref m);
     }
    public form1()
    {
      //
      // required for windows form designer support
      //
      initializecomponent();
      //colours[0]="red";
      colours[1]="red";
      colours[2]="blue";
      colours[3]="black";
      colours[4]="yellow";
      colours[5]="crimson";
      colours[6]="gold";
      colours[7]="green";
      colours[8]="magenta";
      colours[9]="aquamarine";
      colours[10]="brown";
      colours[11]="red";
      colours[12]="darkblue";
      colours[13]="brown";
      colours[14]="red";
      colours[15]="darkblue";
      initializecomponent();
      registerhotkey(this.handle, 247696411, 0, (uint32)keys.escape); //注册热键
      //
      // todo: add any constructor code after initializecomponent call
      //
    }
 
    /// <summary>
    /// clean up any resources being used.
    /// </summary>
 
    protected override void dispose( bool disposing )
    {
      if( disposing )
      {
        if (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()
    {
      this.components = new system.componentmodel.container();
      this.timer1 = new system.windows.forms.timer(this.components);
      this.suspendlayout();
      //
      // timer1
      //
      this.timer1.interval = 25;
      this.timer1.tick += new system.eventhandler(this.timer1_tick);
      //
      // form1
      //
      this.autoscalebasesize = new system.drawing.size(6, 14);
      this.backcolor = system.drawing.color.fromargb(((int)(((byte)(255)))), ((int)(((byte)(192)))), ((int)(((byte)(192)))));
      this.clientsize = new system.drawing.size(373, 294);
      this.doublebuffered = true;
      this.formborderstyle = system.windows.forms.formborderstyle.none;
      this.name = "form1";
      this.showintaskbar = false;
      this.text = "小焱屏幕保护";
      this.topmost = true;
      this.transparencykey = system.drawing.color.fromargb(((int)(((byte)(255)))), ((int)(((byte)(192)))), ((int)(((byte)(192)))));
      this.windowstate = system.windows.forms.formwindowstate.maximized;
      this.load += new system.eventhandler(this.form1_load);
      this.resumelayout(false);
 
    }
      #endregion
    /// <summary>
    /// the main entry point for the application.
    /// </summary>
 
    [stathread]
    static void main()
    {
      application.run(new form1());
    }
 
    private void timer1_tick(object sender, system.eventargs e)
    {
      
      for (int i=1;i<=13;i++)
      {  
        //add direction vectors to coordinates
        ballarray[i,1] = ballarray[i,1] + ballarray[i,3];
        ballarray[i,2] = ballarray[i,2] + ballarray[i,4];
        //if ball goes of to right
        if ((ballarray[i,1]+50)>=clientsize.width)
        {     
          ballarray[i,1]=ballarray[i,1]-ballarray[i,3];
          ballarray[i,3]=-ballarray[i,3];
        }
          //if ball goes off bottom
        else if ((ballarray[i,2]+50)>=clientsize.height)
        {
          ballarray[i,2]=ballarray[i,2]-ballarray[i,4];
          ballarray[i,4]=-ballarray[i,4];
        }
          //if ball goes off to left
        else if (ballarray[i,1]<=1)
        {
          ballarray[i,1]=ballarray[i,1]-ballarray[i,3];
          ballarray[i,3]=-ballarray[i,3];
        }        
          //if ball goes over top
        else if (ballarray[i,2]<=1)
        {
          ballarray[i,2]=ballarray[i,2]-ballarray[i,4];
          ballarray[i,4]=-ballarray[i,4];
        }
      }
      this.refresh(); //force repaint of window
    }
    //called from timer event when window needs redrawing
    protected override void onpaint(painteventargs e)
    {
      random ra = new random();
      bmp = new bitmap(clientsize.width,clientsize.height, e.graphics);
      graphics bmpgraphics = graphics.fromimage(bmp);
      // draw here       
      for (int i=1;i<=13;i++)
      {
        bmpgraphics.drawellipse(new pen(color.fromname(colours[i]),2),
          ballarray[i, 1], ballarray[i, 2], 70+ra.next(1, 10), 70+ra.next(1, 10));//利用随机数产生粘滞效果
      }
      e.graphics.drawimageunscaled(bmp, 0, 0);
      //draw ellipse acording to mouse coords.
      
      bmpgraphics.dispose();
      bmp.dispose();
    }     
    private void form1_load(object sender, eventargs e)
    {
      random r = new random();
      //set ball coords and vectors x,y,xv,yv
      for (int i = 1; i <= 13; i++)
      {
        ballarray[i, 1] = +r.next(10) + 1; //+1 means i lose zero values
        ballarray[i, 2] = +r.next(10) + 1;
 
        ballarray[i, 3] = +r.next(10) + 1;
        ballarray[i, 4] = +r.next(10) + 1;
      }
      timer1.start();
    }
   
  }
}

transparencykey可以让窗体的某个颜色透明显示,我们只要把窗体的颜色和transparencykey的颜色设置一致就可以了,这里我设置的是粉红,注意最好设置的颜色是窗体所没有的,否则一旦匹配将会以透明显示!

效果如下:

C#实现打造气泡屏幕保护效果

延伸 · 阅读

精彩推荐
  • C#深入理解C#的数组

    深入理解C#的数组

    本篇文章主要介绍了C#的数组,数组是一种数据结构,详细的介绍了数组的声明和访问等,有兴趣的可以了解一下。...

    佳园9492021-12-10
  • C#三十分钟快速掌握C# 6.0知识点

    三十分钟快速掌握C# 6.0知识点

    这篇文章主要介绍了C# 6.0的相关知识点,文中介绍的非常详细,通过这篇文字可以让大家在三十分钟内快速的掌握C# 6.0,需要的朋友可以参考借鉴,下面来...

    雨夜潇湘8272021-12-28
  • C#如何使用C#将Tensorflow训练的.pb文件用在生产环境详解

    如何使用C#将Tensorflow训练的.pb文件用在生产环境详解

    这篇文章主要给大家介绍了关于如何使用C#将Tensorflow训练的.pb文件用在生产环境的相关资料,文中通过示例代码介绍的非常详细,需要的朋友可以参考借鉴...

    bbird201811792022-03-05
  • C#利用C#实现网络爬虫

    利用C#实现网络爬虫

    这篇文章主要介绍了利用C#实现网络爬虫,完整的介绍了C#实现网络爬虫详细过程,感兴趣的小伙伴们可以参考一下...

    C#教程网11852021-11-16
  • C#SQLite在C#中的安装与操作技巧

    SQLite在C#中的安装与操作技巧

    SQLite,是一款轻型的数据库,用于本地的数据储存。其优点有很多,下面通过本文给大家介绍SQLite在C#中的安装与操作技巧,感兴趣的的朋友参考下吧...

    蓝曈魅11162022-01-20
  • C#C#微信公众号与订阅号接口开发示例代码

    C#微信公众号与订阅号接口开发示例代码

    这篇文章主要介绍了C#微信公众号与订阅号接口开发示例代码,结合实例形式简单分析了C#针对微信接口的调用与处理技巧,需要的朋友可以参考下...

    smartsmile20127762021-11-25
  • C#VS2012 程序打包部署图文详解

    VS2012 程序打包部署图文详解

    VS2012虽然没有集成打包工具,但它为我们提供了下载的端口,需要我们手动安装一个插件InstallShield。网上有很多第三方的打包工具,但为什么偏要使用微软...

    张信秀7712021-12-15
  • C#C#设计模式之Strategy策略模式解决007大破密码危机问题示例

    C#设计模式之Strategy策略模式解决007大破密码危机问题示例

    这篇文章主要介绍了C#设计模式之Strategy策略模式解决007大破密码危机问题,简单描述了策略模式的定义并结合加密解密算法实例分析了C#策略模式的具体使用...

    GhostRider10972022-01-21