NppCppMSVS: Visual Studio Project Template for a Notepad++ C++ Plugin

Introduction

NppCppMSVS is a template for Microsoft Visual Studio which you can use to build C++ plugins for Notepad++. Like Notepad++, this template is released under the GNU General Public License (either version 3 of the License, or, at your option, any later version).

This template uses JSON for Modern C++ by Niels Lohmann, which is released under the MIT license.

This documentation, copyright ©2025 by Randy Fellmy, is provided under the Creative Commons Attribution 4.0 license. The author waives attribution and notice of modification requirements when this document is used as a model for the purpose of creating help for your own projects.

Purpose and use

This project is not a part of Notepad++ and is not endorsed by the author of Notepad++.

This template includes framework code for making a Notepad++ plugin in C++, along with various utility functions and examples.

I have constructed it to give myself and others a useful starting point when developing a Notepad++ plugin in C++.

It necessarily reflects my own idiosyncrasies as a programmer. I hope it may prove useful to others, and I welcome comments, suggestions and problem reports in the Issues; however, I make no apologies for its incorporation of my personal choices and styles — which might not meet with universal approval — and I do not promise to make changes to accommodate all plausible programming styles and use cases. So be it.

At present, support for docking dialogs is not included. It might be added later.

To use this template, place the zip file for the latest release in the Visual Studio 2022\Templates\ProjectTemplates folder within your Documents folder. The next time you start Visual Studio and choose Create a new project, you’ll find Notepad++ C++ Plugin available as a C++ project template.

The initial Visual Studio project settings are chosen to make it possible to test the plugin with an installed copy of Notepad++ (x86, x64 or both). After a successful build, the plugin dll and documentation files will be copied to your Notepad++ plugin directory if Notepad++ is installed in the default location. This only works if you set permissions on those directories to allow copying without elevated permissions. You can modify the Post-Build Event in the Configuration Properties for the project if you want to deploy the plugin to a different copy of Notepad++ for testing, or disable the Post-Build Event if you want to copy it manually.

Project layout

A project created from this template begins with five sections in the Microsoft Visual Studio Solution Explorer: Documentation, Header Files, Resource Files, Source Files and Support Files. The standard categories of References and External Dependencies will also be present.

Documentation

Documentation contains CHANGLOG.md, help.htm, LICENSE.txt and README.md. These files are in the root directory of the project. They are copied to the output directory when you build the project. The sample About box gives the user the option to view these files. If you add or remove documentation files, you’ll want to modify the code in About.cpp and the IDD_ABOUT dialog to work properly with your changes.

You should change these files to correspond to your plugin. As supplied, they describe the template.

Header Files

CommonData.h, found in the src directory of the project, defines data used by the example Source Files included in this template. This file is not required; if you keep it, you will replace nearly everything in it as appropriate for your project, but you might want to use it as a model. It includes examples of how you can use the config template and the config_history structure to define persistent data stored in your project’s configuration file.

Resource Files

These files are in the src directory of the project.

The resource.h file is maintained by the resource editor in Visual Studio. Include it in any cpp files that need to reference dialogs or controls. You usually don’t want to edit this file directly; however, there is one common situation in which doing so may be necessary. The CheckRadioButton function from the Windows API only works properly if the resource identifiers of all the radio buttons in a mutually-exclusive group span a numeric range that does not include any other resource identifiers (in practice, you usually just want them to be sequential numbers). The resource editor doesn’t take that into consideration when assigning control identifiers (counterintuitively, the tab order you set in the resource editor isn’t reflected in the control identifiers); so you might need to reassign control identifiers by editing this file.

The resource.rc file contains definitions of dialogs and version information. You ordinarily use the Resource View in Visual Studio to view and edit this file. IDD_ABOUT (the sample About dialog template), IDD_SETTINGS (the sample Settings dialog template) and VS_VERSION_INFO (version information) are contained in this file. You will need to modify all of these.

Source Files

These files are in the src directory of the project.

About.cpp contains sample code to display a Help/About dialog. You will want to modify the dialog (IDD_ABOUT in the Resource View) to describe your plugin. Depending on what changes you make in the dialog, you might need to modify this file, or it might be OK as it is.

Configuration.cpp reads and writes a configuration file in the folder Notepad++ reserves for plugin configuration files. The configuration file is in JSON format. See the Configuration section of this help for more information. You might not need to modify Configuration.cpp.

Plugin.cpp contains code which implements the required structure of a Notepad++ plugin and routes notifications and menu commands to your routines. You will need to modify this to define your menu commands and reference the routines which process them, and to select notifications you want to process and route them to your routines.

