A kontrol elkészítése
A kontrolunk képes tehát imitálni egy működő analóg időmérőt, mely rendelkezik másodpercmutatóval is. A kontrol létrehozásakor a megvalósító osztály tulajdonságait bővítjük a ISupportinitialize interfész jellemzőivel, így az osztálydeklaráció a következőképpen fest:
public class TimerControl : System.Windows.Forms.Control, ISupportInitialize
{
...
}
Az osztály rendelkezik néhány tagváltozóval, illetve objektummal, melyeket felhasználunk a munka során.
private Timer timer = new Timer();
private bool initializing = false;
A timer tagobjektum fogja minden másodpercben frissíteni a képet, vagyis meghívni a kontrolt újrarajzoló metódust.
A kontrol konstruktorában beállítunk néhány jellemzőt, melyek a kontrol vizuális megjelenítését befolyásolják.
public TimerControl()
{
this.SetStyle(ControlStyles.DoubleBuffer, true);
this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
this.SetStyle(ControlStyles.ResizeRedraw, true);
}
A fent említett interfész tulajdonságainak használatához két metódusát mindenképpen meg kell valósítanunk az osztály kódjában. Az első a BeginInit metódus, melyben megadhatunk bizonyos ellenőrző kódokat a kontrol működését tekintve. Most azonban csak arra szolgál, hogy jelezzük, az inicializáció megtörtént, beállítva a tagváltozónkat.
void ISupportInitialize.BeginInit()
{
initializing = true;
}
Az EndInit metódus viszont ennél hasznosabb funkcióval rendelkezik. Amennyiben a kontrol osztályának konstruktorában helyezzük el a Timer objektum inicializáló kódját, az óra szerkesztési időben is „járni” fog, vagyis a kontrol minden másodpercben frissül, használva a processzoridőt. Ezt elkerülendő, az EndInit metódusban megvizsgáljuk, hogy a kontrol szerkesztési időben van-e, és ha nem, akkor inicializáljuk a Timer objektumot:
void ISupportInitialize.EndInit()
{
if( !this.DesignMode )
{
timer.Interval = 1000;
timer.Tick += new System.EventHandler(this.timer_Ticker);
timer.Enabled = true;
}
initializing = false;
}
A Timer másodpercenként meghívja a kontrolt frissítő metódust a következőképpen:
private void timer_Ticker(object sender, System.EventArgs e)
{
this.Refresh();
}
Vagyis a WM_Paint üzenet célba ér. Ennek kezelésére szolgál az OnPaint metódus, melyben elhelyeztük az óra megjelenítését végző kódsorokat.
A metódus elején deklaráljuk azokat az objektumokat – többek közt a Graphics objektumot - melyre szükségünk van. A művelet az óratest kirajzolásával indul.
protected override void OnPaint(PaintEventArgs pe)
{
Graphics g = pe.Graphics;
Size clientSize = this.ClientRectangle.Size;
int xRadius = clientSize.Width/2;
int yRadius = clientSize.Height/2;
Deklarálnunk kell a Pen, és a SolidBrush objektumokat a rajzoláshoz.
...
Pen allPen = new Pen(Color.Black, 2);
SolidBrush allBrush = new SolidBrush(Color.White);
Először megrajzoljuk az óratest körvonalait:
g.DrawPie(allPen, allPen.Width, allPen.Width, clientSize.Width - allPen.Width * 2, clientSize.Height - allPen.Width * 2,0.0F,360.0F);
Majd kitöltjük az ellipszis területét fehér színnel.
g.FillPie(allBrush, allPen.Width, allPen.Width, clientSize.Width - allPen.Width * 2, clientSize.Height - allPen.Width * 2,0.0F,360.0F);
Az óra három karjának megrajzolását három művelet-csoport végzi el. Az első az órakart rajzolja. Minden műveletben először meghatározzuk, hogy hol legyen az adott kar kezdőpontja.
degrees = (90.0 - ((DateTime.Now.Hour/3.0) + (DateTime.Now.Minute/180.0)) * 90.0) * (Math.PI/180.0);
xPos = (int)Math.Round((xRadius/3.0) * Math.Cos(degrees));
yPos = (int)-(Math.Round((yRadius/3.0) * Math.Sin(degrees)));
Majd megrajzoljuk azt a Graphics objektum DrawLine metódusával.
...
g.DrawLine(allPen, xRadius, yRadius, xPos + xRadius, yPos + yRadius);
A többi kar megrajzolása hasonló műveletek eredménye.
A következő művelet az óralap számainak megrajzolása.
for(int i=1;i<13;i++)
{
degrees = i * 30;
xNum = (float)Math.Round(Math.Sin((degrees/180) * Math.PI) * (xRadius - 15));
yNum = (float)Math.Round(-Math.Cos((degrees/180) * Math.PI) * (yRadius - 15));
g.DrawString(i.ToString(),f,b,xNum+xRadius-7,yNum+yRadius-7);
}
A művelet végén meg kell hívni az ősosztály OnPaint metódusát is.
Felhasználása előtt a kontrolt fel kell tenni a ToolBox-ra a szokásos módon: kattintsunk a ToolBox valamely lapján az egér jobb gombjával, majd a megjelenő menüből válasszuk ki a Customize ToolBox pontot, a megjelenő ablakban a .NET Frameworks Components fület. A Browse gombbal keressük elő az imént létrehozott .DLL-t.
A kontrol felhasználása
A kontrolt egyszerűen felhelyeztük a TimerTest alkalmazás Form1 űrlapjára, majd a kívánt méretre igazítottuk. A Form felületén elhelyezett jelölőnégyzettel futási időben is megadhatjuk, hogy látszódjon a digitális időjelzés, vagy sem.