Attention to Documentation

Our User Education staff at Data Dynamics is doing great things right now. We have a very active documentation staff that is constantly striving to create better walk throughs and more informative reference manuals for all of our products. Help files are linked up with individual members directly from the code window or designer. The information that we provide on simple intellisense answers users questions while they are coding. If it doesn’t, simply select the object, function, property, or event and press [F1]. We'll take you to where you need to go to get the most information. If that doesn’t answer your question, we provide you with all relevant links to where you can get more help.

This is one area that I feel really makes or breaks any software product that I buy. I use [F1] all the time! If the help files are crap, the software is crap. I've seen good documentation and I've seen bad documentation. I am more than likely to stick with an application (or component) if the documentation treats me like a 4 year old. I don't want help files that have one liners and a link. I want help files that are there to help me use the product with as much information as I can soak up. I find myself getting engulfed in good documentation sometimes for hours. I have never found myself spending more than 5 minute with bad documentation.

 

Today I found a topic in our ActiveBar 3.0 help file that really concerned me. The topic itself was very informative and really explained the information quite well. My concern was with the code snippet that we supplied with it. This code has probably been in our documentation since ActiveBar was first released and I'm sure it has been modified over and over from each version. Basically, the sample code itself was so confusing that I found myself following the logic just to see what it "should" do. I eventually started up a new VB6 project just to see what this mess of code was supposed to do. Once I discovered what it was doing, I stepped back and realized that the code did absolutely nothing for me from within the help file. The help file didn't explain what the code was supposed to do and the code was scattered with so many variables that I got away from what I went to the help file for… that could have been my A.D.D. kicking in though…? Nonetheless, the fact that I had a problem with the code led me to believe that first time users of our products would have an even harder time understanding its purpose.

Here is what it was:

' Type structure

Option Explicit

 

Private Type POINTAPI

    X As Long

    Y As Long

End Type

 

' API function

Private Declare Function ClientToScreen Lib "user32" (ByVal hwnd As Long, ByVal lpPOINT As POINTAPI) As Long

 

Private Sub List1_MouseUp(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)

    Dim Pt As POINTAPI

    Dim lRC As Long

    Dim X1 As Long, Y1 As Long

    Dim X2 As Long, Y2 As Long

    Dim X3 As Long, Y3 As Long

 

    If Button <> vbRightButton Then Exit Sub

 

    ' convert Pt to mouse position in screen pixels

    Pt.X = X / Screen.TwipsPerPixelX

    Pt.Y = Y / Screen.TwipsPerPixelY

 

    lRC = ClientToScreen(List1.hwnd, Pt)

 

    If lRC = 0 Then Stop ' error

 

 

    ' convert x1/y1 to mouse position in client twips

    X1 = Pt.X * Screen.TwipsPerPixelX

    Y1 = Pt.Y * Screen.TwipsPerPixelY

 

    ' convert Pt to List Position in client pixels

    Pt.X = List1.Left / Screen.TwipsPerPixelX

    Pt.Y = List1.Top / Screen.TwipsPerPixelY

 

    ' convert pt to list position in screen pixels

    lRC = ClientToScreen(Form1.hwnd, Pt)

 

    If lRC = 0 Then Stop ' error

 

    ' convert x2,y2 to list position in screen twips

 

    X2 = Pt.X * Screen.TwipsPerPixelX

    Y2 = Pt.Y * Screen.TwipsPerPixelY

 

    ' convert pt to list right/bottom in screen pixels

    Pt.X = (X2 + List1.Width) / Screen.TwipsPerPixelX

    Pt.Y = (Y2 + List1.Height) / Screen.TwipsPerPixelY

 

    ' convert x3,y3 to list right/bottom in screen twips

    X3 = Pt.X * Screen.TwipsPerPixelX

    Y3 = Pt.Y * Screen.TwipsPerPixelY

 

    ActiveBar31.Bands("tbContext").PopupMenuEx(0, X1, Y1, X2, Y2, X3, Y3)

 

End Sub


Can you tell what that code is supposed to do?

Here is the new proposed snippet:

 

Option Explicit

 

' Type structure

Private Type POINTAPI

    X As Long

    Y As Long

End Type

 

' Declare the ClientToScreen API function from the user32 library.

Private Declare Function ClientToScreen Lib "user32" (ByVal hwnd As Long, ByVal lpPOINT As POINTAPI) As Long

 

Private Sub List1_MouseUp(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)

 

    Dim bandPosition As POINTAPI ' - used for displaying band at mouse

    Dim topLeftBounds As POINTAPI ' - defines the top left 'No Dismissal' coordinate

    Dim bottomRightBounds As POINTAPI ' - defines the bottom right 'No Dismissal' coordinate

    Dim point As POINTAPI ' - used in all calculations

    Dim returnValue As Long ' - used for "user32" function calls

 

    ' right click?

    If Button <> vbRightButton Then Exit Sub

 

    ' *************************************************************

    ' step 1 : find the x and y coordinates to popup the band.

    ' *************************************************************

 

    ' convert X and Y parameters to pixels

    point.X = X / Screen.TwipsPerPixelX

    point.Y = Y / Screen.TwipsPerPixelY

 

    ' compute x and y coordinates

    returnValue = ClientToScreen(List1.hwnd, point)

 

    ' if the return value is 0, throw an error

    If returnValue = 0 Then Err.Raise(vbObjectError + 1001, "List1", "ClientToScreen")

 

    ' convert x and y back to twips

    bandPosition.X = point.X * Screen.TwipsPerPixelX

    bandPosition.Y = point.Y * Screen.TwipsPerPixelY

 

    ' *************************************************************

    ' step 2 : find the top left boundary of no-dismissal

    ' *************************************************************

 

    ' convert List1 position to pixels.

    point.X = List1.Left / Screen.TwipsPerPixelX

    point.Y = List1.Top / Screen.TwipsPerPixelY

 

    ' compute x and y coordinates

    returnValue = ClientToScreen(Form1.hwnd, point)

 

    ' if the return value is 0, throw an error

    If returnValue = 0 Then Err.Raise(vbObjectError + 1001, "Form1", "ClientToScreen")

 

    ' convert List1 position back to twips

    topLeftBounds.X = point.X * Screen.TwipsPerPixelX

    topLeftBounds.Y = point.Y * Screen.TwipsPerPixelY

 

    ' *************************************************************

    ' step 3 : calculate the bottom right boundary of no-dismissal

    ' *************************************************************

 

    ' calculate right and bottom position

    bottomRightBounds.X = topLeftBounds.X + List1.Width

    bottomRightBounds.Y = topLeftBounds.Y + List1.Height

 

    ' *************************************************************

    ' step 3 : display the band using calculated coordinates

    ' *************************************************************

    ActiveBar31.Bands("contextToolbar").PopupMenuEx(0, _

        bandPosition.X, bandPosition.Y, _

        topLeftBounds.X, topLeftBounds.Y, _

        bottomRightBounds.X, bottomRightBounds.Y)

 

End Sub

 

Can you tell what this is supposed to do?


The code is much cleaner; it has step by step comments that walk the user through exactly what the code is doing. Also, the variables describe what they do and each coordinate conversion is explained. There are no more X1, X2, Y3, etc… Instead the code uses the POINTAPI to store these variables which really helped the flow of the code as it worked with actual camelCased variable names. The end result is much cleaner and the user can see exactly what is happening at each step of the way. Notice the X3 and Y3 calculation is much easier too.

Print | posted on Thursday, June 22, 2006 3:55 PM