September 2, 2014
Hot Topics:
RSS RSS feed Download our iPhone app

XML Documents from Comments

  • January 8, 2008
  • By Paul Kimmel
  • Send Email »
  • More Articles »

By typing ''' (three apostrophes), the IDE will generate the <summary> and <remarks> tags. If the commented item is a function, a <param> tag with the name attribute will be generated for each argument. Also, if the commented member is a function, the <returns> tag will be generated. (See any method for examples of <summary> and <remarks>. Refer to BlockAltTab for an example of the <returns> tag, and see TestForm_Load for examples of <param>.

The <summary> block represents straight code comments. The <remarks> tag can used to add cross references with the <seealso> tag and cref attribute. (See BlockAltEscape for an example of <seealso>. The <param> tag has a name attribute indicating the name of the parameter, and the <returns> tag is empty. You can specify the type that the function returns by typing it in between the opening and closing <returns></returns> tag pair.

Indicating an Exception that Can be Thrown

There are many kinds of tags you can add to your comments. The complete list is described in the MSDN help top "Recommended XML Tags for Documentation Comments." For example, if a function throws an exception as does KeyboardHooker.CheckedHooked, you can indicate that in the comments with the <exception> tag. (See Listing 2 for the KeyboardHooker class.)

Listing 2: The KeyboardHooker class demonstrates how to comment various kinds of code elements as well as introduces the <exception> tag with a cref attribute.

Option Strict Off


Imports System.Runtime.InteropServices
Imports System.Reflection
Imports System.Windows.Forms
Imports System.Diagnostics

''' <summary>
''' A wrapper for Windows API methods for low-level keyboard hooks.
''' </summary>
''' <remarks></remarks>
PublicClass KeyboardHooker

   ''' <summary>
   ''' An API method to restore the keyboard event handling chain
   ''' </summary>
   ''' <param name="hHook"></param>
   ''' <returns></returns>
   ''' <remarks></remarks>
   Public Declare Auto Function UnhookWindowsHookEx Lib "user32" _
      (ByVal hHook As Integer) As Integer

   ''' <summary>
   ''' An extended API method to hook the keyboard
   ''' </summary>
   ''' <param name="idHook"></param>
   ''' <param name="lpfn">Use System.Runtime.InteropServices.
   ''' MarshalAs for pointers</param>
   ''' <param name="hmod"></param>
   ''' <param name="dwThreadId"></param>
   ''' <returns></returns>
   ''' <remarks></remarks>
   Public Declare Auto Function SetWindowsHookEx Lib "User32" _
      Alias "SetWindowsHookExA" ( _
      ByVal idHook As Integer, _
      <MarshalAs(UnmanagedType.FunctionPtr)> _
      ByVal lpfn As KeyboardHookDelegate, _
   ByVal hmod As Integer, ByVal dwThreadId As Integer) As Integer

   ''' <summary>
   ''' Gets the asynchronous keyboard state for detecting Ctrl key
   ''' combinations and such
   ''' </summary>
   ''' <param name="vKey"></param>
   ''' <returns></returns>
   ''' <remarks></remarks>
   Private Declare Function GetAsyncKeyState Lib "user32" _
      (ByVal vKey As Integer) As Integer

   ''' <summary>
   ''' Used to call the next eyboard handler in the chain. By not
   ''' calling this we effectively block other applications from
   ''' getting keyboard events
   ''' </summary>
   ''' <param name="hHook"></param>
   ''' <param name="nCode"></param>
   ''' <param name="wParam"></param>
   ''' <param name="lParam"></param>
   ''' <returns></returns>
   ''' <remarks></remarks>
   Private Declare Function CallNextHookEx Lib "user32" _
      (ByVal hHook As Integer, _
      ByVal nCode As Integer, _
      ByVal wParam As Integer, _
      <MarshalAs(UnmanagedType.Struct)> _
      ByVal lParam As KBDLLHOOKSTRUCT) As Integer

   ''' <summary>
   ''' The structure representing the keyboard state when the
   ''' low-level keyboard handler is called
   ''' </summary>
   ''' <remarks></remarks>
   Public Structure KBDLLHOOKSTRUCT
      Public vkCode As Integer
      Public scanCode As Integer
      Public flags As Integer
      Public time As Integer
      <MarshalAs(UnmanagedType.U8)> _
      Public dwExtraInfo As Long
   End Structure


   ''' <summary>
   ''' Low-level keybard constants. These values
   ''' can go in the KBDLLHOOKSTRUCT.flags field
   ''' </summary>
   ''' <remarks><seealso cref="KBDLLHOOKSTRUCT"/></remarks>
   Private Const HC_ACTION = 0
   ''' <summary>
   ''' Bitmask to check for extended keys
   ''' </summary>
   ''' <remarks></remarks>
   Private Const LLKHF_EXTENDED = &H1
   ''' <summary>
   ''' Test the event-injected flag
   ''' </summary>
   ''' <remarks></remarks>
   Private Const LLKHF_INJECTED = &H10
   ''' <summary>
   ''' Test the context code
   ''' </summary>
   ''' <remarks></remarks>
   Private Const LLKHF_ALTDOWN = &H20
   ''' <summary>
   ''' Set the transition state
   ''' </summary>
   ''' <remarks></remarks>
   Private Const LLKHF_UP = &H80

   ''' <summary>
   ''' Represents the tab key
   ''' </summary>
   ''' <remarks></remarks>
   Public Const VK_TAB = &H9
   ''' <summary>
   ''' Represents the control key
   ''' </summary>
   ''' <remarks></remarks>
   Public Const VK_CONTROL = &H11
   ''' <summary>
   ''' Represents the escape key
   ''' </summary>
   ''' <remarks></remarks>
   Public Const VK_ESCAPE = &H1B
   ''' <summary>
   ''' Represents the delete key
   ''' </summary>
   ''' <remarks></remarks>
   Public Const VK_DELETE = &H2E

   ''' <summary>
   ''' The function value to pass to idHook for the
   ''' SetWindowsHookEx API
   ''' </summary>
   ''' <remarks><seealso cref="SetWindowsHookEx"/></remarks>
   Private Const WH_KEYBOARD_LL = 13&
   ''' <summary>
   ''' Keyboard hook handle return by SetWindowsHookEx.
   ''' We're hooked if the value return is not 0
   ''' </summary>
   ''' <remarks><seealso cref="SetWindowsHookEx"/></remarks>
   Public KeyboardHandle AsInteger

   ''' <summary>
   ''' An instance of the IHooker interface, representing the
   ''' thing that will repsond to keyboard events {i.e. the form
   ''' in our example}
   ''' </summary>
   ''' <remarks></remarks>
   Public Hooker As IHooker

   ''' <summary>
   ''' Scans the Hookstruct to figure out what combinations of
   ''' keys are pressed
   ''' </summary>
   ''' <param name="Hookstruct"></param>
   ''' <returns></returns>
   ''' <remarks></remarks>
   Public Function IsHooked(ByRef Hookstruct As KBDLLHOOKSTRUCT) _
      AsBoolean

      Debug.WriteLine(Hookstruct.vkCode.ToString())


      If (Hookstruct.vkCode = VK_ESCAPE) And _
         CBool(GetAsyncKeyState(VK_CONTROL) _
         And &H8000) Then

         Call HookedState(Hooker.BlockControlEscape,
            "Ctrl + Esc blocked")
         Return Hooker.BlockControlEscape
      End If

      If (Hookstruct.vkCode = VK_TAB) And _
         CBool(Hookstruct.flags And _
         LLKHF_ALTDOWN) Then

         Call HookedState(Hooker.BlockAltTab, "Alt + Tab blocked")
         Return Hooker.BlockAltTab
      End If


      If (Hookstruct.vkCode = VK_ESCAPE) And _
         CBool(Hookstruct.flags And _
            LLKHF_ALTDOWN) Then

         Call HookedState(Hooker.BlockAltEscape,
            "Alt + Escape blocked")
         Return Hooker.BlockAltEscape
      End If

   End Function

   ''' <summary>
   ''' Checks to determine if we are hooked, sending output to the
   ''' debug window.
   ''' </summary>
   ''' <param name="Hooked"></param>
   ''' <param name="Text"></param>
   ''' <remarks>If we use a messagebox then the hook chain is
   ''' goofed up by that window</remarks>
   Private Sub HookedState(ByVal Hooked As Boolean, _
                           ByVal Text As String)
   If (Hooked) Then
      'MessageBox.Show(Text) -' lets the key stroke go through
      Debug.Print(Text)
   End If
   End Sub

   ''' <summary>
   ''' The wrapper's event handler to catch keyboard events and
   ''' pass that information to the IsHooked method for specific
   ''' combinations
   ''' </summary>
   ''' <param name="Code"></param>
   ''' <param name="wParam"></param>
   ''' <param name="lParam"></param>
   ''' <returns>Integer</returns>
   ''' <remarks>If we don't call CallNextHookEx then the keys are
   ''' blocked</remarks>
   Public Function KeyboardCallback(ByVal Code As Integer, _
      ByVal wParam As Integer, ByRef lParam _
         As KBDLLHOOKSTRUCT) _As Integer

      If (Code = HC_ACTION) Then
         If (IsHooked(lParam)) Then
            Return 1
         End If
      End If

      Return CallNextHookEx(KeyboardHandle, _
         Code, wParam, lParam)

   End Function

   ''' <summary>
   ''' A definition of our keyboard event handler
   ''' </summary>
   ''' <param name="Code"></param>
   ''' <param name="wParam"></param>
   ''' <param name="lparam"></param>
   ''' <returns></returns>
   ''' <remarks></remarks>
   Public Delegate Function KeyboardHookDelegate( _
      ByVal Code As Integer, ByVal wParam As Integer, _
      ByRef lparam As KBDLLHOOKSTRUCT) As Integer

   ''' <summary>
   ''' The instance of the keyboard event handler we pass this
   ''' as lpfn (the function pointer) to SetWindowsHookEx
   ''' </summary>
   ''' <remarks><seealso cref="HookKeyboard"/></remarks>

   <MarshalAs(UnmanagedType.FunctionPtr)> _
   Private callback As KeyboardHookDelegate


   Public Sub HookKeyboard()
      callback = New _
         KeyboardHookDelegate(AddressOf KeyboardCallback)

      KeyboardHandle = SetWindowsHookEx( _
         WH_KEYBOARD_LL, callback, _
         Marshal.GetHINSTANCE([Assembly]. _
         GetExecutingAssembly.GetModules()(0)).ToInt32(), 0)
      Call CheckHooked()
   End Sub

   ''' <summary>
   ''' Were we able to hook the keyboard
   ''' </summary>
   ''' <remarks></remarks>
   ''' <exception cref="Exception">Exception</exception>
   Public Sub CheckHooked()
      If (Hooked()) Then
         Debug.Print("Keyboard hooked")
      Else
         Debug.Print("Keyboard hook failed: " & Err.LastDllError)
         Throw New Exception("Keyboard hook failed")
      End If
   End Sub

   ''' <summary>
   ''' Test to see if the handle is 0 or not. Non-zero means
   ''' the keyboard was hooked
   ''' </summary>
   ''' <returns></returns>
   ''' <remarks></remarks>
   Private Function Hooked()
      Hooked = KeyboardHandle <> 0
   End Function

   ''' <summary>
   ''' Unhook the keybaord and restore the chain as it was before
   ''' we changed it
   ''' </summary>
   ''' <remarks></remarks>
   Public Sub UnhookKeyboard()
      If (Hooked()) Then
         Call UnhookWindowsHookEx(KeyboardHandle)
      End If
   End Sub

End Class




Page 2 of 3



Comment and Contribute

 


(Maximum characters: 1200). You have characters left.

 

 


Sitemap | Contact Us

Rocket Fuel