C#动态生成控件以及添加事件处理

C#动态生成控件以及添加事件处理

有时候需要在程序运行到一定时候或者某个事件之后需要动态生成控件 C#下一般方式是:

    private Button Db=new Button() ;
     Db.Name="Dy_Button"           //设定名称
     Db.Location=new Point(100,200);//设定位置
     。。。。//其他属性设置

   //这里添加消息处理
     。。
     this.Controls.Add (Db);//添加到控件组中

  这样就完成了动态生成但是需要给控件添加消息处理事件

  那么现在就需要在生成控件添加到控件组前增加如下语句:

DPB.MouseClick += new EventHandler(this.pictureBox_MouseClick);

  现在编写这个消息处理的函数pictureBox_Click()

        private void pictureBox_MouseClick(object sender,EventArgs e)
        {
            MessageBox.Show("click");
        }

  这样完成了事件处理的添加

  首先,创建一个全局变量"i "用来区分各个新的按钮:

private int i=0;

  然后在已有的按钮中添加方法如下:

   private void button1_Click(object sender, System.EventArgs e)
   {
    i++;
    Button b = new Button();//创建一个新的按钮
    b.Name="b"+i;//这是我用来区别各个按钮的办法
    System.Drawing.Point p = new Point(12,13+i*30);//创建一个坐标,用来给新的按钮定位
    b.Location = p;//把按钮的位置与刚创建的坐标绑定在一起
  
    panel1.Controls.Add(b);//向panel中添加此按钮
    b.Click += new System.EventHandler(btn_click);//将按钮的方法绑定到按钮的单击事件中b.Click是按钮的单击事件
   }

完成以上步骤就已经可以进行动态按钮的创建 下面我们来讲如何对新建的按钮添加对应的事件方法btn_click(): private void btn_click(object sender, System.EventArgs e) { Button b1 = (Button)sender;//将触发此事

  完成以上步骤就已经可以进行动态按钮的创建

 

  下面我们来讲如何对新建的按钮添加对应的事件方法btn_click():

   private void btn_click(object sender, System.EventArgs e)
   {
    Button b1 = (Button)sender;//将触发此事件的对象转换为该Button对象
  
     MessageBox.Show(""+b1.Name);
   }

  至此就已经完成了动态创建按钮和事件

  ASP.net为控件动态添加事件

  实现的功能是在网页上的Panel中动态添加一个Button,并为这个Button写一个单击事件。

  动态添加控件的事件,语句:

Control.Command += new CommandEventHandler(this.EventFun);

  具体的代码请看下面:

  需要特别注意的是:

  添加控件和给控件加事件时绝对不能放到 if!IsPostback{}里面,那样的话,点击一次后控件会消失,而且事件也不

  会执行。

protected void Page_Load(object sender, EventArgs e)
    {
       //将输入字符串分析为System.Web.UI.Control对象,b为传进去的值
        Control c = ParseControl("");

        //将控件添加大Panel中
        this.Panel1.Controls.Add(c);

        //查找页面名为myButton的控件
        Button Button = (Button)Page.FindControl("myButton");

        //添加事件On_Button
        Button.Command += new CommandEventHandler(this.On_Button);
       
    }

    //CommandEventArgs为command事件提供数据
    protected void On_Button(Object sender,CommandEventArgs e)
    {
        Response.Write("");
    }

动态添加控件并添加事件 private void Page_Load(object sender, System.EventArgs e) { Button Button1 = new Button(); Button1.CommandArgument = b1; Button1.Text = Btn1; Button1.Command += new CommandEvent

  动态添加控件并添加事件

 

private void Page_Load(object sender, System.EventArgs e)
{
   Button Button1 = new Button();
   Button1.CommandArgument = "b1";
   Button1.Text = "Btn1";
   Button1.Command += new CommandEventHandler(this.OnButton);
   PlaceHolder1.Controls.Add(Button1);
   Button Button2 = new Button();
   Button2.CommandArgument = "b2";
   Button2.Text = "Btn2";
   Button2.Command += new CommandEventHandler(this.OnButton);
   PlaceHolder1.Controls.Add(Button2);


   Control c3 = ParseControl(""); //将字符串转换成Web控件
   Control c4 = ParseControl("");
   PlaceHolder1.Controls.Add(c3);
   PlaceHolder1.Controls.Add(c4);
   Button myBut = (Button)Page.FindControl("Button3");
   myBut.Command += new CommandEventHandler(this.OnButton);
   Button myBut2 = (Button)Page.FindControl("Button4");
   myBut2.Command += new CommandEventHandler(this.OnButton);

}
public void OnButton(Object Sender, CommandEventArgs e)
{
   switch (e.CommandArgument.ToString().ToLower())
   {
    case "b1":
     Label1.Text = "Button 1";
     break;
    case "b2":
     Label1.Text = "Button 2";
     break;
    case "b3":
     Label1.Text = "Button 3";
     break;
    case "b4":
     Label1.Text = "Button 4";
     break;
   };
} 

这几天忙,好久没上来了,今天项目基本完了,可以轻松下了。明天周末,呵呵。 我项目中遇到的是动态创建Tab选项卡和Gridview,按下面的方法可以,创建它们当然在page_load里了,有时,它会引起你页面上其它的按钮用

  这几天忙,好久没上来了,今天项目基本完了,可以轻松下了。明天周末,呵呵。

 

   我项目中遇到的是动态创建Tab选项卡和Gridview,按下面的方法可以,创建它们当然在page_load里了,有时,它会引起你页面上其它的按钮用不了,这时,你可以把它们不放在page_load里,而放在page_init里,这样就不会有问题了,我不知其它的Ajax控件会不会有这样的问题,我创建TabPanel时,就出现异常。我把它们放在Page_Init里就不会这样了。

  动态添加AjaxControl ToolkitTab控件及设置模板

  有朋友在使用AjaxControl Toolkit里的Tab控件,他刚刚问怎么实现在cs里动态添加TabPanel项。我建了一个项目试了一下。主要问题是TabPanel里如何创建ContentTemplate

   控件使用方法比较简单,直接拖到页面上,添加TabPanel,然后直接输入TabPanel的内容就可以了,控件完全支持设计时的WYSIWYG,非常方便。TabPanel里的内容是通过来指定的。这个对应于TabPanelContentTemplate属性,VSintellisense显示它的类型是ITemplate,这是一个接口,我试着在intellisense里找找有没有类实现了这个接口,但一无所获。找不到这个类,就没有办法给ContentTemplate赋值。于是查看了一下Tab控件的源码,又查阅了MSDN,终于把问题解决了。

  问题关键就在于这个实现了ITemplate接口的类,我找不到,只好自己写了一个。也不知道有没有别的方法,希望有知道的朋友告诉我。全部代码如下:

using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using AjaxControlToolkit; //记得加上这个啊

public partial class _Default : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        TabContainer tabContainer1 = new TabContainer();
        TabPanel tab1 = new TabPanel();
        tab1.HeaderText = "标签1";
        tabContainer1.Tabs.Add(tab1);
        TabPanel tab2 = new TabPanel();
        tab2.HeaderText = "标签2";
        tabContainer1.Tabs.Add(tab2);

        //建立第一个Tab里的内容
        Panel panel1 = new Panel();
       
        Label label1 = new Label();
        label1.Text = "这是第一个Tab";

        panel1.Controls.Add(label1);

        //创建一个Template
        TabContentTemplate temp1 = new TabContentTemplate();
        //添加子控件
        temp1.SetTemplate(panel1);

        tab1.ContentTemplate = temp1;
        this.form1.Controls.Add(tabContainer1);
    }


}

