Classic VB Corner

Customizing the Ride Part 2

Karl Peterson returns with another batch of tricks designed to improve the IDE.

Does it bother anyone else that enumerations don't hold their case, like normal variables and constants do? That is, if you declare a module level variable:

Private aRidicuLousCamel As Whatever

And then later on in some routine elsewhere, you just merrily typing away, and enter the variable name in all lowercase, VB will automagically correct the case for you to match the declaration. I'll bet a great number of you rely on this feature to be sure you've spelled the name of the variable correctly?

But if you were to declare an Enum in the same manner:

Public Enum LocaleDateFlags
   DATE_SHORTDATE = &H1
   DATE_LONGDATE = &H2
End Enum

Now, if you were to type "date_shortdate" in your procedure window, you'll perhaps be surprised to see that it doesn't change to all caps as it was declared. Well, that's the way Classic VB is, and there's nothing we can do to change that. But we can force the case fairly easily.

The trick is to declare the variables again, but in a segment of code that doesn't actually even get compiled. I do it like this:

#If False Then
   ' Placing these constants within a conditional compiler block
   ' forces the IDE to propercase them whenever typing anywhere
   ' within the project.
   Private Sub ForceEnumCase()
      ' Date Flags for GetDateFormatW.
      Const DATE_SHORTDATE As Long = &H1
      Const DATE_LONGDATE As Long = &H2
   End Sub
#End If

Now, when I type "date_shortdate" and hit return, the IDE automagically capitalizes it just as it should. Yeah, it's a little extra setup, but it can truly save considerable frustration down the road.

Testing for Out-of-Range Enums
This is one I have to search high and low for, every time I need it, because no matter what I always forget it! I frequently write routines with arguments that are of an enumerated type. This makes providing the arguments while writing code as simple as could possibly be, because as I'm typing away I get a nice drop-down list of potential argument values from Intellisense. But how do I test to see whether an argument is in range, within the called procedure?

Let's use the following Enum, from my Uptime sample, as an example. The ProcessTimes enumeration consists of four sequential constants:

Public Enum ProcessTimes
   piCreationTime = 0
   piExitTime = 1
   piKernelTime = 2
   piUserTime = 3
End Enum

You can then write a routine that expects one of these values, by simply declaring the argument As that type:

Public Property Get ProcessTime( _
   ByVal WhichTime As ProcessTimes) As Date

When coding, Intellisense will provide you with the dropdown list of options. But you aren't forced to use any of them, of course, and there may be times when you want to use a calculated value anyway. Perhaps an error would be triggered in the called routine, if you passed an out of range value, though. You could do tests like this:

If WhichTime >= piCreationTime And _
   WhichTime <= piUserTime Then

But how ugly is that??? Imagine if you need to rename a constant or expand or reorder the list or any number of other things that could muck that up. How many places might you have to remember to update that test? Here's a solution that only requires a single tweak if your Enum changes. Declare it like this:

Public Enum ProcessTimes
   [_ProcessTimesMin] = 0
   piCreationTime = 0
   piExitTime = 1
   piKernelTime = 2
   piUserTime = 3
   [_ProcessTimesMax] = 3
End Enum

The underscore used in the first and last constants is an invalid leading character, of course. But putting the brackets around it tells VB to allow it in this specific case. It's useful in two very special ways. The bracket-underscore combination 1) will not show up in Intellisense, and 2) can be used in code!

This means you won't see those values when Intellisense pops while you're writing code, but you can still test for them in the code you're calling. The awkward test above becomes:

If WhichTime >= [_ProcessTimesMin] And _
   WhichTime <= [_ProcessTimesMax] Then

Never again needing to be updated, should your Enum change.

About the Author

Karl E. Peterson wrote Q&A, Programming Techniques, and various other columns for VBPJ and VSM from 1995 onward, until Classic VB columns were dropped entirely in favor of other languages. Similarly, Karl was a Microsoft BASIC MVP from 1994 through 2005, until such community contributions were no longer deemed valuable. He is the author of VisualStudioMagazine.com's new Classic VB Corner column. You can contact him through his Web site if you'd like to suggest future topics for this column.

comments powered by Disqus

Featured

Subscribe on YouTube