The remaining Source Files show examples of routines that perform simple tasks. They are not required. If you keep them, you will need to replace nearly everything in them as appropriate for your project; but you might want to use them as models:

  • ProcessCommands.cpp contains an example of a routine to process a command.
  • ProcessNotifications.cpp contains some examples of routines that process notifications.
  • Settings.cpp contains code to support the sample Settings dialog. It includes examples of how to use variables defined with the config template and the configHistory structure (described in the Configuration section of this help) to expose settings to the user which your plugin can save in its configuration file.
  • Status.cpp displays a non-modal dialog.

Support Files

These files are in the src\Framework, src\Host and src\nlohmann directories of the project. Ordinarily you should not change these files, other than possibly to replace them with updated copies of their upstream sources if and when newer versions become available.

FilePurposeSource
src\Framework\ConfigFramework.h declares config template and config_history struct for JSON-backed configuration datapart of this framework
src\Framework\PluginFramework.cpp contains the DLL entry point and some plugin implementation code required by Notepad++
src\Framework\PluginFramework.h declares PluginData struct which holds information needed to communicate with Notepad++ and Scintilla
src\Framework\ScintillaCallEx.cpp preprocessor modification of ScintillaCall to make exception derive from std::exception, which is handled better by Notepad++
src\Framework\ScintillaCallEx.h
src\Framework\UtilityFramework.h Defines a few helpful functions, as described in the Utility functions section of this help.
src\Host\BoostRegexSearch.h Scintilla within Notepad++
src\Host\menuCmdID.h Notepad++
src\Host\Notepad_plus_msgs.h Notepad++
src\Host\PluginInterface.h Notepad++
src\Host\Scintilla.h Scintilla within Notepad++
src\Host\ScintillaCall.cxx Scintilla within Notepad++
src\Host\ScintillaCall.h Scintilla within Notepad++
src\Host\ScintillaMessages.h Scintilla within Notepad++
src\Host\ScintillaStructures.h Scintilla within Notepad++
src\Host\ScintillaTypes.h Scintilla within Notepad++
src\Host\Sci_Position.h Scintilla within Notepad++
src\nlohmann\json.hpp Niels Lohmann’s JSON for Modern C++

Using Scintilla

Notepad++ uses Scintilla to implement its edit windows. If your plugin does anything with the content of files being edited, it will do that through Scintilla. Scintilla works with “documents” and “controls.” Notepad++ displays either one or two Scintilla controls, the main view and the secondary view. The tabs in each view represent separate documents, but Notepad++ loads just one document at a time into each Scintilla control.

The most basic way of communicating with Scintilla is through Windows messages. That’s a very general C-style interface which makes Scintilla compatible with most anything that can run on Windows, but it’s frustrating (like most C interfaces) to use from C++. The good news is that Scintilla has created a C++ interface which is much less annoying. The bad news is... there’s no explicit documentation for it.

The C++ interface is implemented through a class named ScintillaCall. To work, it needs a bit of setup, for which the setup code needs to know which Scintilla control is being addressed. Since there are two (and, in fact, others which don’t represent edit windows) in Notepad++, it’s important to get the right one. This framework sorts that out for you whenever possible.

When your plugin is called to process a menu command, the situation is simple. There is always an active tab, and the associated document is loaded into the view in which that tab exists. This framework prepares the ScintillaCall interface before calling your command processing routine.

The Notepad++ notification NPPN_BUFFERACTIVATED also occurs only when there is a known active tab, so that is handled in the same way as commands.

Scintilla notifications contain the handle of the Scintilla control from which they emanate, so they, too, can be set up unambiguously. However, it is not guaranteed that Scintilla notifications will come only for the two Scintilla edit controls. If you process Scintilla messages, take care to be sure they really are for a document you want to process.

Notepad++ notifications — NPPN_ messages — other than NPPN_BUFFERACTIVATED typically cannot be associated with a Scintilla control. (This template shows, in the modifyAll routine in ProcessNotifications.cpp, an example of how it is possible to associate some NPPN_GLOBALMODIFIED messages with one, or both, edit controls, and how to use plugin.getScintillaPointers to enable the ScintillaCall interface.) Nothing will stop your program from compiling if you try to use Scintilla when processing these notifications, but it won’t work as you expect unless you can determine the necessary information and call plugin.getScintillaPointers first.

To call Scintilla, use sci.CommandName. (UtilityFramework.h defines sci as a reference to the instance of the ScintillaCall class managed by this framework.) Nearly all the Scintilla messages described here have corresponding member functions in this class. I know of no specific documentation for the ScintillaCall interface, but you can generally find the message you need in the main Scintilla documentation, then begin typing “sci.” followed by the name of the message and auto-complete will steer you to the function call. When in doubt, examine the code in src\Host\ScintillaCall.cxx (in the Support Files section in Solution Explorer in Visual Studio) to work out what is happening.

