Create a Visual Studio extension to generate the C ++ #define directive in the header file

    Good afternoon.
    We will do a Visual Studio extension that embeds the “Create C ++ Header #define” field in the context menu of the editor, when clicked, a unique #define directive is generated (the directive allows you to include the header only once).
    Ultimately, it will look like this:



    In fact, it is usually automated using the macros of the studio itself (and there are many macro options on the network), but I’m more pleased to use the context menu, especially since creating the extension itself is simple, it will do all the work VSPackage Builder, we only need to enter a few lines of code into the handler for clicking a menu item.


    So, let's begin. We will need Visual Studio 2010 Pro or later. It is necessary to additionally installVisual Studio 2010 SDK and a special add-on VSPackage Builder , making it as easy as possible to create new extensions.

    Create extension


    Create a new project in Visual Studio:
    Visual C # -> Extensibility -> VSPackage Builder
    Give the project a name - I named it HeaderDefineCreater.



    In the opened project, we will place all the elements we need on the extension designer (HeaderDefineCreater.vspackage file). Let's start with the first element - add a context menu. In its properties, opposite the Location field, select the location - “Context Menu | Editor »



    Then create a Group, one button (let's call it CreateHeaderDefineButton) and two connections between all elements. The screenshot on the left shows the properties for the button. Everything is standard there, unless you should pay attention that the button (i.e. the line in the context menu) will be visible only in the editor ( Visibility Constraints: TextEditor) As for the shortcut, these fields can be left empty, because they can be configured separately when using the extension.



    Well, everything is ready. It remains only to fill out the handler for clicking on the context menu item.
    An automatically generated click handler looks like this:
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Runtime.InteropServices;
    using Microsoft.VisualStudio;
    using Microsoft.VisualStudio.Shell.Interop;
    using Microsoft.VisualStudio.OLE.Interop;
    using Microsoft.VisualStudio.Shell;
    namespace HeaderDefineCreater
    {
        [Guid(GuidList.guidHeaderDefineCreaterPkgString)]
        public class HeaderDefineCreaterPackage : HeaderDefineCreaterPackageBase
        {
            protected override void CreateHeaderDefineButtonExecuteHandler(object sender, EventArgs e)
            {
            }
        }
    }
    


    Fill the handler. There are many similar functionality macros for the studio, written in VB, so I didn’t have to invent anything myself, I just rewrote it a bit in C #.

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Runtime.InteropServices;
    using Microsoft.VisualStudio;
    using Microsoft.VisualStudio.Shell.Interop;
    using Microsoft.VisualStudio.OLE.Interop;
    using Microsoft.VisualStudio.Shell;
    // Импортируем еще 3 пространства имен:
    using System.Windows.Forms;
    using EnvDTE;
    using System.IO;
    namespace HeaderDefineCreater
    {
        [Guid(GuidList.guidHeaderDefineCreaterPkgString)]
        public class HeaderDefineCreaterPackage : HeaderDefineCreaterPackageBase
        {
            protected override void CreateHeaderDefineButtonExecuteHandler(object sender, EventArgs e)
            {
                try
                {
                    // Получим объект верхнего уровня в объектной модели автоматизации Visual Studio
                    EnvDTE.DTE dte = (EnvDTE.DTE)GetService(typeof(EnvDTE.DTE));
                    // Получим название без расширения у активного документа в Visual Studio
                    String fileName = Path.GetFileNameWithoutExtension(dte.ActiveDocument.Name);
                    // Приведем название к прописным буквам
                    fileName = fileName.ToUpper();
                    // Сгенерируем уникальный идентификатор GUID
                    String strGuid = System.Guid.NewGuid().ToString().ToUpper();
                    strGuid = strGuid.Replace("-", "_");
                    // Объединим название файла и идентификатор GUID 
                    String strDefine = fileName + "_" + strGuid;
                    // Создадим саму надпись, которая будет выведена в документе
                    string txt = "";
                    txt += "\n#ifndef " + strDefine;
                    txt += "\n#define " + strDefine;
                    txt += "\n\n\n\n\n#endif // " + strDefine;
                    txt += "\n";
                    // Выведем надпись в активный документ
                    TextSelection textSelection = (TextSelection)dte.ActiveDocument.Selection;
                    textSelection.Text = txt;
                }
                catch (Exception ex)
                {
                    // Если что-то пошло не так, то просто покажем сообщение об ошибке и не уроним студию...
                    MessageBox.Show(ex.Message);
                }
            }
        }
    }
    


    We just have to fill in the fields in the manifest (add an icon, description, etc.) and compile everything.



    After compilation, we get the finished extension HeaderDefineCreater.vsix.

    Install extension and change shortcuts


    The extension is installed with a simple double click.
    You can delete it by going to Tools-> Extension Manager .



    In order to set a shortcut for an extension, you need to go to Tools -> Options -> Keyboard , find the name of the button there by search (we called the button CreateHeaderDefineButton, but, for simplicity, we could also name it the extension name). For the found button, put any free combination:



    Thanks for attention. Comments are welcome. I note that I do not write in C #, but I study C ++ and the extension was created primarily to facilitate routine operations on pluses and for internal use. I think that a name for the context menu field could have been better ... and the icon does not correspond to the content :) But here I just wanted to show how to quickly create my extension, I hope it will be useful to someone else.

    I did not post the whole project here, because the extension is very simple, all the steps are described, and all the code in the click handler is also laid out here. Therefore, I will attach for example only the extension itself, which turned out as a result - HeaderDefineCreater.vsix

    Also popular now: