Category Archives: VB Feng Shui

Visual Basic and line numbers

2
Filed under Utilities, VB Feng Shui

I’ve seen lots of rants over the years saying things along the lines of

Who wants to use a language that looks like this:

10   Print "Hello, World"
20   If x = 1 Then Goto 50
30   Print "Something else"
50   Print "Result was 50"

Or similiar nonsense. Of course, VB only vaguely resembles this style of code anymore, but one thing has remained virtually the same. Line numbers.

If I remember correctly, in BASCOM and BASICA, they were required. Then Basic Professional Developer System (MS BasicPDS) came out and line nums were no longer necessary, but you could still use them if you liked (probably more to be backwardly compatible with all that old BASICA code).

In all the older VBs (pre .NET days), you actually had to add line numbers to the source code itself in order to get them into the program and refer to them (via the ERL function). While this was certainly doable, the resultant code ended up looking like some seriously old-school mash you wouldn’t want to be caught dead delivering (or trying to maintain).

However, being able to report a line number during an error at runtime, at the client site, so it can be logged or reported back to you as a developer is damn near invaluable. Microsoft recognized this enough in .NET to include line number support built in to the error stack and handling subsystem (although the old style line numbers in code and ERL function still work, appearently).

That’s great for .NET, but there’s still a lot of VB6/5 and older code laying around that has to be maintained. So what do you do?

Ages ago, I built a little command line utility to run through every module in a VBP file (and every module of every project in a VBG file, too), and either add or remove line numbers. It output all the files to the same directory, but with “LINED_” prepended to the file name. This tactic makes it very easy to simply DEL LINED_*.* when you’ve compiled the line numbered project to clean things up and not leave line numbered code sitting around. You can run it against individual BAS, FRM, CTL, DSR, CLS, etc files, but if you point it at a VBP or a VBG file, it’ll even rewrite that file so that it’s contents point to the new file names. This makes it very easy to construct a batch file to 1) line number a project, 2) compile it, and 3) kill off the line numbered source files.

For instance, this batch file:

set pfile=%~dpn0
set pname=%~n0
set pdir=%~dp0
vbliner %pfile%.vbp
VB6.EXE /m "%pdir%LINED_%pname%.vbp"
del "%pdir%LINED_*.*"

Just name it the same name as a VBP file, save it to the same folder as your VBP file, and run it.

It will pull the file name and path from the name of the batch file itself (which should be the same as the VBP you want to compile), line number the project, compile it, then delete the line numbered source files when fnished, leaving you with a nice compiled file, completely line numbered but with none of the mess.

Its other nifty trick is to line number the lines using the same algorithm that the VB6 IDE uses to display line numbers as you move through code, as in:

This one trick (which I haven’t seen in any utility to line number VB source), makes it so that you don’t have to keep the line numbered source around so you can refer to it later. Somebody calls up saying they get an error in Module XYZ, line number 10202, all you have to do is pull that version of the module from SourceSafe (you do use version control of some kind, right?), load it up in VB and jump to the given line number. Can’t get much simpler.

VBLiner starts numbering at 10000, the rational behind that being that if you happen to need to include a hardcoded line number in your code for some reason, the automatic numbers hopefully won’t interfer with your hand coded numbers.

Another handy tip. Once you’ve opened your VB project, Right click the project explorer, select ADD, then ADD FILE. Find the BAT file that you just created above, and be sure and check the “Add as Related Document” box before adding it to your project. Now, then, you should be able to simply DBL CLICK on the BAT file from the VB project explorer to run the bat file and compile your project, complete with line numbers, all automatically.

And a final note; VBLiner does ostensibly support removing line numbers from VB files as well, but I’ve never had much use for that facility, so it’s not well tested. As with any freeware, use at your own risk. And it should go without saying, Back up your source files before running it on them.

Download a zip of the utility here and let me know what you think.

VB Swiss Army Knife

7
Filed under Utilities, VB Feng Shui

VB has one of the best IDE’s around. Sure Eclipse is pretty capable, Delphi is quite slick, and for the purists, editors like SlickEdit can make you almost believe you’re coding in an IDE.

But VB’s IDE is the one to beat. And it has been since VB3.

But even the best have issues; mistakes, ommisions, things that jsut could have been so much better.

And that’s where MZTools comes in.

