C#注销或系统关机等事件

时间:2022-06-13 08:44:40
一般情况下,在研发应用程式的时候都很少考虑一些系统部分的变化对应用程式带来影响,比如系统字体库里的字体增加或减少,用户注销或系统关机,桌面主题变换等等。针对应用程式的不同,或多或少会造成一些影响,比如程式在运行过程中没有退出就被用户注销,有可能造成数据丢失,系统字体的更改或系统时钟的更改对程式造成界面显示上或处理上的影响。假如需要程式有一定的健壮性,就需要在这些事件发生时做一些处理。幸运的是为实现这些功能我们无需自己写一些繁杂的代码,.net fcl提供了一个类microsoft.win32.systemevents来很好的完成这项任务,在看大师charles petzold著的《microsoft c# windows 程式设计》的时候发现这个类,想必许多人都已用过了,但是还是决定自己写一些代码来体验一下。 
         打开.net framework sdk 文档,查看systemevents的信息,他作为一个类提供了一些静态事件,我新建一个windows 项目对一些事件进行了测试。 
在窗体构造函数中注册一堆静态事件, 
public form1() 
         { 
              initializecomponent(); 
              //当用户更改显示配置时发生。 
              systemevents.displaysettingschanged += new eventhandler(systemevents_displaysettingschanged); 
              //在侦听系统事件的线程终止前发生。将在事件线程上调用委托。 
              systemevents.eventsthreadshutdown += new eventhandler(systemevents_eventsthreadshutdown); 
              //当用户在系统中添加或移除字体时发生。 
              systemevents.installedfontschanged += new eventhandler(systemevents_installedfontschanged); 
              //当系统用完可用 ram 时发生。 
              systemevents.lowmemory += new eventhandler(systemevents_lowmemory); 
              //当用户转换到使用其他调色板的应用程式时发生。 
              systemevents.palettechanged += new eventhandler(systemevents_palettechanged); 
              //当用户挂起或继续系统时发生。 
              systemevents.powermodechanged += new powermodechangedeventhandler(systemevents_powermodechanged); 
              //当用户注销或关闭系统时发生。 
              systemevents.sessionended += new sessionendedeventhandler(systemevents_sessionended); 
              //当用户试图注销或关闭系统时发生。 
              systemevents.sessionending += new sessionendingeventhandler(systemevents_sessionending); 
              //当用户更改系统时钟上的时间时发生。 
              systemevents.timechanged += new eventhandler(systemevents_timechanged); 
              //在窗口计时器间隔过期时发生。 
              systemevents.timerelapsed += new timerelapsedeventhandler(systemevents_timerelapsed); 
              //在用户最好选择项更改后发生。 
              systemevents.userpreferencechanged += new userpreferencechangedeventhandler(systemevents_userpreferencechanged); 
              //当用户最好选择项更改时发生。 
              systemevents.userpreferencechanging += new userpreferencechangingeventhandler(systemevents_userpreferencechanging); 
         } 
上面的代码很清楚也很简单,对其中几个事件处理程式的测试如下, 
         private void systemevents_userpreferencechanging(object sender, userpreferencechangingeventargs e) 
         { 
              userpreferencecategory category = e.category; 
              messagebox.show(category.tostring()); 
         } 
userpreferencecategory是个枚举类型,每一项值表示标识已更改的用户最好选择项区域,类型比较多,具体能够看msdn文档,userpreferencechanged事件类似,使用userpreferencechangedeventargs参数。 
下面是系统注销或关闭事件处理程式, 
private void systemevents_sessionending(object sender, sessionendingeventargs e) 
         { 
              if(messagebox.show(this,"是否允许系统注销!","系统提示",messageboxbuttons.yesno) != dialogresult.yes) 
              { 
                   e.cancel = true; 
              } 
              else 
              { 
                   e.cancel = false; 
              } 
              sessionendreasons reason = e.reason; 
              switch(reason) 
              { 
                   case sessionendreasons.logoff: 
                       messagebox.show("用户正在注销。操作系统继续运行,但启动此应用程式的用户正在注销。"); 
                       break; 
                   case sessionendreasons.systemshutdown: 
                       messagebox.show("操作系统正在关闭。"); 
                       break; 
              } 
         } 
假如把上面的事件处理程式修改成如下 
private void systemevents_sessionending(object sender, sessionendingeventargs e) 
         { 
              e.cancel = true;            
         } 
那会出现什么情况,您点击开始菜单关机选择注销、关机、或重新启动将会失效,电脑不能正常关机了,进一步的话把程式做成windows服务,人不知鬼不觉,晕,恶作剧? 
sessionended事件同上,事件参数类为sessionendedeventargs,同sessionendingeventargs相比少了cancel属性,cancel属性同一些windows下的某些事件差不多,比如form.closing事件,control.validating事件。 
     补充,假如需要获取应用程式需要的系统信息,能够访问system.windows.forms.systeminformation类,这也是个很有用的类,他提供了一组静态属性。