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.

Reader Comments:

Thu, Jan 19, 2012 painkillers http://www.kingpainkillers.com

That’s another thing to worry about especially for my Californian affiliates working for my Firm. thanks for the information.

Wed, Jun 29, 2011 Online Calculator http://onlineworkingcalculator.com

Case correction is not working if the names are coming wrong from external typelibs. In which case you have to make a custom typlib with correct cases and reference it *before* the offending ones. Still there is this edge case when there is an offending struct (all upper-case) matching a function name in the project. The most definite way for forcing casing on names project-wide is to declare structs with matching names in a custom typelib and reference it before every other reference (highest in references dialog). This way names will converge to proper casing upon check-out.

Thu, Apr 28, 2011 max garnar America

Ride quality refers to the degree of protection offered vehicle occupants from uneven elements in the road surface, or the terrain if driving off-road. A car with very good ride quality is also a comfortable car to ride in. Cars which disturb vehicle occupants with major or minor road irregularities would be judged to have low ride quality. Key factors for ride quality are Whole body vibration and noise. http://www.sbfdebtconsolidation.com/ DOT

Fri, Nov 5, 2010 Dirk Germany

If one declares (unfortunately) a variable anywhere in the project (to follow your example) named date_shortDate the IDE will again change all declarations. So this is of very limited use ...

Fri, Jun 25, 2010 SEO Services canada

Don't know what is wrong what is rite but i know that every one has there own point of view and same goes to this one..

Fri, Jun 11, 2010 wqw

Case correction is not working if the names are coming wrong from external typelibs. In which case you have to make a custom typlib with correct cases and reference it *before* the offending ones. Still there is this edge case when there is an offending struct (all upper-case) matching a function name in the project. The most definite way for forcing casing on names project-wide is to declare structs with matching names in a custom typelib and reference it before every other reference (highest in references dialog). This way names will converge to proper casing upon check-out. Also, see http://stackoverflow.com/questions/1064858/stop-visual-basic-6-from-changing-my-casing for custom typelib description sans structs hack.

Tue, Apr 13, 2010 James Head

We've been doing this for years. We usually do it a little differently: #If forcecase then ' some un-used variable (which defaults to False since it's un-defined) Dim piCreationTime, piExitTime, piKernelTime,piUserTime #EndIf Doing this with the square-bracket names drops the square brackets, though. It's OK, even though the line turns red, indicating an error -- it still compiles.

Add Your Comments Now:

Your Name:(optional)
Your Email:(optional)
Your Location:(optional)
Comment:
Please type the letters/numbers you see above