Some examples:
auto ltext = sci.GetLine(12);
sci.InsertText(-1, newText.data());
auto stext = sci.GetSelText();
auto cpos = sci.CurrentPos();
auto text4 = sci.StringOfRange(Scintilla::Span(cpos, cpos + 4));

Utility functions

src\Framework\UtilityFramework.h includes several convenience functions you can use.

LRESULT npp(UINT Msg, WPARAM wParam, LPARAM lParam)

Sends a message to Notepad++. See this documentation for descriptions of the available messages. Example:
intptr_t cdi1 = npp(NPPM_GETCURRENTDOCINDEX, 0, 0);

sci.function

Sends a message to a Scintilla control. Arguments and return values vary depending on the function; see Using Scintilla.

std::string fromWide(std::wstring_view s, unsigned int codepage)
std::string fromWide(std::wstring_view s)

Converts a wide string to a byte string. If codepage is omitted, it uses the code page of the active Scintilla (which will be either the system default code page or CP_UTF8; don’t let the code page default when processing a Notepad++ notification other than NPPN_BUFFERACTIVATED unless you have called plugin.getScintillaPointers to establish the correct active Scintilla).

std::wstring toWide(std::string_view s, unsigned int codepage)
std::wstring toWide(std::string_view s)

Converts a byte string to a wide string. If codepage is omitted, it uses the code page of the active Scintilla (which will be either the system default code page or CP_UTF8; don’t let the code page default when processing a Notepad++ notification other than NPPN_BUFFERACTIVATED unless you have called plugin.getScintillaPointers to establish the correct active Scintilla).

std::wstring GetWindowString(HWND hWnd)
std::wstring GetDlgItemString(HWND hwndDlg, int item)

Gets the text of a window or a control in a dialog as a wide string. Specify the window handle of the window, or the window handle of the dialog and the control identifier of the control.

bool ShowBalloonTip(HWND hwndDlg, int item, const std::wstring& text)

Shows text as a balloon tip on an edit control in a dialog. Specify the window handle of the dialog as hwndDlg; item specifies the control identifier of an edit control, a combo box or a spin control with an edit control buddy. Returns true if the request is successful.

std::wstring getFilePath(UINT_PTR buffer)
std::wstring getFilePath()

Gets the full path of a file open in Notepad++ as a std::wstring.

  • If an argument is supplied, it is the Notepad++ buffer id to be examined.
  • If no argument is given, the current buffer is examined; this only works in commands and NPPN_BUFFERACTIVATED notifications, since in Scintilla notifications and most Notepad++ notifications, the "current buffer" is not necessarily meaningful.
  • Returns L"" if there is no such buffer id.
std::wstring getFileExtension(const std::wstring& filepath)
std::wstring getFileExtension(UINT_PTR buffer)
std::wstring getFileExtension()

Gets the file extension, converted to lower case, from a path, a buffer id or the current buffer.

  • If a string is supplied, it is parsed to isolate the file extension.
  • If a numeric argument is supplied, it is the Notepad++ buffer id to be examined.
  • If no argument is given, the current buffer is examined; this only works in commands and NPPN_BUFFERACTIVATED notifications, since in Scintilla notifications and most Notepad++ notifications, the "current buffer" is not necessarily meaningful.
  • Returns L"." for a file with no extension, L"" for a non-path (i.e., without a backslash, e.g., "new 1") or if there is no such buffer id.

Configuration

This Visual Studio template includes a mechanism for loading and saving configuration data using a JSON file, which is created in the folder Notepad++ reserves for plugin configuration files. Three files — src\nlohmann\json.hpp, src\Configuration.cpp and src\Framework\ConfigFramework.h — support this system.

src\nlohmann\json.hpp

This file, from the JSON for Modern C++ project, implements the json class as a recursive, polymorphic STL-like container, which serves as the basis for the configuration mechanism in this template. The value of a json instance can be nearly any C++ type: std::vector values represent JSON arrays, std::map<std::string, T> values represent JSON objects, and other values represent boolean values, numbers, strings or complex objects. A json value can be read from or written to a file, which makes using it for saving configuration settings straightforward.

src\Configuration.cpp

You might need to modify this file, but in many cases it will work just as it is.

Configuration.cpp contains the routines which load and save configuration data for the plugin as a JSON file. The supplied code sets configVersion and configCompatible values to 1. If you later change the configuration format and need to differentiate between versions, add code to do that here. Configuration versions are unrelated to your plugin’s version designation; only increment the configuration version if you create an incompatibility that requires you to recognize whether a file is an older or newer version. Change configCompatible if you create a version that can’t be processed correctly by a version of your plugin that expects an older configuration file version: set it to the configuration version of the oldest configuration version of your plugin which can read this version. If you never create incompatibilities, you can leave both version values at 1.