public class TabContentTemplate : ITemplate
{
    private Control _template;

    public void SetTemplate(Control templateControl)
    {
        _template = templateControl;
    }

    ITemplate Members#region ITemplate Members

    public void InstantiateIn(Control container)
    {
        container.Controls.Add(_template);
    }

    #endregion
}

 

  很多控件,如GridViewRepeat等都使用了Template,应该也都可以按这种方法来实现动态设置模板了。

  BTW,另外还有一种方法动态设置模板,就是使用Page.LoadTemplate("template.ascx"),如tab1.ContentTemplate=Page.LoadTemplate("template.ascx") 

posted @ 2010-04-21 21:32 beibei11 阅读(398) | 评论(0) | 编辑

  2010420

动态添加自定义控件:即按一下Botton添加一个UseControl,再按一下又添加一个

动态添加自定义控件:即按一下Botton添加一个UseControl,再按一下又添加一个

 

ViewState记住你LoadControl几次


int LoadedTimes
{
  get
  {
object o = ViewState["LoadedTimes"];
if (o == null)
return 0;
return (int)o;
  }

  set
  {
ViewState["LoadedTimes"] = value;
  }
}


void CreateControls()
{
  for (int i=0; i < LoadedTimes; i++)
  {
Control c = LoadControl("YourUserControl.ascx");
c.ID = "UC" + i.ToString();
ph.Controls.Add(c);
  }
}

void Page_Load(...)
{
CreateControls();
}


void Button_Click(...)
{
Control c = LoadControl("YourUserControl.ascx");
c.ID = "UC" + LoadedTimes.ToString();
ph.Controls.Add(c);
 
LoadedTimes++;
}

void GetValueButton_Click(..)
{
  for (int i=0; i < LoadedTimes; i++)
  {
YourControl uc = (YourControl)ph.FindControl(""UC" + i.ToString();");
//get the text from your user control
  }
}

 

如果你的稍稍改动少少就更完美了.....
void Button_Click(...)
{
Control c = LoadControl("YourUserControl.ascx");
c.ID = "UC" + LoadedTimes.ToString();
         //
改为
c.ID = "UC" + (LoadedTimes+1).ToString();
ph.Controls.Add(c);
 
LoadedTimes++;
}

posted @ 2010-04-20 22:22 beibei11 阅读(96) | 评论(0) | 编辑

演练:使用 Visual C# 创作用户控件

用户控件提供了一种创建和重用自定义图形界面的方法。用户控件本质上是具有可视化表示形式的组件。因此,它可能包含一个或多个 Windows 窗体控件、组件或代码块,它们能够通过验证用户输入、修改显示属性或执行作者所需的其他任务来扩展功能。可以按照与其他控件相同的方式,将用户控件置于 Windows 窗体中。在本演练的第一部分,创建一个名为 ctlClock 的简单用户控件。在本演练的第二部分通过继承扩展 ctlClock 的功能。

创建项目

创建新的项目时应指定其名称,以设置根命名空间、程序集名称和项目名称,并确保默认组件将位于正确的命名空间中。

创建 ctlClockLib 控件库和 ctlClock 控件

1.     在“文件”菜单上,指向“新建”,然后选择“项目”以打开“新建项目”对话框。

2.     从“C# 项目”列表中选择“Windows 控件库”项目模板,然后在“名称”框中键入 ctlClockLib

注意   Windows 控件库”模板在 Visual C# .NET 的标准版中不可用。有关更多信息,请参见 Visual C# 标准版的功能

默认情况下,项目名称 ctlClockLib 也被分配到根命名空间中。根命名空间用于限定程序集中的组件名。例如,如果两个程序集都提供名为 ctlClock 的组件,则可以使用 ctlClockLib.ctlClock 指定 ctlClock 组件。在解决方案资源管理器中,右击“UserControl1”并从快捷菜单中选择“查看代码”。

3.     找到 Class 语句 public class UserControl1,将 UserControl1 更改为 ctlClock 以更改组件的名称。

注意   默认情况下,用户控件从系统提供的 UserControl 类继承。UserControl 类提供所有用户控件要求的功能,并实现标准方法和属性。

4.     找到构造函数 public UserControl1(),将 UserControl1 更改为 ctlClock

5.     在解决方案资源管理器中,单击“UserControl1”,然后在“属性”窗口中,将 FileName 属性更改为 ctlClock.cs

6.     从“文件”菜单中,选择“全部保存”来保存项目。

Windows 控件和组件添加到用户控件

可视化界面是用户控件的基本部分。这种可视化界面是通过将一个或多个 Windows 控件添加到“用户控件设计器”中实现的。在下面的演示中,将向用户控件中加入 Windows 控件,并编写代码以实现功能。

将标签和计时器添加到用户控件中

1.     在解决方案资源管理器中,右击“ctlClock.cs”,然后选择“视图设计器”。

2.     在工具箱中,单击“Windows 窗体”选项卡,然后双击 label

名为 label1 的标签控件被添加到用户控件设计器上的控件中。

3.     在设计器中,单击 label1。在“属性”窗口中,设置下列属性。

属性

更改为

Name

lblDisplay

Text

(空白)

TextAlign

MiddleCenter

Font.Size

14

4.     在“工具箱”中,单击“Windows 窗体”,然后双击“计时器”。

因为计时器是个组件,所以它在运行时没有可视化的表示形式。因此,它不与其他控件一起出现在“用户控件设计器”上,而是出现在组件栏中。

