|
Problem # 1 - Color Properties DayColor and DayNameColor Properties If you’ve played around with this control for a little while, you may have noticed something a bit peculiar regarding the DayColor and DayNameColor properties. Open the Test Project in Visual Basic’s IDE and, while looking at the properties for the calendar control, change the DayColor property. You’ll notice it will change for a brief moment, then changes to be the same as the DayNameColor property when the calendar gets refreshed. And if you change DayNameColor, the DayColor property also gets changed! This problem is solved through changing the source code, as there’s a bug in the code for the Get DayNameColor property. Let’s have a look at this code: '----------------------------------------------------------------------
A simple mistake: setting the DayColor variable to mclrDayNames, instead of setting the DayNameColor variable to mclrDayNames. Forgetting part of a variable name is easy to do when the names are so similar. A possibility is that this code was developed from a copy of the code for the DayColor property, and that this was missed. This is something to remember when reviewing your own code. What’s Happening? The Refresh property does exactly as its name suggests. One of the keys to its overall performance is that it carries out all of the Get properties in order to fully refresh a given control. When you set the DayColor Property, the code for Let DayColor calls the Refresh routine:Public Property Let DayColor(NewVal As OLE_COLOR) mclrDay = NewVal UserControl.Refresh End Property 'Let DayColor() When this occurs, one of the routines called during the Refresh is Get DayColor: '----------------------------------------------------------------------
This provides us with the grief glimpse of the correct color for the days. However, since the code for Get DayNameColor comes later in the list of routines than the Get DayNameColor property, the DayColor property ultimately gets set to the color for DayNameColor, while the DayNameColor Property doesn’t get refreshed at all. Almost the same thing occurs when you set the DayNameColor property, with a couple of minor exceptions. The instant the color is changed, mclrDayNames gets properly set. When the Refresh occurs for this routine, the DayColor gets set to DayNameColor as well, again via the Get DayNameColor property. Since the DayNameColor property is not addressed correctly in its Get routine, the box on the OLE_COLOR control in the properties menu for DayNameColor never changes. The "Fix" Repair the Get DayNameColor code as follows: '----------------------------------------------------------------------
DayNameColor = mclrDayNames
If you now try to view the test form in design mode without going any further, you’ll see this:
The calendar control needs to be compiled once before we can check the results of our fix. Press the F5 key to run the sample, then shut it down. The test form will now show up as it did the first time we looked at it. Now, go ahead and toy with the DayColor and DayNameColor properties, and you’ll see that these properties now work correctly.Once you’ve done this, select ‘Make MSVBCldr.ocx’ from the File menu of the IDE, making sure to select the c:\windows\system\ directory as its location.
Now What? This problem was labeled #1, which means that, yes, there’s another one we’ll address a little later on. Does this indicate that we shouldn’t use this control in our applications? Of course not. It’s supplied as source code, so anything we find we should go ahead and repair. Problem #2 is a bit different, and we’ll see how to repair something outside of the source code. The reason we receive samples from Microsoft with our development software is to see how to do things, not only how to accomplish a particular task, but also how to develop software in a manner consistent with certain software industry standards. These unsupported controls and utilities are a bit different. Looking deeper at some of the code for this particular control reveals that we are looking at a work in-progress that we normally wouldn’t be allowed to see. For instance, the following code is from the Declarations section of the UserControl for the MSVBCalendar Control: '----------------------------------------------------------------------
The bolded line is important, and indicates that this control may not have been intended as a sample. This may have actually been a control intended to be shipped with Visual Basic 5 that was turned into an unsupported sample due to time constraints. The code for the UserControl’s Paint event is also interesting, as it reveals the uncompleted aspect of this sample: 'change the text color to dark gray to paint the previous month days 'daveste -- 7/31/96 'TODO: this should be replaced with day styles or at least with 'a property the control the font and color of these other dates dcWork.TextColor = RGB(128, 128, 128) Note the grammar on that one. Definitely incomplete! There are other TODO lines throughout the code. You’ll find them if you look around a bit more. What’s even more interesting is the following code, also from the UserControl portion of the code:
Private Sub CopyFont(fntSource As StdFont, fntDest As StdFont)
'daveste -- 8/14/96
'REVIEW: Is there a better way to do this???!!!
'if the destination is nothing, create a new font object
If fntDest Is Nothing Then Set fntDest = New StdFont
fntDest.Bold = fntSource.Bold
fntDest.Charset = fntSource.Charset
fntDest.Italic = fntSource.Italic
fntDest.Name = fntSource.Name
fntDest.Size = fntSource.Size
fntDest.Strikethrough = fntSource.Strikethrough
fntDest.Underline = fntSource.Underline
fntDest.Weight = fntSource.Weight
End Sub 'CopyFont()
Good question from the anonymous ("daveste"?) code reviewer, and quite a challenge for those of us who now have the code. The challenge? Quite simply, this: Finish designing the control. Complete the TODO items, answer the reviewers questions, and test the final control for problems like the one we just repaired. Customize it as you’d like, since you’ve got the source code and the ability to do so. The end result in all of this will not just be a nifty little calendar control that works to our liking. Rather, this is a great way to become better developers than we already are.
Try It Out – Usage of the MSVBCalendar Control In the chapter 6 directory of the CD is a sample application we’ll use to see how the calendar control can be used. Open the project chapter6.vbp and have a look at the form:
If an error occurs during the loading of this project, it’s likely due to the copy of MSVBCldr.ocx on your system being not quite what the IDE is looking for. If this happens, the place where the calendar would have been shown will only show an empty 3-D rectangle. Delete this rectangle, and ensure that the Microsoft Visual Basic Calendar is selected in the projects’ components. Then, add the calendar to the project, on this form, in the place the 3-D rectangle was previously. The default name for the calendar is Calendar1, which is what I used to develop this sample. None of the calendar’s properties need to be changed. Right now there is no code on the form that performs any kind of tasks. The menus are empty, as are the events of the calendar control itself. Place the following code in the form’s Load event to set the calendar’s date to the current date each time the form is opened:
Private Sub Form_Load()
' Set the calendar to today's date
With Calendar1
.Year = Format(Now, "yyyy")
.Month = Format(Now, "m")
.Day = Format(Now, "d")
.Refresh
End With
End Sub
Place the following code under the DblClick event of the calendar control Calendar1:
Private Sub Calendar1_DblClick()
' Declare the variables
Dim SelDate As Variant, NowDate As Variant
Dim SelYear As Integer, SelMonth As Integer, SelDay As Integer
' Assemble the date string from the calendar control
With Calendar1
SelYear = .Year
SelMonth = .Month
SelDay = .Day
End With
SelDate = DateSerial(SelYear, SelMonth, SelDay)
' Compute today's date
NowDate = DateSerial((Format(Now, "yyyy")), (Format(Now, "m")), (Format(Now, "d")))
' Test to see if the selected date is earlier than today
If SelDate < NowDate Then
'If it is...
Msg = "The date you have selected is earlier than today." & Chr(10) & _
"Please select today's date or later."
Style = vbOKOnly + vbExclamation
Title = "Date Selection Error"
Response = MsgBox(Msg, Style, Title)
' Reset the calendar
With Calendar1
.Year = Format(Now, "yyyy")
.Month = Format(Now, "m")
.Day = Format(Now, "d")
.Refresh
End With
Else
' Load the text box with the selected date
If Option1.Value = True Then
' U.S.A.
Text1.Text = SelMonth & "/" & SelDay & "/" & SelYear
Else
If Option2.Value = True Then
' Europe
Text1.Text = SelDay & "/" & SelMonth & "/" & SelYear
Else
' U.S.A.
Option1.Value = True
Text1.Text = SelMonth & "/" & SelDay & "/" & SelYear
End If
End If
End If
End Sub
Place the following code under the option button labeled U.S.A.:
Private Sub Option1_Click()
' Load the text box with the selected date
If Text1.Text = "" Then
' Do nothing
Else
' U.S.A.
Text1.Text = Calendar1.Month & "/" & Calendar1.Day & "/" & Calendar1.Year
End If
End Sub
This next bit of code goes under the option button labeled Europe:
Private Sub Option2_Click()
' Load the text box with the selected date
If Text1.Text = "" Then
' Do nothing
Else
' Europe
Text1.Text = Calendar1.Day & "/" & Calendar1.Month & "/" & Calendar1.Year
End If
End Sub
Press the F5 key to run the program. As long as there are no compilation errors, the form will appear in the center of the screen. If you double-click on a date later than today’s date, the date value will appear in the text box. However, if you double-click on a date earlier than today, a message will appear:
By default, the date is placed into the text box in the format used in the U.S.A. Click on the option button labeled Europe and watch the contents of the text box change appropriately. How It Works First we declare the variables we need to accomplish this task. The first two need to be of the type Variant since they are used with the DateSerial statement: ' Declare the variables Dim SelDate As Variant, NowDate As Variant Dim SelYear As Integer, SelMonth As Integer, SelDay As Integer Instead of simply retrieving the value of the selected date from the calendar, we’ll retrieve it in pieces so we can correctly calculate the value for DateSerial:
' Retreive the date from the calendar control
With Calendar1
SelYear = .Year
SelMonth = .Month
SelDay = .Day
End With
We then compute the serial value for the selected date. ‘ Compute the selected date SelDate = DateSerial(SelYear, SelMonth, SelDay) Note that the DateSerial function will return an error if the value is -32,768 to 32,767 from the base date of January 1, 1904. This is important due to the range of years available from this control and the fact that they can be extended even further. In a similar manner, we then compute today’s date: ' Compute today's date NowDate = DateSerial((Format(Now, "yyyy")), (Format(Now, "m")), (Format(Now, "d"))) Since this sample will be used later in the book for a scheduling wizard, we need to check if the selected date is earlier than today. If it is, we’ll generate an error to that effect. Once the message box is cleared, the calendar is refreshed with today’s date so the user can have another go at it:
' Test to see if the selected date is earlier than today
If SelDate < NowDate Then
'If it is...
Msg = "The date you have selected is earlier than today." & Chr(10) & _
"Please select today's date or later."
Style = vbOKOnly + vbExclamation
Title = "Date Selection Error"
Response = MsgBox(Msg, Style, Title)
' Reset the calendar
With Calendar1
.Year = Format(Now, "yyyy")
.Month = Format(Now, "m")
.Day = Format(Now, "d")
.Refresh
End With
If the selected date is, in fact, today or later, we place the selected date into the text box in the appropriate format for the locale:
Else
' Load the text box with the selected date
If Option1.Value = True Then
' U.S.A.
Text1.Text = SelMonth & "/" & SelDay & "/" & SelYear
Else
If Option2.Value = True Then
' Europe
Text1.Text = SelDay & "/" & SelMonth & "/" & SelYear
Else
' U.S.A.
Option1.Value = True
Text1.Text = SelMonth & "/" & SelDay & "/" & SelYear
End If
End If
End If
The internationalization applied by the option buttons is rather simple, as it places the date fields into the text box in the correct order for the locale. Notice that the controls on this form are located on a picture box, which acts as a container for them. We’ll use this same sample to develop more concepts through the rest of this chapter. Later on, we’ll be building a scheduling wizard from this form, so remember to keep track of where it is. However, this is where the other problem comes in. [Home Page] [Next Lesson] [Previous Lesson] [Dave Liske's Site] [Wrox Web-Developer]
|
Quick searches: Site Search | Advanced Site Search |
|
By using this site you agree to its terms and conditions VB Explorer and VBExplorer.com are trademarks of Exhedra Solutions, Inc. |