The supplied code reads the configuration file into the global json instance configuration during start up and writes it back to the same file during shut down. You can add code to copy specific information between ordinary variables and the JSON structure here; however, you typically won’t need to do that, as the framework provides some handy templates and structures for creating common data types that are reflected in the JSON configuration store automatically.

src\Framework\ConfigFramework.h

This file defines templates and structures that make it easy to use JSON-backed variables in your program for settings that can be exposed to the user as checkboxes, edit controls, combo boxes or radio button sets.

Checkboxes, spin boxes and edit controls

You can use the config template to manage settings users will choose with checkboxes, spin boxes and edit controls. The following code defines one of each:

config<bool>         checkThis    ("check this"   , false);
config<int>          pickANumber  ("number picked", 22);
config<std::wstring> saySomething ("what said"    , L"No comment.");

The names “check this,” “number picked” and “what said” will be used to identify these settings in the JSON configuration file. The values false, 22 and L"No comment." will be used if these settings are not found in the configuration file (typically, until and unless the user changes them).

In your program code, you can usually access config variables as if they were variables of the template parameter type:

if (checkThis) {
    for (int i = 0; i < pickANumber; ++i) {
        std::wstring s = saySomething;
        // ...
    }
}
checkThis = false;
pickANumber = 1;

If you need to access them in a context where implicit conversion won’t work, use get():

SendMessage(0, saySomething.get().data(), L"What did I say?", 0);

To display them to the user in dialog box controls, use put:

put(checkThis, hwndDlg, IDC_CHECKBOX1);
put(pickANumber, hwndDlg, IDC_SPIN2);
put(saySomething, hwndDlg, IDC_EDIT4);

and to retrieve changes the user made, use get:

get(checkThis, hwndDlg, IDC_CHECKBOX1);
get(pickANumber, hwndDlg, IDC_SPIN2);
get(saySomething, hwndDlg, IDC_EDIT4);

You can use bool with checkboxes; you can use std::wstring and arithmetic types (except bool) with edit boxes. You can also use integral types (except bool) with spin boxes; use the control identifier of the spin control, not its edit control buddy, in get and put.

Enumerations and radio buttons

Enumerations go naturally with radio buttons; config supports enumerations, but you have to manage the radio buttons using the ordinary Windows API. In addition, some extra code is necessary to tell the underlying JSON implementation how to represent the enumeration. This code defines an enum class with three possible values and tells the JSON implementation how it is to be represented in a JSON file:

enum class MyPreference {Bacon, IceCream, Pizza};
NLOHMANN_JSON_SERIALIZE_ENUM(MyPreference, {
    {MyPreference::Bacon   , "Bacon"},
    {MyPreference::IceCream, "Ice Cream"},
    {MyPreference::Pizza   , "Pizza"}
})

while this:

config<MyPreference> myPref = { "MyPreference", MyPreference::Bacon };

defines a config variable of type MyPreference with a default value of Bacon. Set the corresponding radio button in a dialog:

switch (data.myPref) {
case MyPreference::Bacon   : CheckRadioButton(hwndDlg, IDC_PREFER_BACON, IDC_PREFER_PIZZA, IDC_PREFER_BACON   ); break;
case MyPreference::IceCream: CheckRadioButton(hwndDlg, IDC_PREFER_BACON, IDC_PREFER_PIZZA, IDC_PREFER_ICECREAM); break;
case MyPreference::Pizza   : CheckRadioButton(hwndDlg, IDC_PREFER_BACON, IDC_PREFER_PIZZA, IDC_PREFER_PIZZA   );
}

and read the user’s choice:

data.myPref = 
    IsDlgButtonChecked(hwndDlg, IDC_PREFER_ICECREAM) == BST_CHECKED ? MyPreference::IceCream
  : IsDlgButtonChecked(hwndDlg, IDC_PREFER_PIZZA   ) == BST_CHECKED ? MyPreference::Pizza
                                                                    : MyPreference::Bacon;   

using standard Windows API functions.

Plugin.cpp

src\Plugin.cpp contains code that implements customizable elements of the Notepad++ plugin interface. This is the only file in the template that both must be included and also requires significant modification to accommodate the specific needs of your plugin.

Since plugin.cpp is responsible for dispatching commands and notifications, near the beginning there are declarations of all the functions in other source files which handle those. You'll change these to reflect the names you choose for your routines.

Next is the definition of your plugin’s menu, specifying the names of the items on the menu and the routines in your code that handle them. Follow the example in the file.

The exported routines defined in Plugin.cpp:

extern "C" __declspec(dllexport) const wchar_t* getName()
extern "C" __declspec(dllexport) FuncItem * getFuncsArray(int *n)
extern "C" __declspec(dllexport) void beNotified(SCNotification *np)
extern "C" __declspec(dllexport) LRESULT messageProc(UINT, WPARAM, LPARAM)

