Click here to Skip to main content
11,435,451 members (59,551 online)
Click here to Skip to main content

Automatic highlighting of matching braces for Visual Studio C++

, 5 Nov 2008 GPL3
Rate this:
Please Sign up or sign in to vote.
This add-in enables highlighting of matching braces next to the cursor for Visual Studio C++.

Introduction

The Visual Studio 2008 C++ text editor only highlights matching braces if written the first time. Almost all text editors have the feature of highlighting matching braces if you put the cursor near to an open or close brace (even the Visual Studio C# editor). This add-in will provide this feature for C++ too. (Tested with Visual Studio 2008; for 2005, you need to change the version information in the "MatchingBraces.AddIn" file from 9.0 to 8.0).

Using the Add-in

  1. Just copy the contents of the "readyplugin" folder to "C:\Users\Username\Documents\Visual Studio 2008\Addins". Restart Visual Studio.
  2. Put the cursor on the right side of a brace (one of: '{[()]}'). If the brace has a matching one, both braces will be highlighted with a bold font.

Source Code Overview

  • Get mouse and keyboard events:

    To get the add-in working, we first need to get notified if the user has moved the cursor somewhere inside the text editor using the mouse or the keyboard. The Visual Studio Add-in API does not provide a functionality for mouse events. It is necessary to use a Window Hook using the SetWindowsHookEx() function. The built-in TextDocumentKeyPressEvents does not work with the arrow keys. For these keys, a keyboard hook is needed:

    private void InitHook()
    {
      //init the mouse and keyboard hook 
      //with the thread id of the Visual Studio IDE
      uint id = GetCurrentThreadId();
      this.MouseProcDelegate = new HookProc(this.MouseProc);
      mhhook = SetWindowsHookEx(WH_MOUSE, 
               this.MouseProcDelegate, IntPtr.Zero, id);
      this.KeyboardProcDelegate = 
           new HookProcKeyboard(this.KeyboardProc);
      khook = SetWindowsHookEx(WH_KEYBOARD, 
              this.KeyboardProcDelegate, IntPtr.Zero, id);
    }

    To make use of SetWindowsHookEx(), it is necessary to use the Platform Invoke stuff. If the user released a key or released a mouse button, the MouseProc (or KeyboardProc) 'function' will be called before the event reaches the Visual Studio window.

  • Do something with the event (here keyboard):

    If KeyboardProc is called, we only know that a key is released somewhere. First, we need to make sure that a document is open and that the document is a C++ source code:

    private int KeyboardProc(int code, IntPtr wParam, IntPtr lParam)
    {
      try
      {
        if (code != HC_ACTION)
        {
          return CallNextHookEx(khook, code, wParam, lParam);
        }
    
        //only with a C++ document open
        if (_applicationObject.ActiveDocument == null ||
            _applicationObject.ActiveDocument.Language != "C/C++")
        {
          return CallNextHookEx(mhhook, code, wParam, lParam);
        }

    Next, we need to check if the event occurred inside the editor window and not somewhere else:

       //check if the editor window has the keyboard focus
       IntPtr h = GetFocus();
       if (!isEditorWindow(h))
       {
         return CallNextHookEx(mhhook, code, wParam, lParam);
       } 
    
    [...]
    
     private static bool isEditorWindow(IntPtr hWnd)
     {
       IntPtr res;
       StringBuilder ClassName = new StringBuilder(256);
       res = GetClassName(hWnd, ClassName, ClassName.Capacity);
       if (res != IntPtr.Zero)
       {
         if (ClassName.ToString() == "VsTextEditPane")
         {
           return true;
         }
       }
       return false;
     }

    This is the case if the keyboard focus belongs to a window with the class "VsTextEditPane".

    Next, we are (almost) ready to highlight the matching braces:

    private void Highlight()
    {
      try
      {
        TextSelection ts = 
          (TextSelection)_applicationObject.ActiveDocument.Selection;
          if (!ts.IsEmpty)
          {
            return;
          }
            
        //create an edit point on the current cursor position
        EditPoint ep = ts.ActivePoint.CreateEditPoint();
            
    
        //get the letter on the left side of the cursor
        String s = ep.GetText(-1);
            
        //check if it is one of the braces: '{[( }])'
        String pattern = "({|}|\\[|\\]|\\(|\\))";
        if (System.Text.RegularExpressions.Regex.IsMatch(s, pattern))
        {
          //select the brace and rewrite it, 
          //this will trigger the matching braces 
          //functionality from Visual Studio
          ts.CharLeft(true, 1);
          ts.Text = s;
        }
      }
      catch
      {
      }
    }

    Of course, it is first necessary to check if the cursor (returned by ts.ActivePoint.CreateEditPoint()) is on the right side of a brace, using GetText(-1) and a Regex which will match for all braces. If 'Yes', the brace will be selected using ts.CharLeft(true, 1) and replaced with a new one. This will trigger the built-in brace matching functionality of Visual Studio.

  • Avoid adding the input of the braces into the undo-list:

    Everything between the call of _applicationObject.UndoContext.Open() and _applicationObject.UndoContext.SetAborted() will not be visible in the undo-list.

  • Avoid visible page scrolling:

    After calling UndoContext.SetAborted(), the cursor will jump to the last position before UndoContext.Open() was called. It is necessary to move the page back to the current position. To hide this movement from the user, it is necessary to forbid the updating of the editor window by using: SendMessage(EditorWindowHwnd, WM_SETREDRAW, (IntPtr)0, (IntPtr)0). If everything is finished, window updating could be re-enabled using SendMessage(EditorWindowHwnd, WM_SETREDRAW, (IntPtr)1, (IntPtr)0).

Limitations

The add-in needs to rewrite the brace. This modifies the text as long as the cursor is near a brace. If you move the cursor away, the text is not modified anymore.

Conclusion

This is an essential feature for every text editor.

History

  • 0.3:
    • new version fixing problem with visible page scrolling
  • 0.2:
    • The add-in no longer modifies the undo-list.
    • The text is only modified as long as the cursor is near a brace.
    • Lot of internal changes.
  • 0.1:
    • Initial release.

License

This article, along with any associated source code and files, is licensed under The GNU General Public License (GPLv3)

Share

About the Author

Jochen Baier

Germany Germany
No Biography provided

Comments and Discussions

 
GeneralNo Wordwrap & Braces are deselected randomly in VS2005 [modified] Pin
fuzibuni4-Mar-11 3:27
memberfuzibuni4-Mar-11 3:27 
GeneralRe: No Wordwrap & Braces are deselected randomly in VS2005 Pin
Jochen Baier5-Mar-11 5:59
memberJochen Baier5-Mar-11 5:59 
GeneralCannot work with source controlled files Pin
Member 475432621-Apr-10 9:13
memberMember 475432621-Apr-10 9:13 
GeneralRe: Cannot work with source controlled files Pin
Jochen Baier6-May-10 11:14
memberJochen Baier6-May-10 11:14 
GeneralRe: Cannot work with source controlled files Pin
Member 823582127-Sep-11 21:21
memberMember 823582127-Sep-11 21:21 
GeneralVisual Studio 2008 german Pin
Honkoid11-Feb-10 14:44
memberHonkoid11-Feb-10 14:44 
GeneralRe: Visual Studio 2008 german Pin
Jochen Baier11-Feb-10 20:28
memberJochen Baier11-Feb-10 20:28 
GeneralRe: Visual Studio 2008 german Pin
Honkoid12-Feb-10 5:55
memberHonkoid12-Feb-10 5:55 
GeneralRe: Visual Studio 2008 german Pin
Jochen Baier12-Feb-10 23:46
memberJochen Baier12-Feb-10 23:46 
GeneralRe: Visual Studio 2008 german Pin
Honkoid23-Feb-10 15:50
memberHonkoid23-Feb-10 15:50 
Questionsource version Pin
doktorekx23-Dec-09 11:06
memberdoktorekx23-Dec-09 11:06 
AnswerRe: source version Pin
Jochen Baier23-Dec-09 11:45
memberJochen Baier23-Dec-09 11:45 
GeneralRe: source version Pin
doktorekx23-Dec-09 12:15
memberdoktorekx23-Dec-09 12:15 
GeneralAwesome! Pin
visualstudiowang23-Oct-09 13:00
membervisualstudiowang23-Oct-09 13:00 
GeneralAuto-Generated End-Brace Comment Pin
kjward30-Sep-09 3:11
memberkjward30-Sep-09 3:11 
GeneralRe: Auto-Generated End-Brace Comment Pin
Jochen Baier2-Oct-09 5:36
memberJochen Baier2-Oct-09 5:36 
GeneralModified for Visual Basic: Works in VS2008 but not VS2005 Pin
Bruce Farmer21-Sep-09 10:27
memberBruce Farmer21-Sep-09 10:27 
GeneralRe: Modified for Visual Basic: Works in VS2008 but not VS2005 Pin
kjward29-Sep-09 5:18
memberkjward29-Sep-09 5:18 
GeneralRe: Modified for Visual Basic: Works in VS2008 but not VS2005 Pin
Bruce Farmer29-Sep-09 5:38
memberBruce Farmer29-Sep-09 5:38 
GeneralRe: Modified for Visual Basic: Works in VS2008 but not VS2005 Pin
kjward29-Sep-09 5:58
memberkjward29-Sep-09 5:58 
GeneralRe: Modified for Visual Basic: Works in VS2008 but not VS2005 Pin
Bruce Farmer29-Sep-09 8:55
memberBruce Farmer29-Sep-09 8:55 
GeneralMy vote of 1 Pin
salocin_2-Jul-09 4:50
membersalocin_2-Jul-09 4:50 
GeneralVS2008 SP1 Pin
VEMS30-Apr-09 3:15
memberVEMS30-Apr-09 3:15 
Questionchances to get this working with visual basic in VS 2k8 as well? Pin
tomtom19802-Apr-09 22:20
membertomtom19802-Apr-09 22:20 
GeneralColor Highliight [modified] Pin
ameliaamelia26-Mar-09 16:57
memberameliaamelia26-Mar-09 16:57 
GeneralVery useful Pin
sprice8620-Feb-09 3:50
membersprice8620-Feb-09 3:50 
QuestionCan this work for .Net 2003? It seems not to! Pin
Jelena Curcic12-Feb-09 22:46
memberJelena Curcic12-Feb-09 22:46 
Questionnot working in Visual C++ Express Pin
torys26-Oct-08 15:13
membertorys26-Oct-08 15:13 
AnswerRe: not working in Visual C++ Express Pin
Jochen Baier28-Oct-08 1:51
memberJochen Baier28-Oct-08 1:51 
AnswerRe: not working in Visual C++ Express Pin
Qwertie11-Nov-08 10:53
memberQwertie11-Nov-08 10:53 
GeneralRe: not working in Visual C++ Express Pin
torys15-Nov-08 7:00
membertorys15-Nov-08 7:00 
QuestionNice idea, but how about something more useful? Pin
tonyt27-Sep-08 14:34
membertonyt27-Sep-08 14:34 
AnswerRe: Nice idea, but how about something more useful? Pin
Jochen Baier27-Sep-08 14:52
memberJochen Baier27-Sep-08 14:52 
QuestionHow to install into VS2005 Pin
lefis15-Sep-08 23:26
memberlefis15-Sep-08 23:26 
AnswerRe: How to install into VS2005 Pin
pulp_434649416-Sep-08 3:43
memberpulp_434649416-Sep-08 3:43 
GeneralGood idea, except for... Pin
Robo1-Sep-08 3:48
memberRobo1-Sep-08 3:48 
GeneralRe: Good idea, except for... Pin
pulp_43464941-Sep-08 15:56
memberpulp_43464941-Sep-08 15:56 
GeneralRe: Good idea, except for... Pin
Robo2-Sep-08 22:41
memberRobo2-Sep-08 22:41 
GeneralThe file is changed when the bracket is highlighted Pin
Member 49072431-Aug-08 21:38
memberMember 49072431-Aug-08 21:38 
GeneralRe: The file is changed when the bracket is highlighted Pin
pulp_43464941-Sep-08 15:50
memberpulp_43464941-Sep-08 15:50 
Generalporting to VS 2005 Pin
alterloewe31-Aug-08 8:54
memberalterloewe31-Aug-08 8:54 
GeneralRe: porting to VS 2005 Pin
pulp_434649431-Aug-08 9:05
memberpulp_434649431-Aug-08 9:05 
GeneralRe: porting to VS 2005 Pin
alterloewe31-Aug-08 20:57
memberalterloewe31-Aug-08 20:57 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web04 | 2.8.150428.2 | Last Updated 5 Nov 2008
Article Copyright 2008 by Jochen Baier
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid