Master C# Logo banner
Welcome to MasterCSharp.com - Master C#, the easy way... - by Saurabh Nandu

 


World Time Client Part2 : Building the User Controls

Add Comment
 

 
<div align="center"> <table width="90%" cellpadding=1 cellspacing=2 class="outline"> <tr> <td width="40%" class="outline"><b>Download</b></td> <td width="10%" class="outline"><b>SDK</b></td> </tr> <tr> <td width="40%" class="outline"> <a class="wbox" href="../../file/worldtimeclient-1.zip"> worldtimeclient-1.zip</a> (37kb)</td> <td width="10%" class="outline">Beta2</td> </tr> </table> </div> <p> <span class=wboxheado>Introduction</span><br> In the <a class="wbox" target="_blank" href="article.aspx?ArticleID=72&&TopicID=8"> previous</a> part, I covered the installation and architecture of the <b>World Time Client</b> application. In this part I will show you how to create the <i>DateTimeDisplayControl</i> User Control which is used to display the world clocks. Please refer to the earlier article to understand the application architecture. <span class=wboxheado></p> <p>A) DateTimeDisplayControl</span> - This control is used to create the UI for displaying the city/area name, date and current time. Since a different instance of this control will be used to display individual clocks I implement it as a <i>User Control</i> so that it becomes easier to use later on. </p> <p><span class=wboxhead>Building the User Control</span><br> 1) Let's straight start with the tutorial, fire-up VS.NET Beta2, if its not already started and create a new <b>Windows Control Library Project</b>. Select the project name as <b>DateTimeDisplayControl</b> and enter the correct location where you want to create the project. Finally, click <b>OK</b> to let VS.NET create the new project for you and the default <b>UserControl1.cs</b> file will open up in the VS.NET <i>Designer window</i>. To give our source code file a new name, go to <i>Solution Explorer</i> window and select the file <b>UserControl1.cs</b> and press the <i>F2</i> key and then rename the file to <b>DateTimeDisplayControl.cs</b>. <br> Next, select the User Control in the <i>Designer</i> window and press the <i>F7</i> key to switch to <i>Code window</i>. In the <i>Code window</i> rename the namespace of the control from <b>DateTimeDisplayControl</b> to <b>MasterCSharp.UserControl</b> and also rename the class <b>UserControl1</b> to <b>DateTimeDisplayControl</b>. Remember to rename the class constructor similarly!! Next add a private <i>DateTime</i> variable that will handle the control's date/time. <br> i.e Add the following line after the class definition.<br> <br> <span class=codetext>private DateTime controlTime;</span></p> <p align="center"> <img border="0" src="../../IMG/worldtimeclient2_1.gif" width="531" height="364"><br> <b>Figure 1:</b> Create new Windows Control Library Project</p> <p>2) Switch back to the <i>Design window</i> and select the User Control then press <i>F4</i> key to pull-out the <i>Properties window</i> for the User Control. Change the following properties of the User Control from the <i>Properties window</i>. One thing you should note while creating Windows Forms that will be hosted from within Internet Explorer is that the <i>Colors</i> you use should <b>not</b> be set to Control Colors since they get rendered depending upon the colors of the HTML document hosting the Control and not upon the Operating System running the control! Does that make sense ?? ?? </p> <div align="center"> <table cellspacing=2 cellpadding=1 width="75%" class="outline" > <tr> <td width="50%" class="outline"><b>Property</b></td> <td width="50%" class="outline"><b>New Value</b></td> </tr> <tr> <td width="50%" class="outline">BackColor</td> <td width="50%" class="outline">DarkKhaki</td> </tr> <tr> <td width="50%" class="outline">Name</td> <td width="50%" class="outline">DateTimeDisplayControl</td> </tr> <tr> <td width="50%" class="outline">Size</td> <td width="50%" class="outline">130 , 120</td> </tr> </table> </div> <p>3) Press <i>Ctrl + Alt + X</i> to pull-out the <i>Toolbox window</i>. Drag a <i>Label </i>control from the <i>Toolbox</i> and place it on the User Control. While the label is selected in the <i>Design window</i> press <i>F4</i> key to bring-out the <i>Properties window</i> for the Label control. Change the following properties for the selected label control. Since this label will be used to display the city/area name we rename the variable as <b>cityLabel</b>.<p>&nbsp;<div align="center"> <center> <table width="75%" cellpadding=1 cellspacing=2 class="outline"> <tr> <td width="50%" class="outline"><b>Property</b></td> <td width="50%" class="outline"><b>New Value</b></td> </tr> <tr> <td width="50%" class="outline">BackColor</td> <td width="50%" class="outline">MidnightBlue</td> </tr> <tr> <td width="50%" class="outline">BorderStyle</td> <td width="50%" class="outline">FixedSingle</td> </tr> <tr> <td width="50%" class="outline">FlatStyle</td> <td width="50%" class="outline">Flat</td> </tr> <tr> <td width="50%" class="outline">Font</td> <td width="50%" class="outline">Veranda, 8.25, Bold (The font size in the Font Properties dialog is 8).</td> </tr> <tr> <td width="50%" class="outline">ForeColor</td> <td width="50%" class="outline">Orange</td> </tr> <tr> <td width="50%" class="outline">Text</td> <td width="50%" class="outline">(empty the textbox)</td> </tr> <tr> <td width="50%" class="outline">TextAlign</td> <td width="50%" class="outline">MiddleCenter</td> </tr> <tr> <td width="50%" class="outline">Name</td> <td width="50%" class="outline">cityLabel</td> </tr> <tr> <td width="50%" class="outline">Location</td> <td width="50%" class="outline">8, 8</td> </tr> <tr> <td width="50%" class="outline">Size</td> <td width="50%" class="outline">114, 24</td> </tr> </table> </center> </div> <p>4) Follow the above <i>Step 3</i> and drag another <i>Label</i> on the User Control this label will be used to display the <b>Date</b> for the city/area. Change the following properties for this label from the <i>Properties window</i>.<p>&nbsp;<div align="center"> <table width="75%" cellpadding=1 cellspacing=2 class="outline"> <tr> <td width="50%" class="outline"><b>Property</b></td> <td width="50%" class="outline"><b>New Value</b></td> </tr> <tr> <td width="50%" class="outline">BackColor</td> <td width="50%" class="outline">MidnightBlue</td> </tr> <tr> <td width="50%" class="outline">BorderStyle</td> <td width="50%" class="outline">FixedSingle</td> </tr> <tr> <td width="50%" class="outline">FlatStyle</td> <td width="50%" class="outline">Flat</td> </tr> <tr> <td width="50%" class="outline">Font</td> <td width="50%" class="outline">Veranda, 8.25, Bold (The font size in the Font Properties dialog is 8).</td> </tr> <tr> <td width="50%" class="outline">ForeColor</td> <td width="50%" class="outline">Orange</td> </tr> <tr> <td width="50%" class="outline">Text</td> <td width="50%" class="outline">(empty the textbox)</td> </tr> <tr> <td width="50%" class="outline">TextAlign</td> <td width="50%" class="outline">MiddleCenter</td> </tr> <tr> <td width="50%" class="outline">Name</td> <td width="50%" class="outline">dateLabel</td> </tr> <tr> <td width="50%" class="outline">Location</td> <td width="50%" class="outline">8, 40</td> </tr> <tr> <td width="50%" class="outline">Size</td> <td width="50%" class="outline">114, 40</td> </tr> </table> </div> <p>5) Drag one more <i>Label</i> from the <i>Toolbox</i> as shown in <i>Step 3</i>, this label will be used to display the <b>Time</b> of the city/area. As usual pull-out the <i>Properties window</i> for this label and make the following changes.<p>&nbsp;<div align="center"> <table width="75%" class="outline" cellpadding=1 cellspacing=2> <tr> <td width="50%" class="outline"><b>Property</b></td> <td width="50%" class="outline"><b>New Value</b></td> </tr> <tr> <td width="50%" class="outline">BackColor</td> <td width="50%" class="outline">MidnightBlue</td> </tr> <tr> <td width="50%" class="outline">BorderStyle</td> <td width="50%" class="outline">FixedSingle</td> </tr> <tr> <td width="50%" class="outline">FlatStyle</td> <td width="50%" class="outline">Flat</td> </tr> <tr> <td width="50%" class="outline">Font</td> <td width="50%" class="outline">Veranda, 8.25, Bold (The font size in the Font Properties dialog is 8).</td> </tr> <tr> <td width="50%" class="outline">ForeColor</td> <td width="50%" class="outline">Orange</td> </tr> <tr> <td width="50%" class="outline">Text</td> <td width="50%" class="outline">(empty the textbox)</td> </tr> <tr> <td width="50%" class="outline">TextAlign</td> <td width="50%" class="outline">MiddleCenter</td> </tr> <tr> <td width="50%" class="outline">Name</td> <td width="50%" class="outline">timeLabel</td> </tr> <tr> <td width="50%" class="outline">Location</td> <td width="50%" class="outline">8, 88</td> </tr> <tr> <td width="50%" class="outline">Size</td> <td width="50%" class="outline">114, 24</td> </tr> </table> </div> <p align="center"> <img border="0" src="../../IMG/worldtimeclient2_2.gif" width="199" height="165"><br> <b>Figure 2:</b> DateTimeDisplayControl Design window.<p align="left">6) This control will be self-sufficient to correctly update its date and time once they have been set by the parent. To regularly update the Control's UI at specific time spans we use the <b>Timer</b> component. Since we are creating a <i>Windows Forms Control</i> we use the <b>Timer</b> defined within the <b>System.Windows.Forms</b> namespace which has been optimized to work with GUI applications. The <i>Timer</i> raises the <b>Tick</b> event after the specified interval (in milliseconds, 1 Second = 1000 Milliseconds) has elapsed, you can handle this event and perform your task after the elapce of the specified time span.&nbsp; Pull-Out the <i>Toolbox window</i> and under the <b>Windows Forms</b> tab search for the <b>Timer</b> component and drag it onto the Control. Remember that the <i>Timer</i> is a <b>Component</b> and <b>not</b> a <b>Control</b>, so does not have UI! VS.NET will update the <i>Designer window</i> and show the <i>Timer</i> Component below the <i>Designer window</i>. Select the <i>Timer</i> component and press the <i>F4</i> key to bring out the <i>Timer</i> Properties. Change the following properties in the <i>Properties window</i>.&nbsp; <P>&nbsp;<div align="center"> <table width="75%" cellpadding=1 cellspacing=2 class="outline"> <tr> <td width="50%" class="outline"><b>Property</b></td> <td width="50%" class="outline"><b>New Value</b></td> </tr> <tr> <td width="50%" class="outline">Interval</td> <td width="50%" class="outline">1000</td> </tr> <tr> <td width="50%" class="outline">Name</td> <td width="50%" class="outline">controlTimer</td> </tr> </table> </div> <p align="left">7) The above <i>Step 6</i> completed the Controls/Component adding part of the User Control Project. Now I move on to adding code that makes the control tick! I hope you're ticking along too :).<br> Double-Click the <b>controlTimer</b> component from below the <i>Designer window</i> so that VS. Net automatically wires-up the <i>Tick</i> event of the component as well as it creates a empty event-handling method called <b>controlTimer_Tick</b> for you in the <i>Code window</i>. Since my control should update its date and time every second to emulate a real clock, in the above step I had setup the <i>Timer</i> component's <b>Interval</b> property to <b>1000</b> so that the <i>Tick</i> event is raised <i>every second</i>. In the event-handling method I just update the date and time labels to reflect the new date and time and of course we increment the <b>controlTime</b> variable (type DateTime)&nbsp; by <i>one</i> second. Below is the complete implementation of the event-handling method. <p align="left">&nbsp;<table width="100%" cellspacing=2 cellpadding=1 class="code"> <tr> <td width="100%"><pre>private void controlTimer_Tick(object sender, System.EventArgs e) { <font color="#0000CC">//Add a second to the time</font> controlTime = controlTime.AddSeconds(1); <font color="#0000CC">//Display the Date and format it properly to fit the control space</font> dateLabel.Text = controlTime.ToLongDateString().Replace(&quot;,&quot;,&quot;\r\n&quot;); <font color="#0000CC">//Display the time</font> timeLabel.Text = controlTime.ToLongTimeString(); }</pre></td> </tr> </table> <p align="left">8) Next I add two more helper methods, <b>StartTimer</b> and <b>StopTimer</b> which as their name suggests start the control ticking and stop it from ticking respectively. Also the <i>StopTimer</i> method is used <b>Dispose</b> off the <i>Timer</i> component since its a costly resource and it should be disposed off as soon as its not needed. Below is the implementation of these methods along with a few helper properties which completes the implementation of this User Control.<p align="left">&nbsp;<table cellpadding="1" cellspacing="2" width="100%" class="Code"> <tr> <td width="100%"><pre>public string City { get { return cityLabel.Text; } set { cityLabel.Text = value; } } public string Date { get { return controlTime.ToLongDateString(); } } public string Time { get { return controlTime.ToLongTimeString(); } } public void StartTimer(DateTime newTime) { <font color="#0000CC">//Set the Date Time</font> this.controlTime = newTime; <font color="#0000CC">//Start the Timer</font> this.controlTimer.Start(); } public void StopTimer() { this.controlTimer.Stop(); <font color="#0000CC">//Release the resource</font> this.controlTimer.Dispose(); }</pre></td> </tr> </table> <p align="left">9) Its a good idea to <i>version</i> the components from the beginning particularly when you want it to be downloaded dynamically from the Internet. So <i>double-click</i> the <b>AssemblyInfo.cs</b> file in the <i>Solution Explorer</i> to open the file in <i>Code window</i> and modify the following attributes as given below, feel free to remove the additional attributes that are not used.<p align="left">&nbsp;<table cellpadding="1" cellspacing="2" width="100%" class="code"> <tr> <td width="100%">[assembly: AssemblyTitle(&quot;DateTimeDisplayControl&quot;)]<br> [assembly: AssemblyDescription(&quot;This Control is used to display the City name, Date and Time&quot;)]<br> [assembly: AssemblyCompany(&quot;MasterCSharp.com&quot;)]<br> [assembly: AssemblyVersion(&quot;1.1.0.0&quot;)]</td> </tr> </table> <p align="left">10) Once you have finished the above steps correctly the moment of truth arrives, press <b>Ctrl+Shift+B</b> to <b>Build/Compile</b> the project. If you ticked along synchronously then definitely you should see the message &quot;<i>Build: 1 succeeded, 0 failed, 0 skipped</i>&quot; in the <b>Output window</b>!<br> At this point if you wish you could build a small test Windows Forms application to test the functionality of this User Control, but I will refrain from explaining that since I still have a long way to go before completing this part...<p align="left"><span class=wboxheado>Adding Toolbox Image</span><br> This part is a bit off-topic from my example ( its fun stuff :) ), but I have been overwhelmed with people asking me <i>how they could display a custom image for their User Controls when its added in the VS.NET Toolbox window</i>. So this section is the '<b>Users Demand</b>' section, particularly in the case of my example it would be a bad idea to do this since it would increase the size of the assembly and I would like to keep that in control since the assembly is downloaded over the Internet!! In the actual implementation of this User Control you can skip this part if you like!<p align="left">Just incase you are unaware, VS.NET's <i>Toolbox</i> is very customizable and you can freely add your own components and controls to it. To add a component/control <i>right-click</i> the <i>Toolbox window</i> and select <b>Customize Toolbox </b>from the context menu. The dialog that show's allows you to select a wide array of <i>COM</i> and <i>.NET components</i> that you could add to your <i>Toolbox</i>. If you would go to the <b>.NET Framework Components</b> tab, click <b>Browse</b> and select the <b>DateTimeDisplayControll.dll</b> User Control that we just compiled you will see a screen as shown below.<p align="center"> <img border="0" src="../../IMG/worldtimeclient2_3.gif" width="571" height="396"><br> <b>Figure 3:</b> Customize Toolbox dialog<p align="left">The summary of the selected assembly shown above (Figure 3) you can see that VS.NET has assigned a default icon (<img border="0" src="IMG/worldtimeclient2_4.gif" width="18" height="16">) for your control/component, this same icon will be used for displaying your control/component in the <i>Toolbox</i>. This might not be a problem in all cases, but if you are a component/control vendor then definitely you would want to replace it with something that describes your controls/components more better!! As of Beta2 there is not much public documentation documenting this feature, but since MS has made its .NET Framework Classes extensible enough for any third-party tools creator to easily create tools like VS.NET without defining a specific API to get VS.NET like <i>design-time</i> support, its a matter of diving deeper into the Framework class documentation to find this functionality. I am summarizing my findings below! A special thanks to <b>Mr. Kousay Alani</b> who's question on the MS Newsgroup prompted me to dive deeper into this and the solution was found in 2 parts one by me, one by Mr. Kousay Alani. <p align="left">1) The first step is to annotate the User Control class with the <b>ToolboxBitmapAttribute</b> from the <b>System.Drawing</b> namespace. One of the constructors of this class takes the <b>Type</b> to use while finding the bitmap to be used for displaying in the <i>Toolbox</i>. Following code snip shows how to annotate a class with this attribute. You will observe that I have used the <b>typeof</b> keyword and passed the <b>Bitmap</b> (<b>System.Drawing</b> namespace) <b>Type</b> to the attribute's constructor. This will remain constant for all your User Control implementations.<p align="left">&nbsp;<table cellpadding="1" cellspacing="2" width="100%" class="code"> <tr> <td width="100%"> <pre>namespace MasterCSharp.UserControl { [ToolboxBitmap(typeof(Bitmap))] public class DateTimeDisplayControl : System.Windows.Forms.UserControl { <font color="#0000CC">//class implementation....</font> } }</pre> </td> </tr> </table> <p align="left">2) Now go to the <b>Project</b> menu and select <b>Add New Item</b>. Select <b>Bitmap</b> from the the <b>Resources</b> tab, rename the file as <b>DateTimeDisplayControl.bmp</b> and click <b>OK</b>. This seemed trivial, right?? Well this was one of the turns where many get stranded!! The file name of the <i>Bitmap</i> should correspond with the class name of the Control/Component that has been annotated by the <i>ToolboxBitmap</i> Attribute for this to work!! So be extra careful to see to it that you match the bitmap and class name when you are providing your custom implementation!<p align="left">3) Now select the bitmap from the <i>Bitmap Designer window</i> and press the <i>F4</i> key to pull-out the <i>Properties window</i> for the bitmap. Change the <b>height</b> and <b>width</b> property to <b>16</b> each and make sure that the <b>Colors</b> property is set to <b>16 Colors</b>. This is because the preferable image attributes are 16x16x16 (Height, Width and Color). Although you could use a high color Bitmap also, but if you increase the size of the bitmap from 16x16 then is not rendered correctly in the VS.NET <i>Toolbox</i>. Once the properties have been set, feel free to design the Icon in the way you want, below is the design I have created very artistic, isn't it?? :). One more notable point is that the green color <b>RGB (0,255,0)</b> is used as a <b>transparency</b> color and is replaced by the control color in the VS.NET Toolbox.<p align="center"> <img border="0" src="../../IMG/worldtimeclient2_5.gif" width="175" height="130"><br> <b>Figure 4:</b> Bitmap Design window<p align="left">4) Go to the <i>Solutions Explorer</i> and select the <i>DateTimeDisplayControl.bmp</i> item from it and press the <i>F4</i> key to bring out the <i>Properties Explorer</i> for the Bitmap file. Note that this is different from the Bitmap properties we worked on in the above step. From the <b>Build Action</b> property select <b>Embed Resource</b>, so that the bitmap file is embed into your assembly as a resource.<p align="left">5) Finally, <i>right-click</i> on the <i>DateTimeDisplayControl Project</i> in the <i>Solution Explorer</i> and select <b>Properties</b> from the context menu. In the <b>Properties</b> dialog set the <b>Default Namespace</b> property to <b>MasterCSharp.UserControl</b>. In your custom implementation be sure you set the correct namespace of the class you have annotated with the <i>ToolboxBitmap</i> Attribute. The reason we need to do this is that VS.NET embeds all resources in the assembly by prefixing the <i>Default Namespace</i> followed by the filename of the resource. As you know, even though the namespace and class names appear different to us as programmers, the .NET Runtime always deals with the fully qualified class names i.e the namespace name followed by the class name. Hence while trying to find the correct bitmap to display for your control/component the .NET Runtime searches for the fully-qualified name of the bitmap that resembles the fully qualified name of the class that has been annotated with the <i>ToolboxBitmap</i> attribute, once found the correct bitmap is displayed. So be extra careful while dealing with this scenario. If you are not sure don't shy to use the service of the the <b>ILDAM.exe</b> tool. Run <i>ILDASM</i> and select the freshly compiled (after making all the above changes) <i>DateTimeDisplayContol.dll</i> assembly. <i>Double-click</i> on the <b>Manifest</b> item to see the <i>Assembly Manifest</i> of the assembly as shown in <i>Figure 5</i>. As you can see the bitmap resource name <b>MasterCSharp.UserControl.DateTimeDisplayControl.bmp</b> resembles the fully qualified name of our User Control and hence this will work!! If there is a mismatch then probably something needs to be fixed! <p align="center"> <img border="0" src="../../IMG/worldtimeclient2_6.gif" width="584" height="231"><br> <b>Figure 5:</b> Assembly Manifest as seen in ILDASM<p align="left">6) Just to be sure this works, go to the <i>Toolbox window</i>, <i>right-click</i> and&nbsp; select <b>Customize Toolbox</b> from the context menu. In the <i>Customize Toolbox dialog</i> go to the <b>.NET Framework Components</b> tab and select the <b>DateTimeDisplayControl.dll</b> assembly that you just compiled (after making the above mentioned changes). You should see something like below. See the change in the Icon?? Neat, isn't it!<p align="center"> <img border="0" src="IMG/worldtimeclient2_7.gif" width="571" height="396"><br> <b>Figure 6:</b> Customize Toolbox Dialog<p align="left"> <span class=wboxheado>B) WorldTimeService</span> - This class actually contains the <b>proxy</b> class that will be used to communicate with the <b>World Time Web service</b>. Creating this assembly is nothing non-trivial, and I simple use the <b>WSDL.exe</b> tool provided along with the <i>.NET Framework SDK</i> to auto-generate the class for me. If you were a bit more picky about the file size, you could trim the source code and then manually compile the code to produce a more compact the assembly. I am going to take the easy way and simple compile the auto-generated class using the following commands at the command prompt (cmd.exe).<br> <b>wsdl /n:MasterCSharp.WebService /out:WorldTimeService.cs http://www.MasterCSharp.com/live/TimeService/TimeService.asmx?WSDL</b><br> <br> to create the source code file <b>WorldTimeService.cs</b> and then compile it with the following command<br> <b>csc /t:library /out:MasterCSharp.WebService.WorldTimeService.dll WorldTimeService.cs</b><p align="left"> This will create the appropriate assembly which will be used later-on.<p align="left"> <span class=wboxheado>Conclusion</span><br> In this part I demonstrated the creation of the <i>DateTimeDisplayControl</i> in VS.NET and lastly I covered the trivial creation of the <i>WorldTimeService</i> proxy class. As an added bonus to this article I covered how to use the <i>ToolboxBitmap</i> Attribute to add icons to your controls/components. In the next articles in this series I will cover the creation of other two assemblies which are used in the <i>World Time Client</i> application.

Comments

Add Comment