are required; you can’t change their names or signatures. If the name for your plugin that should appear on the Plugins menu is not the same as the name you gave for your project when you created it from this template, correct that in the getName function. Unless the menu you want Notepad++ to display for your plugin is not always the same (there is no support for that in this template), leave getFuncsArray unchanged and define your menu in the section above. The messageProc routine is rarely used, and no example is provided in this template; you probably don’t want to change it.

The beNotified function captures notifications both from Notepad++ and from Scintilla. This means it is called very frequently, and you really want to keep it as efficient as possible to avoid adversely impacting the performance of Notepad++. You will have to determine which notifications you require and adapt this routine to route them accordingly. Notepad++ notifications are also used to trigger some plugin framework functions (like loading and saving the configuration file), so you will need to take care when modifying that section of the routine.

About.cpp

The code in src\About.cpp displays a Help/About box. It retrieves version and build time information from the plugin binary and provides buttons to open help.htm in a browser and to open CHANGELOG.md, LICENSE.txt and README.md in Notepad++. The dialog is defined in src\resources.rc in the Resource Files section of the project; use the Resource View in Visual Studio to examine it. You will want to edit the dialog to provide information about your plugin. If you change available functions in the dialog (such as adding a link to your webpage or repository), implement the changes in src\About.cpp; otherwise, you might not need to modify this file.

Example files

The files CommonData.h, ProcessCommands.cpp, ProcessNotifications.cpp, Settings.cpp and Status.cpp contain example code. None of these files are required, but you might want to use them as models for your code.

  • CommonData.h defines data used by the other example files. If you keep it, you’ll need to replace nearly everything in it as appropriate for your project, but you might want to use it as a model. It includes examples of how you can use the config template and the config_history structure to define persistent data stored in your project’s configuration file.
  • ProcessCommands.cpp contains an example of a routine to process a command.
  • ProcessNotifications.cpp contains some examples of routines that process notifications.
  • Settings.cpp displays a sample dialog box for presenting user settings. If you keep this file you’ll need to change most of its content to fit the needs of your project, but you might want to use it and the associated Settings dialog (accessible using the Resource View in Visual Studio) as a guide for how to construct a settings dialog using the tools described in the Configuration section of this help. It includes examples of how to use variables defined with the config template and the configHistory structure to expose settings to the user which your plugin saves in its configuration file.
  • Status.cpp displays a non-modal dialog in response to a menu command. The scnModified routine in ProcessNotifications.cpp calls updateStatusDialog in this file to update the information in the dialog when the user inserts or deletes text.

Detailed specifications for config

Structures defined using the config template wrap an underlying type so that it can be used normally in program code, but can also be easily read from or written to a JSON object defined using nlohmann::json. They can be synchronized automatically with the global configuration variable, which in turn is synchronized with a configuration file at start up and shut down. In addition, there are convenience functions for arithmetic types and std::wstring simplifying their use with common Windows controls.

template<typename T> struct config {

    const std::string name;
    T value;
    const T initial;
    const bool autoconfig;
    bool loaded = false;

    bool peek(T& v, const nlohmann::json& j) const;
    bool peek(T& v, HWND w)                  const;
    bool peek(T& v, HWND w, int id)          const;

    T peek(const nlohmann::json& j) const;
    T peek(HWND w)                  const;
    T peek(HWND w, int id)          const;

    static void show(HWND w, const T& v);
    static void show(HWND w, int id, const T& v);

    T& get(const nlohmann::json& j);
    T& get(HWND w);
    T& get(HWND w, int id);
    T& get();

    const T& put(nlohmann::json& j) const;
    const T& put(HWND w);
    const T& put(HWND w, int id);

    operator T&();
    config<T>& operator=(const T& v);

    config(const std::string& name, T initial, bool autoconfig = true);

};
config<T>(const std::string& name, T initial, bool autoconfig = true)

Constructs a config object.

  • T specifies the C++ type on which this configuration item is based. You can use any type supported by nlohmann::json; src\Framework\ConfigUtility.h includes a specialization for nlohmann::adl_serializer<std::wstring> which adds support for std::wstring.

  • name (usually given as a character literal) specifies the name used for this variable in json objects.
  • initial specifies an initial value for the variable.
  • autoconfig, when true (the default), specifies that the first attempt to access the variable using get() or implicit or explicit conversion to type T will cause the value to be read from the global json object configuration; and any time the assignment operator, get(HWND) or get(HWND, int) is used, the new value will be written to configuration. When false, a json object is never accessed unless explicitly specified in a call to peek, get or put.
  • When T is bool, functions that take an HWND assume the designated control is a checkbox.
  • When T is an integral type other than bool, functions that take an HWND assume the designated control is either an edit control or a spin control (which can have an edit control buddy).
  • When T is std::wstring or a floating point type, functions that take an HWND assume the designated control is an edit control.
  • When T is not an arithmetic type or std::wstring, functions that take an HWND are not available.
  • In all cases, functions which include:
    HWND w, int id
    among their parameters are equivalent to the same-named functions with HWND w and no int id, substituting:
    GetDlgItem(w, id)
    for w.