5.     在组件栏中,单击 timer1,并将 Interval 属性设置为 1000,将 Enabled 属性设置为 true

Interval 属性控制计时器组件的刻度频率。timer1 每走过一个刻度,它都会运行一次 Timer1_Tick 事件中的代码。interval 表示前后两次刻度之间的毫秒数。

6.     在组件栏中,双击 timer1 以转到 ctlClock timer1_Tick 事件。

7.     将该代码修改为类似如下所示的代码示例。请确保将访问修饰符从 private 更改为 protected

这些代码将使得当前时间显示在 lblDisplay 中。因为 timer1 的间隔设置为 1000,所以该事件每隔 1000 毫秒激发一次,从而每隔一秒就更新一次当前时间。

8.     virtual 关键字修改该方法使其可重写。有关更多信息,请参见本主题的下一节“从用户控件继承”。

9.     从“文件”菜单中,选择“全部保存”来保存项目。

Copy Code

protected virtual void timer1_Tick(object sender, System.EventArgs e)

Copy Code

protected void timer1_Tick(object sender, System.EventArgs e){   // Causes the label to display the current time   lblDisplay.Text = DateTime.Now.ToLongTimeString(); }

将属性添加到用户控件中

现在,clock 控件封装了 Label 控件和 Timer 组件,每个都有其自己的继承属性组。尽管您的控件的后续用户无法访问这些控件的个别属性,但可以通过编写适当的代码块来创建和公开自定义属性。在下面的章节中,您将向控件中添加属性,这些属性使用户能够更改背景和文本的颜色。

将属性添加到用户控件中

1.     在解决方案资源管理器中,右击“ctlClock.cs”,然后从快捷菜单中单击“查看代码”。

控件的代码编辑器打开。

2.     找到 public class ctlClock 语句。在开始的 { 后面,键入:

这些语句会创建私有变量,用来存储要创建的属性的值。

3.     在步骤 2 中的变量声明下方键入以下代码:

前述的代码使两个自定义属性(ClockForeColor ClockBackColor)可用于该控件后面的用户。Get Set 语句提供属性值的存储和检索,以及提供实现适合于属性的功能的代码。

4.     从“文件”菜单中,选择“全部保存”来保存项目。

Copy Code

// Declares the name and type of the property.public Color ClockBackColor// Retrieves the value of the private variable colBColor.{   get   {      return colBColor;   }   // Stores the selected value in the private variable colBColor, and    // updates the backcolor of the label control lblDisplay.   set   {      colBColor = value;      lblDisplay.BackColor = colBColor;      }}// Provides a similar set of instructions for the forecolor.public Color ClockForeColor{   get   {      return colFColor;   }   set   {      colFColor = value;      lblDisplay.ForeColor = colFColor;   }}

Copy Code

private Color colFColor;private Color colBColor;

测试控件

控件不是独立的应用程序,它们必须寄宿在容器中。为了测试控件,必须提供一个在其中运行该控件的测试项目。在本节中,将生成控件并在 Windows 窗体中测试它。

生成控件

o            在“生成”菜单上单击“生成”。

创建测试项目

1.     在“文件”菜单上,指向“添加项目”,然后单击“新建项目”以打开“添加新项目”窗口。

2.     单击“Windows 应用程序”,然后在“名称”框中,键入 Test

3.     在解决方案资源管理器中,右击测试项目的“引用”节点。单击“添加引用”,显示“添加引用”对话框。

4.     单击标记为“项目”的选项卡。用户控件项目将在“项目名称”下列出。

5.     双击您的项目。

注意,此时该项目显示在“选定的组件”窗口中。

在添加引用之后,可以将控件置于您的窗体中。

测试控件

1.     在“工具箱”中,单击“我的用户控件”,然后向下滚动,直到显示表示 ctlClock 的控件图标为止。

2.     双击 ctlClock 图标。

现在,您的控件的副本被添加到窗体中。请注意,它显示当前时间,并且每秒更新一次。

3.     在工具箱中,选择该图标,然后将鼠标移动到您的窗体上。

4.     按住鼠标左键,同时在窗体上移动鼠标。

控件的另一个副本被拖放到窗体上。可以根据需要将任意数目的计时器副本添加到您的窗体上。

5.     在设计器中,单击 ctlClock 的实例之一。

该实例的属性显示在“属性”窗口中。

6.     在“属性”窗口中,找到 ClockBackColor 属性,然后选择属性以显示调色板。

7.     通过单击某个颜色来选择它。

控件的背景颜色更改为您选择的颜色。

8.     使用类似的事件序列来验证 ClockForeColor 属性的功能是否与预期的一样。

在本节中,您已经知道组件和 Windows 控件如何与代码和打包结合,以用户控件的形式提供自定义功能。您已经学会在用户控件中公开属性,以及如何在完成后测试控件。在下一节中,您将学习如何将 ctlClock 用作基来构造继承的用户控件。

从用户控件中继承

在上一节中,您已经学会如何将 Windows 控件、组件和代码组合成可重用的用户控件。现在,您的用户控件可以用作生成其他控件的基础。从基类派生类的过程称为“继承”。在本节中,将创建称为 ctlAlarmClock 的用户控件。此控件将从其父控件 ctlClock 中派生。您将学习通过重写父级方法并添加新的方法和属性来扩展 ctlClock 的功能。

创建继承的控件

创建继承控件的第一步是从它的父控件派生。该操作创建一个新控件,它具有父控件的全部属性、方法和图形特征,但也可以用作添加新功能或修改过的功能的基础。

创建继承的控件

1.     在解决方案资源管理器中,单击 ctlClockLib

2.     从“项目”菜单中,选择“添加继承的控件”。

“添加新项”窗口打开,这时“继承的用户控件”已选中。

3.     在“名称”框中,键入 ctlAlarmClock.cs,然后单击“打开”。

“继承选择器”窗口出现。

4.     在“组件名称”下,双击 ctlClock

5.     在解决方案资源管理器中,浏览当前项目。注意,已添加一个称为 ctlAlarmClock 的文件。

添加 Alarm 属性

将属性添加到继承的控件的方法与添加到用户控件的方法相同。现在将使用属性声明语法向控件中添加两个属性:AlarmTime AlarmSet,前者将存储发出警报的日期和时间值,后者将指示是否设置了警报。

将属性添加到用户控件中

1.     在解决方案资源管理器中,右击 ctlAlarmClock 并选择“查看代码”。

2.     找到 public class 语句。注意,控件从 ctlClockLib.ctlClock 继承。在 { 语句下面键入下列代码:

添加到控件的图形界面

继承的控件具有可视化的界面,该界面与它从中继承的控件的界面完全相同。它与其父控件拥有相同的构成控件,但除非将构成控件的属性特别公开,否则它们将不可用。可以向继承的用户控件的图形界面进行添加,方法与向任何用户控件进行添加时相同。若要继续向您的警报时钟的可视化界面进行添加,请您添加一个 label 控件,它将在警报响起时闪烁。

添加 label 控件

1.     在解决方案资源管理器中,右击 ctlAlarmClock,并从快捷菜单中选择“视图设计器”。

ctlAlarmClock 的设计器在主窗口中打开。

2.     单击该控件的显示部分,并查看“属性”窗口。

注意,当显示所有属性时,属性是浅灰色的。这表明这些属性是 lblDisplay 所固有的,因而不能在属性窗口中修改或访问。默认情况下,包含在用户控件中的控件是 private,其属性无论如何都无法访问。

提示   如果希望用户控件后面的用户可以访问其内部控件,则将其声明为 public protected。这样就可以使用适当的代码,设置和修改包含在用户控件内的控件的属性。

3.     将一个 Label 控件添加到您的用户控件。

4.     使用鼠标移动该 label 控件,使它紧靠在显示框之下。在“属性”窗口中,设置以下属性:

属性

设置

Name

lblAlarm

Text

Alarm!

TextAlign

Middle Center

Visible

false

添加警报功能

在前面的章节中,已经添加了一些属性和一个控件,它们将启用用户控件中的警报功能。在本节中,将添加代码以比较当前时间和警报时间,如果两者相同,则警报会闪烁。通过重写 ctlClock Timer1_Tick 方法并将其他的代码添加到其中,可以在扩展 ctlAlarmClock 功能的同时仍保留 ctlClock 的固有功能。

重写 ctlClock timer1_Tick 方法

1.     在代码编辑器中,找到 private bool blnAlarmSet; 语句。在它之后,紧接着添加下列语句:

2.     在代码编辑器中,在类的结尾找到 }

3.     } 之前,添加下列代码:

添加此代码将完成几项任务。Override 语句指示控件使用此方法替换从基控件继承的方法。此方法被调用时,它通过调用 base.timer1_Tick 语句来调用它重写的方法,从而确保在该控件中重新产生原始控件包含的所有功能。然后,它运行附加代码以合并警报功能。当触发警报时,闪烁的 label 控件将出现。

警报时钟控件已经基本完成。剩下的唯一事情是实现关闭它的方法。为此,将向 lblAlarm_Click 方法中添加代码。

实现关闭方法

1.     在解决方案资源管理器中,右击“ctlAlarmClock.cs”,然后单击“视图设计器”。

设计器打开。

2.     将一个按钮添加到控件中。按以下方式设置该按钮的属性:

属性

Name

btnAlarmOff

Text

Disable Alarm

3.     在设计器中,双击 btnAlarmOff

代码编辑器打开并显示 private void btnAlarmOff_Click 行。

4.     修改此方法,使其类似于:

5.     从“文件”菜单中,选择“全部保存”来保存项目。

Copy Code

private void btnAlarmOff_Click(object sender, System.EventArgs e){   // Turns off the alarm   AlarmSet = false;   // Hides the flashing label   lblAlarm.Visible = false;}

测试继承的控件

与标准用户控件一样,继承的用户控件不能独立存在,而必须寄宿在窗体或其他容器中。由于 ctlAlarmClock 的功能更加深入,因此需要附加代码以对其进行测试。在本节中,将编写一个简单的程序来测试 ctlAlarmClock 的功能。将编写代码以设置和显示 ctlAlarmClock AlarmTime 属性,而且将测试其继承功能。

生成一个测试窗体并将您的控件添加到该窗体

1.     在解决方案资源管理器中,单击 ctlClockLib。在“生成”菜单上,选择“生成 ctlClockLib”。

2.     将一个新的“Windows 应用程序”项目添加到该解决方案中,并将其命名为 Test2

3.     在解决方案资源管理器中,右击测试项目的“引用”节点。单击“添加引用”以显示“添加引用”窗口。单击标记为“项目”的选项卡。项目将在“项目名称”下列出。双击该项目,并注意该项目此时出现在“选定的组件”窗口中。

4.     在工具箱中,单击“我的用户控件”。

5.     向下滚动,直到 ctlAlarmClock 的图标出现。

6.     双击 ctlAlarmClock,将 ctlAlarmClock 一个副本添加到窗体中。

7.     在工具箱中,定位并双击 DateTimePicker 以将一个 DateTimePicker 控件添加到窗体中,并通过双击 Label 添加一个 Label 控件。

8.     使用鼠标将这些控件放置在窗体上合适的位置。

9.     按以下方式设置这些控件的属性:

控件

属性

label1

Text

(保留为空白)

 

Name

lblTest

dateTimePicker1

Name

dtpTest

 

Format

Time

10. 在设计器中,双击 dtpTest

代码编辑器打开并显示 private void dtpTest_ValueChanged

11. 将该代码修改为类似如下所示:

12. 在解决方案资源管理器中,右击 Test2,然后从快捷菜单中选择“设为启动项目”。

13. 从“调试”菜单中选择“启动”。

测试程序启动。注意,当前时间在 ctlAlarmClock 控件中被更新,并且启动时间显示在 DateTimePicker 控件中。

14. 单击 DateTimePicker,其中显示小时的分钟值。

15. 使用键盘设置一个分钟值,使它比 ctlAlarmClock 显示的当前时间快一分钟。

警报设置的时间显示在 lblTest 中。

16. 等候显示的时间到达警报设置时间。

当显示时间到达设置警报的时间时,lblAlarm 将会闪烁。单击 btnAlarmOff 关闭警报。您现在可以重置警报。

Copy Code

private void dtpTest_ValueChanged(object sender, System.EventArgs e){   ctlAlarmClock1.AlarmTime = dtpTest.Value;   ctlAlarmClock1.AlarmSet = true;   lblTest.Text = "Alarm Time is " +      ctlAlarmClock1.AlarmTime.ToShortTimeString();}

本演练涉及了一些关键概念。您已经学会通过将控件和组件组合到用户控件容器中来创建用户控件。您还已经学会将属性添加到控件,以及编写代码以实现自定义功能。在第二节中,您学会了通过继承来扩展给定用户控件的功能,以及通过重写这些方法来更改宿主方法的功能。

posted @ 2010-04-20 20:23 beibei11 阅读(105) | 评论(0) | 编辑

  2010419

C#static类型的变量和方法

1、定义了变量和方法不知道什么时候该加上static修饰符。

2static变量和方法与非static变量和方法有什么区别?

3、在一个类的静态方法里为什么不能访问该类的非静态成员变量和方法?

4、在一个类的非静态方法中为什么可以访问该类的静态变量和方法?

5、在静态方法中为什么不能用this

6、静态构造函数有什么作用?

基于以上问题,我发表自己的看法如下:

1static变量及方法不用实例化对象就可以用类名.静态变量和类名.静态方法这种方式进行访问,这使得访问更加方便,不用手工实例化对象。对于某些只读变量和方法来说很适合共享。

2static与非static最大的区别就是static类型的变量及方法在调用的时候就在内存中分配了地址,且这个地址只有一份,故static可以直接访问。而非static必需手工去实例化该类,以对象的方式去访问变量和方法。

3、在一个静态方法里去访问该类的非静态变量或方法,由于static是属于类本身的,是在类被调用的时候,static类型就已经生成,而非static此时并没有生成,它不属于这个类本身,它是属于这个类的对象。故在没有实例化成对象的时候,在静态方法中访问非静态是根本找不到它们的,它不属于这个类。

4、在非静态方法中去访问静态,由于类被调用时,静态变量和方法就已经生成,也就是说它们属于这个类。既然已经存在,故不管是在静态方法中,还是非静态方法中都可以访问到它们。

5this表明对象本身,而在静态方法中并没有对象概念存在,它只有类本身这个概念,它和对象是属于两种互拆的状态,即我中无你,你中无我的情况。也就是说你用对象名.静态变量或对象名.静态方法是不可访问的。

6、每个类都必须有构造函数,否则此类无法实例化成对象。而我们有时定义的类可以不写它的构造函数,这是因为编译器会帮我们加上一个静态的空构造函数。这样才能实例化。也可以用静态构造函数去初始化静态变量。

static的全部用法

     
要理解static,就必须要先理解另一个与之相对的关键字,很多人可能都还不知道有这个关键字,那就是auto,其实我们通常声明的不用static修饰的变量,都是auto的,因为它是默认的,就象shortlong总是默认为int一样;我们通常声明一个变量:
      int a;
      string s;
     
其实就是:
      auto int a;
      auto string s;
     
static变量的声明是:
      static int a;
      static string s;
     
这样似乎可以更有利于理解autostatic是一对成对的关键字吧,就像privateprotectedpublic一样;
     
对于static的不理解,其实就是对于auto的不理解,因为它是更一般的;有的东西你天天在用,但未必就代表你真正了解它;auto的含义是由程序自 动控制变量的生存周期,通常指的就是变量在进入其作用域的时候被分配,离开其作用域的时候被释放;而static就是不auto,变量在程序初始化时被分 配,直到程序退出前才被释放;也就是static是按照程序的生命周期来分配释放变量的,而不是变量自己的生命周期;所以,像这样的例子:
     void func()
      ...{
          int a;
          static int b;
      }
     
每一次调用该函数,变量a都是新的,因为它是在进入函数体的时候被分配,退出函数体的时候被释放,所以多个线程调用该函数,都会拥有各自独立的变量a,因 为它总是要被重新分配的;而变量b不管你是否使用该函数,在程序初始化时就被分配的了,或者在第一次执行到它的声明的时候分配(不同的编译器可能不同), 所以多个线程调用该函数的时候,总是访问同一个变量b,这也是在多线程编程中必须注意的! 

      1
.类的静态成员:

      class A
      ...{
      private:
      static int s_;
      };
     
cpp中必须对它进行初始化:
             int A::s_ = 0;//
注意,这里没有static的修饰!
     
类的静态成员是该类所有实例的共用成员,也就是在该类的范畴内是个全局变量,也可以理解为是一个名为A::s_的全局变量,只不过它是带有类安全属性的;道理很简单,因为它是在程序初始化的时候分配的,所以只分配一次,所以就是共用的;
     
类的静态成员必须初始化,道理也是一样的,因为它是在程序初始化的时候分配的,所以必须有初始化,类中只是声明,在cpp中才是初始化,你可以在初始化的 代码上放个断点,在程序执行main的第一条语句之前就会先走到那;如果你的静态成员是个类,那么就会调用到它的构造函数;


      2
.类的静态函数:
      class A
      ...{
      private:
static void func(int );
      };
     
实现的时候也不需要static的修饰,因为static是声明性关键字;
     
类的静态函数是在该类的范畴内的全局函数,不能访问类的私有成员,只能访问类的静态成员,不需要类的实例即可调用;实际上,它就是增加了类的访问权限的全局函数:void A::func(int)
     
静态成员函数可以继承和覆盖,但无法是虚函数;


      3
.只在cpp内有效的全局变量:

     
cpp文件的全局范围内声明:
      static int g_ = 0;
     
这个变量的含义是在该cpp内有效,但是其他的cpp文件不能访问这个变量;如果有两个cpp文件声明了同名的全局静态变量,那么他们实际上是独立的两个变量;
     
如果不使用static声明全局变量:
      int g_ = 0;
     
那么将无法保证这个变量不被别的cpp共享,也无法保证一定能被别的cpp共享,因为要让多个cpp共享一个全局变量,应将它声明为extern(外部)的;也有可能编译会报告变量被重复定义;总之不建议这样的写法,不明确这个全局变量的用法;
     
如果在一个头文件中声明:
      static int g_vaule = 0;
     
那么会为每个包含该头文件的cpp都创建一个全局变量,但他们都是独立的;所以也不建议这样的写法,一样不明确需要怎样使用这个变量,因为只是创建了一组同名而不同作用域的变量;
     
这里顺便说一下如何声明所有cpp可共享的全局变量,在头文件里声明为extern的:
      extern int g_;       //
注意,不要初始化值!
     
然后在其中任何一个包含该头文件的cpp中初始化(一次)就好:
      int g_ = 0;       //
初始化一样不要extern修饰,因为extern也是声明性关键字;
     
然后所有包含该头文件的cpp文件都可以用g_这个名字访问相同的一个变量;


      4
.只在cpp内有效的全局函数:
     
cpp内声明:
      static void func();
     
函数的实现不需要static修饰,那么这个函数只可在本cpp内使用,不会同其他cpp中的同名函数引起冲突;道理和如果不使用static会引起的问 题和第3点一样;不要在头文件中声明static的全局函数,不要在cpp内声明非static的全局函数,如果你要在多个cpp中复用该函数,就把它的 声明提到头文件里去,否则在cpp内部声明需要加上static修饰;在C语言中这点由为重要.


posted @ 2010-04-19 21:58 beibei11 阅读(214) | 评论(0) | 编辑

C# 反射机制(转)

1 什么是反射
2
命名空间与装配件的关系
3
运行期得到类型信息有什么用
4
如何使用反射获取类型
5
如何根据类型来动态创建对象
6
如何获取方法以及动态调用方法
7
动态创建委托

 1、什么是反射
        Reflection
,中文翻译为反射。
       
这是.Net中获取运行时类型信息的方式,.Net的应用程序由几个部分:‘程序集(Assembly)’、‘模块(Module)’、‘类型(class)’组成,而反射提供一种编程的方式,让程序员可以在程序运行期获得这几个组成部分的相关信息,例如:

        Assembly类可以获得正在运行的装配件信息,也可以动态的加载装配件,以及在装配件中查找类型信息,并创建该类型的实例。
Type
类可以获得对象的类型信息,此信息包含对象的所有要素:方法、构造器、属性等等,通过Type类可以得到这些要素的信息,并且调用之。
MethodInfo
包含方法的信息,通过这个类可以得到方法的名称、参数、返回值等,并且可以调用之。
诸如此类,还有FieldInfoEventInfo等等,这些类都包含在System.Reflection命名空间下。

2、命名空间与装配件的关系
       
很多人对这个概念可能还是很不清晰,对于合格的.Net程序员,有必要对这点进行澄清。
       
命名空间类似与Java的包,但又不完全等同,因为Java的包必须按照目录结构来放置,命名空间则不需要。

        装配件是.Net应用程序执行的最小单位,编译出来的.dll.exe都是装配件。

        装配件和命名空间的关系不是一一对应,也不互相包含,一个装配件里面可以有多个命名空间,一个命名空间也可以在多个装配件中存在,这样说可能有点模糊,举个例子:
装配件A
namespace   N1
{
      public   class   AC1   {…}
      public   class   AC2   {…}
}
namespace   N2
{
      public   class   AC3   {…}
      public   class   AC4{…}
}
装配件B
namespace   N1
{
      public   class   BC1   {…}
      public   class   BC2   {…}
}
namespace   N2
{
      public   class   BC3   {…}
      public   class   BC4{…}
}

        这两个装配件中都有N1N2两个命名空间,而且各声明了两个类,这样是完全可以的,然后我们在一个应用程序中引用装配件A,那么在这个应用程序中,我们能看到N1下面的类为AC1AC2N2下面的类为AC3AC4
       
接着我们去掉对A的引用,加上对B的引用,那么我们在这个应用程序下能看到的N1下面的类变成了BC1BC2N2下面也一样。
       
如果我们同时引用这两个装配件,那么N1下面我们就能看到四个类:AC1AC2BC1BC2

        到这里,我们可以清楚一个概念了,命名空间只是说明一个类型是那个族的,比如有人是汉族、有人是回族;而装配件表明一个类型住在哪里,比如有人住在北京、有人住在上海;那么北京有汉族人,也有回族人,上海有汉族人,也有回族人,这是不矛盾的。

        上面我们说了,装配件是一个类型居住的地方,那么在一个程序中要使用一个类,就必须告诉编译器这个类住在哪儿,编译器才能找到它,也就是说必须引用该装配件。
       
那么如果在编写程序的时候,也许不确定这个类在哪里,仅仅只是知道它的名称,就不能使用了吗?答案是可以,这就是反射了,就是在程序运行的时候提供该类型的地址,而去找到它。
有兴趣的话,接着往下看吧。

3、运行期得到类型信息有什么用
       
有人也许疑问,既然在开发时就能够写好代码,干嘛还放到运行期去做,不光繁琐,而且效率也受影响。
这就是个见仁见智的问题了,就跟早绑定和晚绑定一样,应用到不同的场合。有的人反对晚绑定,理由是损耗效率,但是很多人在享受虚函数带来的好处的时侯还没有意识到他已经用上了晚绑定。这个问题说开去,不是三言两语能讲清楚的,所以就点到为止了。
       
我的看法是,晚绑定能够带来很多设计上的便利,合适的使用能够大大提高程序的复用性和灵活性,但是任何东西都有两面性,使用的时侯,需要再三衡量。

接着说,运行期得到类型信息到底有什么用呢?
还是举个例子来说明,很多软件开发者喜欢在自己的软件中留下一些接口,其他人可以编写一些插件来扩充软件的功能,比如我有一个媒体播放器,我希望以后可以很方便的扩展识别的格式,那么我声明一个接口:
public   interface   IMediaFormat
{
string   Extension   {get;}
Decoder   GetDecoder();
}
这个接口中包含一个Extension属性,这个属性返回支持的扩展名,另一个方法返回一个解码器的对象(这里我假设了一个Decoder的类,这个类提供把文件流解码的功能,扩展插件可以派生之),通过解码器对象我就可以解释文件流。
那么我规定所有的解码插件都必须派生一个解码器,并且实现这个接口,在GetDecoder方法中返回解码器对象,并且将其类型的名称配置到我的配置文件里面。
这样的话,我就不需要在开发播放器的时侯知道将来扩展的格式的类型,只需要从配置文件中获取现在所有解码器的类型名称,而动态的创建媒体格式的对象,将其转换为IMediaFormat接口来使用。

这就是一个反射的典型应用。


4
、如何使用反射获取类型
       
首先我们来看如何获得类型信息。
       
获得类型信息有两种方法,一种是得到实例对象
       
这个时侯我仅仅是得到这个实例对象,得到的方式也许是一个object的引用,也许是一个接口的引用,但是我并不知道它的确切类型,我需要了解,那么就可以通过调用System.Object上声明的方法GetType来获取实例对象的类型对象,比如在某个方法内,我需要判断传递进来的参数是否实现了某个接口,如果实现了,则调用该接口的一个方法:

public   void   Process(   object   processObj   )
{
Type   t   =   processsObj.GetType();
if(   t.GetInterface(“ITest”)   !=null   )
                    …
}

       
另外一种获取类型的方法是通过Type.GetType以及Assembly.GetType方法,如:
              Type   t   =   Type.GetType(“System.String”);
       
需要注意的是,前面我们讲到了命名空间和装配件的关系,要查找一个类,必须指定它所在的装配件,或者在已经获得的Assembly实例上面调用GetType
       
本装配件中类型可以只写类型名称,另一个例外是mscorlib.dll,这个装配件中声明的类型也可以省略装配件名称(.Net装配件编译的时候,默认都引用了mscorlib.dll,除非在编译的时候明确指定不引用它),比如:
          System.String
是在mscorlib.dll中声明的,上面的Type   t   =   Type.GetType(System.String)是正确的
          System.Data.DataTable
是在System.Data.dll中声明的,那么:
Type.GetType(
System.Data.DataTable)就只能得到空引用。
         
必须:
Type   t   =   Type.GetType("System.Data.DataTable,System.Data,Version=1.0.3300.0,   Culture=neutral,   PublicKeyToken=b77a5c561934e089");
         
这样才可以,大家可以看下面这个帖子:
                http://expert.csdn.net/Expert/topic/2210/2210762.xml?temp=.1919977
          qqchen
的回答很精彩


5
、如何根据类型来动态创建对象
        System.Activator
提供了方法来根据类型动态创建对象,比如创建一个DataTable

Type   t   =   Type.GetType("System.Data.DataTable,System.Data,Version=1.0.3300.0,   Culture=neutral,   PublicKeyToken=b77a5c561934e089");

DataTable   table   =   (DataTable)Activator.CreateInstance(t);

    例二:根据有参数的构造器创建对象
namespace   TestSpace 
 {
  public   class   TestClass
      {
      private   string   _value;
       public   TestClass(string   value)  
     {
       _value=value;
       }
  }
}

Type   t   =   Type.GetType(“TestSpace.TestClass”);
Object[]   constructParms   =   new   object[]   {
hello};   //构造器参数
TestClass   obj   =   (TestClass)Activator.CreateInstance(t,constructParms);

把参数按照顺序放入一个Object数组中即可


6
、如何获取方法以及动态调用方法
namespace   TestSpace
{
      public   class   TestClass   {
          private   string   _value;
          public   TestClass()   {
          }
          public   TestClass(string   value)   {
                _value   =   value;
          }

          public   string   GetValue(   string   prefix   )   {
           if(   _value==null   )
           return   "NULL";
           else
             return   prefix+"   :   "+_value;
            }

            public   string   Value   {
set   {
_value=value;
}
get   {
if(   _value==null   )
return   "NULL";
else
return   _value;
}
            }
      }
}

        上面是一个简单的类,包含一个有参数的构造器,一个GetValue的方法,一个Value属性,我们可以通过方法的名称来得到方法并且调用之,如:

//获取类型信息
Type   t   =   Type.GetType("TestSpace.TestClass");
//
构造器的参数
object[]   constuctParms   =   new   object[]{"timmy"};
//
根据类型创建对象
object   dObj   =   Activator.CreateInstance(t,constuctParms);
//
获取方法的信息
MethodInfo   method   =   t.GetMethod("GetValue");
//
调用方法的一些标志位,这里的含义是Public并且是实例方法,这也是默认的值
BindingFlags   flag   =   BindingFlags.Public   |   BindingFlags.Instance;
//GetValue
方法的参数
object[]   parameters   =   new   object[]{"Hello"};
//
调用方法,用一个object接收返回值
object   returnValue   =   method.Invoke(dObj,flag,Type.DefaultBinder,parameters,null);

        属性与方法的调用大同小异,大家也可以参考MSDN

7、动态创建委托
       
委托是C#中实现事件的基础,有时候不可避免的要动态的创建委托,实际上委托也是一种类型:System.Delegate,所有的委托都是从这个类派生的
        System.Delegate
提供了一些静态方法来动态创建一个委托,比如一个委托:

namespace   TestSpace   {
      delegate   string   TestDelegate(string   value);
      public   class   TestClass   {
public   TestClass()   {
                  }
                  public   void   GetValue(string   value)   {
                          return   value;
                  }
        }
}

使用示例:
TestClass   obj   =   new   TestClass();

//获取类型,实际上这里也可以直接用typeof来获取类型
Type   t   =   Type.GetType(“TestSpace.TestClass”);
//
创建代理,传入类型、创建代理的对象以及方法名称
TestDelegate   method   =   (TestDelegate)Delegate.CreateDelegate(t,obj,”GetValue”);

String   returnValue   =   method(“hello”);

posted @ 2010-04-19 11:06 beibei11 阅读(158) | 评论(0) | 编辑

  2010418

c#连接数据库和更新数据库操作

对数据库的操作总体可以分为两类:查询(select)和更新(insert,delete,update)。为什么这样来分呢?仔细看看两类的区别,select只是从数据库中将数据拿出来使用,而其余三者都会对数据库的物理数据进行修改。capucivar在上篇文章中已经对数据库的查询操作进行了详细的阐述。这篇文章将接着阐述更新数据。

  更新数据库信息首先是连接数据库,这个capucivar在《C#连接数据库之查询数据库》中已有介绍了。对数据库的更新需要一个对象:OleDbCommand。该对象表示要对数据源执行的SQL语句或存储过程。

  这个对象有三个属性:1CommandText表示要设置命令的文本;2Connection表示要设置命令的连接;3CommandType表示设置命令的类型,默认的是Sql语句(但如果不是执行sql语句,就一定要指定命令的类型)。OleDbCommand对象设置好以后,就该执行sql语句了。方法ExecuteNonQuery()就是执行sql语句。如果记不住这个方法,教你一个简单的记法:将“ExecuteNonQuery”单词分为三部分,就是“执行不查询”,那就是更新数据了。

  下面就做一个例子熟悉对数据库的更新:

  先使用Visual Studio2005做出如下界面:

 

界面做好以后就相当于做了一个空壳子。接下来就是往里边添加事件了。我们还要借用上篇文章中的ConnDb类,在该类里添加一个方法:update()对数据库进行更新,该方法里有一个参数string sql

public class ConnDb

    { OleDbConnection conn = null;//连接数据库的对象

//下面是构造函数连接数据库

        public ConnDb()

        { if (conn==null)//判断连接是否为空

            {  conn = new OleDbConnection();

            conn.ConnectionString="provider=sqloledb.1;data source=.;initial catalog=capucivar;user id=sa;pwd=";//连接数据库的字符串 }

            if (conn.State == ConnectionState.Closed)

            {  conn.Open();//打开数据库连接

            } }

//下面这个方法是从数据库中查找数据的方法

        public DataSet query(string sql)

        { DataSet ds = new DataSet();//DataSet是表的集合

            OleDbDataAdapter da = new OleDbDataAdapter(sql,conn);//从数据库中查询

            da.Fill(ds);//将数据填充到DataSet

            connClose();//关闭连接

            return ds;//返回结果

        }

//下面的方法是对数据库进行更新

        public int update(string sql)

        {OleDbCommand oc = new OleDbCommand();//表示要对数据源执行的SQL语句或存储过程

            oc.CommandText = sql;//设置命令的文本

            oc.CommandType = CommandType.Text;//设置命令的类型

            oc.Connection = conn;//设置命令的连接

            int x=oc.ExecuteNonQuery();//执行SQL语句

            connClose();//关闭连接

            return x;   //返回一个影响行数

        }

//下面的connClose()方法是关闭数据库连接

        public void connClose()

        { if (conn.State == ConnectionState.Open)

            {//判断数据库的连接状态,如果状态是打开的话就将它关闭

                conn.Close();    }   }  }

 

对数据库的操作类写好了。然后就来实现增删改的功能:

  理一下思路,先添加一个用户,如何编写代码:1、得到客户所填的数据(用户名和密码);2、编写insert语句,将用户信息通过ConnDb()类添加到数据库中;3、返回一个影响行数以便通知客户执行是否成功。代码如下:

private void add_but_Click(object sender, EventArgs e)

        {//按钮单击事件

//得到用户所填的用户名和密码

string uname = this.uname_text.Text;            string upass = this.upass_text.Text;

            string sql = string.Format("insert into users values('{0}','{1}')",uname,upass);//拼写sql语句将该用户信息插入到数据库中

            int x = new Db.ConnDb().update(sql);//通过ConnDb()对象的update()方法执行sql语句并返回一个影响行数

            if (x > 0)

            {//如果影响行数大于0则说明插入成功,否则的话插入失败

                MessageBox.Show("添加成功!");

            } else {

                MessageBox.Show("添加失败!");

            } }

  添加一个用户之后,在右边的listBox中显示出来:

public void refurbish()

    { string sql = "select * from users";//sql语句查询数据

       DataSet ds = new Db.ConnDb().query(sql);//查询返回一个DataSet

        this.listBox1.DisplayMember = "username";//listBox中要显示的列

   this.listBox1.DataSource=ds.Tables[0];// listBox的数据源

 }

 

执行结果如下:

 

而当客户选中右边的listBox中的一个选项时,可以进行相应的删除或修改。删除的代码如下:

private void del_but_Click(object sender, EventArgs e)

        {string uname = this.listBox1.Text;//得到listBox中所选的值

            string sql = string.Format("delete from users where username='{0}'",uname);//拼写sql语句删除用户

            int x = new Db.ConnDb().update(sql);//调用update()方法返回影响行数

            if (x > 0)

            {//根据返回的影响行数判断删除是否成功

                MessageBox.Show("删除成功!");

            } else{

          MessageBox.Show("删除失败!");   }  }

  删除之后的结果如下:

 

在点击“更新”按钮之后,应该弹出一个窗口显示客户所选用户的信息供客户更新。更新的代码如下:

  private void upa_but_Click(object sender, EventArgs e)

  {  string uname = this.listBox1.Text;//得到listBox中所选的用户信息

new upd(uname).ShowDialog();//弹出要更新窗口upd.cs }

  upd.cs的代码如下:

    public partial class upd : Form

    {  public upd()//无参构造函数

        {  InitializeComponent();  }

        public upd(string uname)//有参构造函数

        { InitializeComponent();

        this.uname_text.Text = uname;//将用户名放到文本框

            string sql = string.Format("select * from users where username='{0}'", uname);//拼写sql语句通过用户名查找用户的信息

            DataSet ds = new Db.ConnDb().query(sql);

//下面得到结果集中的信息分别放至相应文本框中

            this.uid_text.Text = ds.Tables[0].Rows[0][0].ToString();            this.upass_text.Text = ds.Tables[0].Rows[0][2].ToString();

        }

        private void button1_Click(object sender, EventArgs e)//点击“确认修改”按钮所响应的事件

    {int uid = Convert.ToInt32(this.uid_text.Text);//得到uid

            string uname = this.uname_text.Text;//得到用户名

            string upass = this.upass_text.Text;//得到用户密码

            string sql = string.Format("update users set username='{0}',userpass='{1}' where uid={2}",uname,upass,uid);//拼写一个修改sql语句

           int x = new Db.ConnDb().update(sql);//返回所受影响行数

            if (x > 0)

            {//根据影响行数判断修改是否成功

                MessageBox.Show("修改成功!");

                this.Visible = false;//将该页面隐藏

            } else  {

                MessageBox.Show("修改失败!");

                return; } }

        private void button2_Click(object sender, EventArgs e){//点击“取消”按钮所响应的事件

            this.Visible = false;//将该页面隐藏

        }  }}

 

  修改的结果如下:

 

在每次对数据库进行修改之后,界面右边的listBox中的数据就会更新一次,所以每次对数据库操作之后都应该调用refurbish()方法。一个简单的使用C#对数据库进行增删改查的代码就写完了。代码写的很简单,只是完成了最简单的增删改查功能,可以将上述的代码更加完善。

 

Copy Code

protected override void timer1_Tick(object sender, System.EventArgs e){   // Calls the Timer1_Tick method of ctlClock.   base.timer1_Tick(sender, e);   // Checks to see if the Alarm is set.   if (AlarmSet == false)      return;   else      // If the date, hour and minute of the alarm time are the same as      // now, flash!    {      if (AlarmTime.Date == DateTime.Now.Date && AlarmTime.Hour ==          DateTime.Now.Hour && AlarmTime.Minute == DateTime.Now.Minute)      {         // Makes lblAlarmVisible, and changes the backcolor based on         // the value of blnColorTicker. The backcolor of the label          // will flash once per tick of the clock.         lblAlarm.Visible = true;         if (blnColorTicker == false)          {            lblAlarm.BackColor = Color.Red;            blnColorTicker = true;         }         else         {            lblAlarm.BackColor = Color.Blue;            blnColorTicker = false;         }      }      else      {         // Once the alarm has sounded for a minute, the label is made          // invisible again.         lblAlarm.Visible = false;      }   }}

Copy Code

private bool blnColorTicker;

Copy Code

private DateTime dteAlarmTime;private bool blnAlarmSet;// These properties will be declared as public to allow future // developers to access them.public DateTime AlarmTime{   get   {      return dteAlarmTime;   }   set   {      dteAlarmTime = value;   }}public bool AlarmSet{   get   {      return blnAlarmSet;   }   set   {      blnAlarmSet = value;   }}

你可能感兴趣的:(C#)