If you haven’t already played with it, download a copy and install it now. Carlos originally built MZTools for VB6 way back when, and that version was (and still is) a free utility. He’s branched out to supporting Visual Studio .NET now, and the newest version is not free, but it is worth every penny.

Take a look at the features page for version 3 (which supports VB6). The Code Review, Code Templates, and Error Handler Templates are gauranteed to save tons of time.

Personally, I don’t like his line numbering support. I feel like the line number applied to a line should be the same as the actual line number in the file, as reported by the VB6 editor, like this:

That way, you don’t have to retain the numbered version of the source to be able to refer back to a specific line number. However, this is a pretty minor nitpick.

In short, MZTools is a massively handy utility to have on you’re VB menu bar. Definitely for VB6 (cause it’s, well, free), and worthy of consideration for .NET.

Office 2007 and RibbonIDs

0
Filed under Office, VB Feng Shui

By now, I suspect the Office 2007 Ribbon is a bit old news.

From a developer’s point of view, it’s relatively easy to customize the ribbon via add-in code, which is really nice. And since there seems to be no dearth of examples on doing so, I won’t be wandering down that path.

For Word, Excel, and PowerPoint, things are pretty straightforward, because, as far as I can tell, there’s only one Ribbon for them.

But in Outlook, things are more complicated. The main Outlook window doesn’t even have a ribbon. But the sole parameter of the main entry callback for customizing the ribbon is:

Public function GetCustomUI(ByVal RibbonID as string) as string

so what are the possible RibbonIDs?

After a good bit of searching, I found the following table in the VSTO3CTPTutorial.doc file that identifies them all:

RibbonID MessageClass
Microsoft.Outlook.Mail.Read IPM.Note.*
Microsoft.Outlook.Mail.Compose IPM.Note.*
Microsoft.Outlook.MeetingRequest.Read IPM.Schedule.Meeting.Request or IPM.Schedule.Meeting.Canceled
Microsoft.Outlook.MeetingRequest.Send IPM.Schedule.Meeting.Request
Microsoft.Outlook.Appointment IPM.Appointment.*
Microsoft.Outlook.Contact IPM.Contact.*
Microsoft.Outlook.Journal IPM.Activity.*
Microsoft.Outlook.Task IPM.Task.* and IPM.TaskRequest.*
Microsoft.Outlook.DistributionList IPM.DistList.*
Microsoft.Outlook.Report IPM.Report.*
Microsoft.Outlook.Resend IPM.Resend.*
Microsoft.Outlook.Response.Read IPM.Schedule.Meeting.Resp.*
Microsoft.Outlook.Response.Compose IPM.Schedule.Meeting.Resp.*
Microsoft.Outlook.Response.CounterPropose IPM.Schedule.Meeting.Resp.*
Microsoft.Outlook.RSS IPM.Post.Rss
Microsoft.Outlook.Post.Read IPM.Post.*
Microsoft.Outlook.Post.Compose IPM.Post.*
Microsoft.Outlook.Sharing.Read IPM.Sharing.*
Microsoft.Outlook.Sharing.Compose IPM.Sharing.*

BTW, for those that are interested, in Word, the RibbonID is always Microsoft.Word.Document

Similiarly, in Excel, it’s Microsoft.Excel.Workbook

and in PowerPoint, it’s Microsoft.PowerPoint.Presentation

I wasn’t able to find that info published anywhere. I suppose it’s technically irrelevant, but still…

Solid Writing

0
Filed under Blogging, VB Feng Shui

It’s tough to write well. Unfortunately, too many people out there don’t realize this.

I realize it. I also realize I don’t write particularly well, but recognizing your problem is always the first step, right?

I just came across a Gar’s Tips on Sucks-Less Writing that lays down 10 rules to tighten up your writing. It’s old news, sure, but there’s good stuff there.

In the end, I suppose the most important concept to osmose is to say enough, and nothing more.

Application Configuration

0
Filed under Software Architecture, VB Feng Shui

I’ve played a bit now with the .NET configuration model and while I can certainly see some elements in there to like, it seems to me that it falls short in a number of different ways.

First off, it doesn’t really have any concept of “multi-level configuration.” In fact, it’s basically a single level XML file (granted, you could create a hierarchical organization within that single xml file, but there’s other issues with that). .NET does help a bit with the concept of a machine config file, but from what I can tell that’s about as far as it goes.