T value

You can access the value directly at any time using the value member.

bool loaded

The loaded member is initially false, and is set to true when any operation (other than direct access to the value member) sets the value of the variable. Its purpose is to control autoconfig: once a value has been set, whatever value is present is used, and configuration is not consulted again.

bool peek(T& v, const nlohmann::json& j) const
bool peek(T& v, HWND w) const
bool peek(T& v, HWND w, int id) const
T peek(const nlohmann::json& j) const
T peek(HWND w) const
T peek(HWND w, int id) const

The peek member functions retrieve a value from either a json object or a Windows control without setting the value member.

  • The versions which return a bool return true if the value was successfully retrieved and false otherwise. The versions which return a value return the current value of value if retrieval was unsuccessful.
  • v is a reference to a variable of the same type as the template parameter type. If retrieval is successful, it is set to the retrieved value; otherwise it is unchanged.
  • j designates a json object (in the C++ sense of object) which contains an object (in the JSON sense of object); the name member determines the name of the member of the JSON object the value of which is to be retrieved.
  • w specifies the window handle, or the window handle of the parent window, of the control from which the value is to be retrieved.
  • id specifies the resource identifier of the control from which a value is to be retrieved; w is a handle to the parent of the control to be examined (e.g., a dialog). When no id is specified, w is the handle of the control itself.
  • If a window handle is given and the template type is bool, the control must be a checkbox.
  • If a window handle is given and the template type is an integral type other than bool, the control must be either an edit control or a spin control (which can have an edit control buddy).
  • If a window handle is given and the template type is std::wstring or a floating point type, the control must be an edit control.
  • If the template type is not an arithmetic type or std::wstring, the member functions that take a window handle will not be available.
static void show(HWND w, const T& v)
static void show(HWND w, int id, const T& v)

The show member functions display a value in a Windows control. They don’t use any data in the config object, but the template type parameter determines the type of Windows controls they can address.

  • w specifies the window handle, or the window handle of the parent window, of the control in which the value is to be displayed.
  • id specifies the resource identifier of the control in which a value is to be displayed; w is a handle to the parent of the control to be updated (e.g., a dialog). When no id is specified, w is the handle of the control itself.
  • v is a const reference to a variable of the same type as the template parameter type.
  • If the template type is bool, the control must be a checkbox.
  • If the template type is an integral type other than bool, the control must be either an edit control or a spin control (which can have an edit control buddy).
  • If the template type is std::wstring or a floating point type, the control must be an edit control.
  • If the template type is not an arithmetic type or std::wstring, the show member functions will not be available.
T& get(const nlohmann::json& j)
T& get(HWND w)
T& get(HWND w, int id)
T& get()

The get member functions retrieve a value from either a json object or a Windows control and set the value member. All versions return a reference to value. If the attempt to retrieve a value is unsuccessful, value is not changed.

  • get(), with no arguments, attempts to retrieve the value corresponding to name from the global configuration object if autoconfig is true and loaded is false. In all other cases, or if the attempt to retrieve the value fails, get() returns value unchanged.
  • j designates a json object (in the C++ sense of object) which contains an object (in the JSON sense of object); the name member determines the name of the member of the JSON object the value of which is to be retrieved.
  • w specifies the window handle, or the window handle of the parent window, of the control from which the value is to be retrieved.
  • id specifies the resource identifier of the control from which a value is to be retrieved; w is a handle to the parent of the control to be examined (e.g., a dialog). When no id is specified, w is the handle of the control itself.
  • If a window handle is given and the template type is bool, the control must be a checkbox.
  • If a window handle is given and the template type is an integral type other than bool, the control must be either an edit control or a spin control (which can have an edit control buddy).
  • If a window handle is given and the template type is std::wstring or a floating point type, the control must be an edit control.
  • If the template type is not an arithmetic type or std::wstring, the member functions that take a window handle will not be available.
const T& put(nlohmann::json& j) const
const T& put(HWND w)
const T& put(HWND w, int id)