Second, the default behavior is to locate the application config file in the same path as the application itself. That’s great if your user is running as administrator, but not so great in more locked-down situations where users do not have full admin rights. In those cases, configuration that’s writable needs to be stored somewhere within the user’s profile directory structure. This is just going to get worse with Vista, too.

Ok, sounds good but what, you may be asking, is a multi-level configuration scheme, and why would I want one? Almost every app I’ve ever worked on, short of the trivial utilities I’ve built, has required this sort of configuration scheme (or at the very least greatly benefited from having it). It almost always follows along this line:

  • Administrator specified User specific configuration (rarely used, the user cannot change this configuration)
  • User specific configuration (that the user can change dynamically)
  • Group specific configuration (typically set by a system administrator or group admin and read only to users)
  • Machine specific configuration (typically set by a system admin, and rarely used, read only to users)
  • Application global configuration (typically set by the system admin, read only to users)
  • OEM defaults (typically set by the app developers to provide default config values, generally readonly by everyone except the developers)

At each level, the system provides for an essentially unlimited number of name value pairs that can be cordoned off into groups (or sections as they used to be called in INI files). Some may argue that a section-name-value system like this is too limiting and you should always accomodate full hierarchical structures, but I’ve found the extra functionality rarely necessary.

Of course, the type of value (string, int, date, etc) for a particular setting is defined within the application, but value types might also be defined as OEM default settings. Should sysadmins really be able to change setting X from a string to a date? I’d imagine not usually.

The trick and the real beauty of the system is in the way that setting values are resolved. The resolution logic basically says that if the app can find a setting at a higher level in the hierarchy, it uses that value. Otherwise it searches down the hierarchy till it either finds a value, or till it drops to the OEM defaults. If no setting is specified at the OEM level, the system defaults to blanks, or 0’s depending on the data type.

So, for instance, the code might ask for the setting “AskOnExit” from the “Prompts” section. The config handler needs to look first at the “level of most significance” which, in the above list of levels, would be the Administrator specified user specific settings (ie those settings that are set on a per user basis, but that the user himself doesn’t have the authority to change.

If the setting isn’t found there, the code continues down the hierarchy, looking at each level in turn until eventually in run through them all and returns the default or a blank or 0.

And, of course, you also have to provide a means to retrieving and writing a setting at a specific level in the hierarchy, for those settings that are always application level or machine level or what not.

Obviously, such a scheme requires a little more work up front, but the configuration flexibility (especially when you’re talking about major, multi user systems with lots of configuration options, typically off-the-shelf, reseller-friendly applications like accounting systems or CRM packages), is a huge selling point to admins and users alike.

Why, then does configuration handling in .NET seem so archaically primitive?

Could you roll all these levels into that singular .config file? Sure, when where would you put it? In the Application path? No, users won’t typically have write rights there. Under the user’s Application Data folder in the Profile? No, can’t put app wide settings somewhere that only a single user can access it. How about that machine config file. Again, not writable by typical users.

It’s funny that Windows already has a rights system that is very stable, quite flexible and easy to work with, both manually and from within code and yet it often goes completely unused by larger apps. I’m talking, of course, of the file system.

These days, though, web apps are de rigueur and you can’t go assigning file system rights to web users. There’s no way that would fly with most web developers (you weren’t really thinking of something like that, right?). So, roll it up into a simple table, with a getSetting and a setSetting stored procedure to simplify the coding. With proper indexing, and a little intelligent caching, it’ll be every big as fast as using the .NET configuration functions, and whole lot more flexible.

Long story short. If your sideline utility needs to save a few settings, use the .NET configuration. It’s fast, relatively easy and convenient. But for just about everything else, take a little time and do it right.

Your users and their sysadmins will thank you.

VB and Resource Files (part 2)

0
Filed under Resource Files, VB Feng Shui

If you’ve ever looking closely at Windows applications, you know that Windows Version Numbers are composed of 4 parts:

  • Major version
  • Minor version number
  • Revision number
  • Build number

So a version of 4.8.3.9888 would typically mean Major version 4, Minor version 8, Revision 3, Build 9888.

If you’ve ever looked at VB’s Project properties box, though, you’ve probably noticed the disconnect.

ProjProps

Obviously, VB directly supports the Major and Minor, and appearently, the Revision number.

But, build a VB6 app with unique values in for each number and then view the app’s properties via Windows Explorer:

AppProps

In this particular app’s case, Major and Minor are 0, and Revision was set to 49. However, according to the Windows Property panel, the Build number is 49. VB internally makes the Build number what you enter as the Revision number in the VB project property UI.

Now, whether this was just a typo on the part of the VB developers or an intentional “feature”, I can’t say. But it definitely can cause confusion and make it difficult to identify versions of your app out in the field. Then there’s the constant explaining of why your app’s revision always seems to be 0, but other applications have something there.

In a previous post on VB and resources, I mention the Microsoft Resource Compiler, a utility that can compile resource files into RES files, which can then be compiled into your application by VB.

This combination works wonders if all you want to do is embed icons, bitmaps, strings or arbitrary files into the resources of your app.

And, if you look at the RC documentation, you’d see info on VERSIONINFO statement that is used to define a Version Info Resource.

So, it would stand to reason that if you created a resource file, say like this:

VersionInfoTest.rc

1 VERSIONINFO
FILEVERSION 1,2,3,4
PRODUCTVERSION 1,2,3,4
FILEOS 0x4
FILETYPE 0x1 //// 2 for dll, 1 for exe
{
BLOCK "StringFileInfo"
{
BLOCK "000004b0"
{
VALUE "CompanyName", "MyCompany"
VALUE "ProductName", "MyProduct"
VALUE "FileDescription", "MyFileDesc"
VALUE "LegalCopyright", "MyLegalCopyright"
VALUE "LegalTrademarks", "MyLegalTrademark"
VALUE "OriginalFilename", "MyOriginalFilename"
VALUE "ProductVersion", "1.2.3.4"
VALUE "FileVersion", "1.2.3.4"
VALUE "Comments", "MyComments"
VALUE "InternalName", "MyInternalName"
}
}
BLOCK "VarFileInfo"
{
VALUE "Translation", 0x0000 0x04B0
}
}

Then, all you should have to do is compile the RC file with RC.EXE, load up VB, add the resulting RES file to your project and you’d be done.

Unfortunately, the path to enlightnment is never straightforward, and neither is the process of getting a proper version number into a VB6 executable.

The problem is that VB post-processes the compiled executable in order to put the version information from the Project properties screen into the VERSIONINFO resource. This means that the nice, correct VERSIONINFO resource that you just compiled into the executable get’s stomped on by whatever you happen to have in the Project Properties dialog, and that dialog will always reset the Windows Revision number to 0, and use the VB Revision number as the Windows Build number.

What you have to do is post-post-process your exe and put the correct VERSIONINFO resource back in after VB is completely finished with the file.

And the easiest way to do that is with a handy free utility called Resource Hacker. This utility allows you to easily open, view, and even extract all the resources in any EXE or DLL. If you want to just pull all the icons out of a file’s resources, there are definitely better ways. But if you really want to poke around the resources in a file, ResHacker is perfect. Plus, it’s got a very handy, if not a little arcane, command line interface that will allow you to automate much of the process via MAKE files or batch scripts.

Make sure the RESHACKER.EXE is on your path, then run:

reshacker -addoverwrite "yourexe.exe", "yourexe.exe", "yourexe-VersionInfo.res", versioninfo, 1 , 1033

I’m assuming your compiled application is called yourexe.exe, and that you’ve compiled an RC file with a VERSIONINFO resource in it to the file yourexe-VersionInfo.res.

Resource hacker will dutifully wipe out the VB created VERSIONINFO resource and replace it with the one compiled from your RC script.

One important note, though. ResHacker will not merge a single resource, and all of the version information is considered a single resource. That means that you need to specify all the pertinent version info properties in your RC file, because everything specified via the VB Project Properties dialog will get replaced.

“But”, you say, “the version numbers themselves appear to be replicated 4 times in the RC file! I’m a lazy programmer and the thought of updating 4 copies of the version number just seems, well, wrong.”

And you’d be right.

Fortunately, there is a way to convince RC.EXE to allow you to specify the version number for your app only once. However, doing so is, like the concept of using resources in a VB app, more complicated that you would at first imagine.

I’ll discuss that in my next post.

Visual Basic 6 and Resource Files

1
Filed under Resource Files, Utilities, VB Feng Shui

Feng Shui is all about the placement of things to better harmonize with their (and consequently your) surroundings.

With VB, there’s no better place to examine that than the file footprint of your application.

Ask yourself: You have two apps to evaluate. They perform identically, are configurable in all the same ways and behave exactly the same. One app consists of hundreds of files scattered across dozens of folders. The other’s footprint is exactly one file, the EXE itself. Which would you choose?

Granted, that’s an extreme case, but the point is, the smaller your app footprint, the better, in almost all circumstances.

And a really nice way to shrink an app footprint is with resources.

If you’ve never messed around with resource files in VB6, or maybe only tried to use the built in resource editor add-in, you really don’t know what you’re missing.

Resources can be an immensely handy way to embed everything from pictures to WAV files, to chunks of script, to icons, and just about anything else directly into your application, but in a way that makes them accessible to the outside world, for one-off customizations, translations, or to just keep the file footprint of your app as small as possible.

However, resource files can be notoriously difficult to work with because of the lack of tools available natively with VB6. VB.NET dramatically improves upon the situation, but there’s still a lot of VB6 code out there that might benefit from resources.

Generally speaking, you have two “types” of resource files where VB6 is concerned.

  • the resource file the can be “included” in the project and is available to your code while you’re running in the IDE
  • Any resources “added” to your applications EXE/DLL/OCX file AFTER you compile it.

Why the distinction?

There’s one specific kind of resource that you very much should want to include in your compiled file, but which VB is notoriously lacking about. The Version Info Resource.

VB only allows you to specify the Major, Minor, and Build version numbers (although VB calls the Build number, the “revision” number, mysteriously).
Windows executables, on the other hand, support a Major, Minor, Revision, and Build.

Now, the truth is, VBs support is generally fine for utilities, hobbiest programs and the like. But real, commercial applications really should make use of all four numbers, and that’s something that is impossible using VB alone.

Ah, you say, VB does have that “Resource Editor” add-in, just use it! Not quite. You can’t create a version info resource in it, and even if you could, VB’s compiler replaces any version info element within that resource file with the information from the project properties window.

The solution is relatively simple and still preserves all the great things that resource files in VB can do for you.

The IN-THE-IDE Resource file

For this resource file, you have 2 choices, use the VB Resource Editor Add-In, or create an RC resource script file, and compile it to a RES binary format file that VB expects. I prefer the later, simply because scripting the resource file makes it much easier to include things like big chunks of text (xml, scripts, icons, what-have-you), and you can leave all of those things external to the RES file without having to manually pull them in via the Editor add-in every time they change.

I usually create an RC file with the same name as the VBP file, but with an RC extension

test.RC

// Test Resource Compiler file
// used to automatically compile the RC file into a RES file
// BEFORE the project itself is compiled
// This makes the Resource data available to code while in the IDE
//
//-----------------------------------------------------------------------------------
// Arbitrary Text File Resources
//
//----------------------------------------------------------------------
TEXTRES1   TEXTRES_DEFS PRELOAD DISCARDABLE TextRes1.txt
TEXTRES2  TEXTRES_DEFS PRELOAD DISCARDABLE TextRes2.txt

//-----------------------------------------------------------------------------------
// Bitmap Resources
//-----------------------------------------------------------------------------------
IMG_MAIN  BITMAP PRELOAD  DISCARDABLE ".\test.bmp"

Note that test.bmp is just some random bitmap file, and that TextRes1.txt and TextRes2.txt are arbitrary text files.

Then, you can access those resources via a little bit of VB code

To get the text file resources

Dim a() As Byte
dim buf$
a() = LoadResData("TEXTRES1", "TEXTRES_DEFS")
buf$ = StrConv(a, vbUnicode) 'need to convert the raw ansi text file content to UNICODE to make VB happy

Or to load the bitmap

Set form.Picture = LoadResPicture("IMG_MAIN", vbResBitmap)

Icons, and string tables are a little more difficult, esp. with respect to XP and VISTA format icons, so I’ll worry about them later.

You can compile the RC file using a command line similiar to the following:

rc.exe /r /fo "test.res" "test.rc"

Make sure the RC.EXE resource compiler is on your path for it to run right. The RC.EXE file itself should be somewhere in the VB6 installation folder under Program Files. For a muhc more thorough explanation of the Resource Compiler, check here. Microsoft has some very good RC information here also.

Alternatively, you can put this command in a BAT file, and execute it quietly:

cmd /Q /c rc.ex /r /fo "test.res" "test.rc"

One caveat. If you decide to use the RC file, be aware that VB loads the compiled RES file when you load the project. So if you make a change to one of the component resource files (say, an ICO or BMP file), you’ll need to exit VB, recompile the RC file to a RES file, and then RELOAD the project in VB. Since RES files don’t change all that much once initially created, this isn’t a huge problem.

Another note: You can only include one resource file in a single VBP project, so it has to contain all the resources the app will need (except, of course, for the Version Info Resource).

And a final note: You can easily add a resource file to a project by
1) compiling the RC file to a RES file
2) Opening your VBP project
3) dragging the RES file from Explorer to the VB Project Window.