The put member functions copy the value of a config object to a json object or a Windows control. All versions return a constant reference to value.

  • j designates a json object (in the C++ sense of object) which contains an object (in the JSON sense of object); the name member determines the name of the member of the JSON object the value of which is to be set to value. This form of put never changes value.
  • w specifies the window handle, or the window handle of the parent window, of the control in which the value is to be displayed. This form of put (with or without id) can change value. If autoconfig is true and loaded is false, put-to-HWND first attempts to retrieve the value corresponding to name from the global configuration object. In all other cases, or if the attempt to retrieve the value fails, value is unchanged. Regardless of whether retrieval was successful, value is copied to the specified Windows control.
  • id specifies the resource identifier of the control in which a value is to be displayed; w is a handle to the parent of the control to be updated (e.g., a dialog). When no id is specified, w is the handle of the control itself.
  • If a window handle is given and the template type is bool, the control must be a checkbox.
  • If a window handle is given and the template type is an integral type other than bool, the control must be either an edit control or a spin control (which can have an edit control buddy).
  • If a window handle is given and the template type is std::wstring or a floating point type, the control must be an edit control.
  • If the template type is not an arithmetic type or std::wstring, the member functions that take a window handle will not be available.
operator T&()

Conversion to template type is identical to get().

config<T>& operator=(const T& v)

Assignment assigns the right-side value to value and sets loaded to true. If autoconfig is true it then writes the new value to the name member of the global configuration object.

Detailed specifications for config_history

Variables defined using the config_history structure manage a std::vector<std::wstring> so that it can be used easily with a combo box to maintain and show a history of text the user enters. Its member functions are similar to those in the config template. The vector holds the history in reverse order: that is, the first element is the current value and the last element is the oldest.

struct config_history {

    const std::string name;
    std::vector<std::wstring> history;
    std::vector<std::wstring> initial;
    int depth;
    bool retainBlank;
    bool retainDuplicate;
    bool retainEmpty;
    bool loaded = false;
    const bool autoconfig;

    bool peek(std::vector<std::wstring>& v, const nlohmann::json& j) const;

    std::wstring peek(HWND w)         const;
    std::wstring peek(HWND w, int id) const;

    static void show(HWND w, const std::wstring& s);
    static void show(HWND w, int id, const std::wstring& s);

    std::wstring& get(const nlohmann::json& j);
    std::wstring& get(HWND w);
    std::wstring& get(HWND w, int id);
    std::wstring& get();

    const std::wstring& put(nlohmann::json& j) const;
    const std::wstring& put(HWND w);
    const std::wstring& put(HWND w, int id);

    operator std::wstring&();
    config_history& operator=(const std::vector<std::wstring>& v);
    config_history& operator=(const std::wstring& v);
    config_history& operator+=(const std::wstring& v);

    constexpr static int Blank     = 1;
    constexpr static int Duplicate = 2;
    constexpr static int Empty     = 4;

    config_history(const std::string& name, const std::vector<std::wstring>& initial,
        int depth = 10, int retain = 0, bool autoconfig = true);

};
constexpr static int Blank     = 1;
constexpr static int Duplicate = 2;
constexpr static int Empty     = 4;

config_history(const std::string& name, const std::vector<std::wstring>& initial,
    int depth = 10, int retain = 0, bool autoconfig = true);

Constructs a config_history object as wrapper for a vector of wide strings which can read from or written to an array stored as a memeber in a nlohmann::json object, and read from or written to a Windows combo box control.

  • name (usually given as a character literal) specifies the name used for this array in json objects.
  • initial specifies an initial value for the vector.
  • depth, when positive, specifies the maximum number of items in the vector. Older items are removed. This constraint is enforced during get functions specifying an HWND and += operations. When depth is zero or negative, no constraint is imposed.
  • retain can be zero or a combination of config_history::Blank, config_history::Duplicate and config_history::Empty specifying how items in the history are retained (combine with + or |). By default, empty strings and strings which duplicate the current string (the one in history[0] or the edit control of a combo box) are not retained in history items beyond the first, and for purposes of matching or recognizing the empty string, trailing blanks are removed. This constraint is enforced during get functions specifying an HWND and += operations.
  • Blank indicates that trailing blanks are significant for purposes of matching the current string or recognizing the empty string.
  • Duplicate indicates that strings which duplicate the current string (the one in history[0] or the edit control of a combo box) are to be retained in the history.
  • Empty indicates that empty strings are to be retained in the history.
  • autoconfig, when true (the default), specifies that the first attempt to access the history or the current value from the history using get() or implicit or explicit conversion to a wide string will cause the history to be read from the global json object configuration; and any time the assignment operator, += operator, get(HWND) or get(HWND, int) is used, the new history will be written to configuration. When false, a json object is never accessed unless explicitly specified in a call to peek, get or put.
  • In all cases, functions which include:
    HWND w, int id
    among their parameters are equivalent to the same-named functions with HWND w and no int id, substituting:
    GetDlgItem(w, id)
    for w.
std::vector<std::wstring> history

You can access the underlying vector of wide strings directly as the history member.

bool loaded

The loaded member is initially false, and is set to true when any operation (other than direct access to the history member) changes the history. Its purpose is to control autoconfig: once the history has been initialized, whatever history is present is used, and configuration is not consulted again.