For next time, handling the Version Info Resource….

Indenting

0
Filed under VB Feng Shui

Why is it that VB (and VBScript) seems to be more prone to poor code styling than most other languages.

I suppose it’s likely because Basic is, if I recall correctly, the most widely used language out there. And if something’s that widespread, well, bad things are just bound to happen, and happen more often.

I was looking at some code recently (I read lots of code) and saw this (the function name and a few comments have been removed but otherwise this is exactly as I found it, and I’m not even concerned with what the code does for this purpose):

Function XXXX(Optional AutoRestart As Bo olean = True, Optional CreateNew As Boolean) As Boolean
InitCommonControls
On Error Resume Next
Dim XML             As String
Dim ManifestCheck   As String
Dim strManifest     As String
Dim FreeFileNo      As Integer

If cIDECheck = True Then AutoRestart = False
If AutoRestart = True Then CreateNew = False

XML = (" " & vbCrLf & "<assembly>" & vbCrLf & "<assemblyidentity>" & vbCrLf & "    <description>EXEDESCRIBTION</description>" & vbCrLf & "    <dependency>" & vbCrLf & "    <dependentassembly>" & vbCrLf & "    <assemblyidentity>" & vbCrLf & "    </dependentassembly>" & vbCrLf & "    </dependency>" & vbCrLf & "</assembly>" & vbCrLf & "")