bool peek(std::vector<std::wstring>& v, const nlohmann::json& j) const
std::wstring peek(HWND w)         const
std::wstring peek(HWND w, int id) const

The peek member functions retrieve a history from a json object or the current text in the edit control of a Windows combo box without setting the history member.

  • v is a reference to a vector of wide strings. If retrieval is successful, it is set to the retrieved history and true is returned; otherwise it is unchanged and false is returned.
  • j designates a json object (in the C++ sense of object) which contains an object (in the JSON sense of object); the name member determines the name of the member of the JSON object which contains an array that will be copied to v.
  • w specifies the window handle, or the window handle of the parent window, of a combo box control. The return value is retrieved from the edit control of the combo box.
  • id specifies the resource identifier of a combo box; w is a handle to the parent of the control to be examined (e.g., a dialog). When no id is specified, w is the handle of the combo box itself.
static void show(HWND w, const std::wstring& s)
static void show(HWND w, int id, const std::wstring& s)

The show member functions display the specified value in the edit control of a combobox. No data from the config_history object is used.

  • w specifies the window handle, or the window handle of the parent window, of the combo box in which the value is to be displayed.
  • id specifies the resource identifier of the combo box in which a value is to be displayed; w is a handle to the parent of the control to be updated (e.g., a dialog). When no id is specified, w is the handle of the control itself.
std::wstring& get(const nlohmann::json& j)
std::wstring& get(HWND w)
std::wstring& get(HWND w, int id)
std::wstring& get()

The get member functions retrieve a vector of wide strings from either a json object or a Windows combo box and store it in the history member, then return a reference to history[0]. If the attempt to retrieve a vector of wide strings is unsuccessful history is not changed; except that in all cases (successful or not), if an empty vector would otherwise result, {L""} is assigned to history.

  • get(), with no arguments, attempts to retrieve the JSON array corresponding to name from the global configuration object if autoconfig is true and loaded is false, then store it in history as a vector of wide strings. In all other cases, or if the attempt to retrieve the array and convert it to a vector of wide strings fails, history is not changed; except that in all cases (successful or not), if an empty vector would otherwise result, {L""} is assigned to history.
  • j designates a json object (in the C++ sense of object) which contains an object (in the JSON sense of object); the name member determines the name of the member of the JSON object from which an array of strings is to be retrieved.
  • w specifies the window handle, or the window handle of the parent window, of the combo box from which a list of strings is to be retrieved. The content of the edit box becomes the first element of history and the remaining elements are the items in the list. Depth and retention constraints, as specified in the constructor, are applied.
  • id specifies the resource identifier of the combo box from which a list of strings is to be retrieved; w is a handle to the parent of the combo box to be examined (e.g., a dialog). When no id is specified, w is the handle of the combo box itself.
const std::wstring& put(nlohmann::json& j) const
const std::wstring& put(HWND w)
const std::wstring& put(HWND w, int id)

The put member functions copy the value of a config_history object to a json object or a Windows combo box control. All versions return a constant reference to history[0] unless history is empty, in which case they return a reference to L"".

  • j designates a json object (in the C++ sense of object) which contains an object (in the JSON sense of object); the name member determines the name of the member of the JSON object to which an array of strings corresponding to history is assigned. This form of put never changes history.
  • w specifies the window handle, or the window handle of the parent window, of the combo box in which the history is to be displayed. This form of put (with or without id) can change history. If autoconfig is true and loaded is false, put-to-HWND first attempts to retrieve the history corresponding to name from the global configuration object. In all other cases, or if the attempt to retrieve the history fails, history is not changed; except that in all cases (successful or not), if an empty vector would otherwise result, {L""} is assigned to history. Regardless of whether retrieval was successful, the first element of history is copied to the edit control of the combo box and the remaining elements are copied to the drop-down list.
  • id specifies the resource identifier of the combo box in which a list of strings is to be displayed; w is a handle to the parent of the combo box to be updated (e.g., a dialog). When no id is specified, w is the handle of the combo box itself.
operator std::wstring&()

Conversion to std::wstring& is identical to get().

config_history& operator=(const std::vector<std::wstring>& v)

Assignment from a vector assigns the vector to history and sets loaded to true. If autoconfig is true it then writes the new history to the name member of the global configuration object. Depth and retention constraints are not applied.

config_history& operator=(const std::wstring& v)

Assignment from a wide string replaces the first element of history with the wide string and sets loaded to true. If autoconfig is true it then writes the new history to the name member of the global configuration object. If history is empty before the assignment, a new element is created. Depth and retention constraints are not applied.

config_history& operator+=(const std::wstring& v)

The += operator inserts the right-side string as the first value of history and sets loaded to true. Depth and retention constraints, as specified in the constructor, are applied. If autoconfig is true it then writes the new history to the name member of the global configuration object.