strManifest = App.Path & "\" & App.EXEName & ".exe.manifest"    'set the name of the manifest
ManifestCheck = Dir(strManifest, vbNormal + vbSystem + vbHidden + vbReadOnly + vbArchive) 'check the app manifest file.
If ManifestCheck = "" Or CreateNew = True Then           'if not found.. make a new one
XML = Replace(XML, "EXENAME", App.EXEName & ".exe")             'Replaces the string "EXENAME" with the program's exe file name.
XML = Replace(XML, "EXEVERSION", App.Major & "." & App.Minor & "." & App.Revision & ".0") 'Replaces the "EXEVERSION" string.
XML = Replace(XML, "EXEDESCRIBTION", App.FileDescription)       'Replaces the app Describtion.
FreeFileNo = FreeFile      
If ManifestCheck <> "" Then
SetAttr strManifest, vbNormal
Kill strManifest
End If
Open strManifest For Binary As #(FreeFileNo) 'open the file
Put #(FreeFileNo), , XML    'uses 'put' to set the file content.. note that 'put' (binary mode) is much faster than 'print'(output mode)
Close #(FreeFileNo)         'close the file.
SetAttr strManifest, vbHidden + vbSystem
If ManifestCheck = "" Then
XXXX = False            
Else
XXXX = True
End If
If AutoRestart = True Then  
Shell App.Path & "\" & App.EXEName & ".exe " & Command$, vbNormalFocus  'restart the program and bypass command line parameters (if any)
End                         
End If
Else                'the manifest file exists.
XXXX = True      'return true.
End If
End Function

Now, I’m sure this code functions just fine and is probably quite useful, but how can even the guy that wrote this come back and read it, quickly, 6 months from now?

I indented the same code and took screen shots to compare them side by side (the highlighter is mine):

CodeNoIndent CodeIndent

Note how the highlighter (and your eye) is naturally drawn into the curves of the indentation.

By comparison, the unindented code yields a straight line. There are no clues to tell your eyes where to look.

A guiding principle in feng shui is that straight lines are generally bad. Many books on the subject call them poison arrows because, it’s believed, straight lines tend to direct negative chi (energy) toward whatever they’re pointing at.

In the same way that you generally do not want an arrow straight walkway directly from the street to your front door, you do not want an arrow straight eyeball walkway that directs the eye right by the code it’s supposed to be reading.

Long story short, it’s good to be a lazy programmer, but it’s certainly possible to be too lazy.

Visual Basic’s got a bit of a bad rap as it is. A little less of this might go a long way towards helping that.