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 theconfigHistory
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.
File | Purpose | Source |
---|---|---|
src\Framework\ConfigFramework.h | declares config template and config_history struct for JSON-backed configuration data | part 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 theconfig_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 theconfigHistory
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 callsupdateStatusDialog
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 bynlohmann::json
; src\Framework\ConfigUtility.h includes a specialization fornlohmann::adl_serializer<std::wstring>
which adds support forstd::wstring
.name
(usually given as a character literal) specifies the name used for this variable injson
objects.initial
specifies an initial value for the variable.autoconfig
, when true (the default), specifies that the first attempt to access the variable usingget()
or implicit or explicit conversion to typeT
will cause the value to be read from the globaljson
objectconfiguration
; and any time the assignment operator,get(HWND)
orget(HWND, int)
is used, the new value will be written toconfiguration
. Whenfalse
, ajson
object is never accessed unless explicitly specified in a call topeek
,get
orput
.- When
T
isbool
, functions that take an HWND assume the designated control is a checkbox. - When
T
is an integral type other thanbool
, 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
isstd::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 orstd::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 withHWND w
and noint id
, substituting:GetDlgItem(w, id)
forw
.
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
returntrue
if the value was successfully retrieved andfalse
otherwise. The versions which return a value return the current value ofvalue
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 ajson
object (in the C++ sense of object) which contains an object (in the JSON sense of object); thename
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 noid
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 noid
is specified,w
is the handle of the control itself.v
is aconst
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
, theshow
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 toname
from the globalconfiguration
object ifautoconfig
istrue
andloaded
isfalse
. In all other cases, or if the attempt to retrieve the value fails,get()
returnsvalue
unchanged.j
designates ajson
object (in the C++ sense of object) which contains an object (in the JSON sense of object); thename
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 noid
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 ajson
object (in the C++ sense of object) which contains an object (in the JSON sense of object); thename
member determines the name of the member of the JSON object the value of which is to be set tovalue
. This form ofput
never changesvalue
.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 ofput
(with or withoutid
) can changevalue
. Ifautoconfig
istrue
andloaded
isfalse
,put
-to-HWND
first attempts to retrieve the value corresponding toname
from the globalconfiguration
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 noid
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 injson
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 duringget
functions specifying an HWND and+=
operations. Whendepth
is zero or negative, no constraint is imposed.retain
can be zero or a combination ofconfig_history::Blank
,config_history::Duplicate
andconfig_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 inhistory[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 duringget
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 inhistory[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 usingget()
or implicit or explicit conversion to a wide string will cause the history to be read from the globaljson
objectconfiguration
; and any time the assignment operator,+=
operator,get(HWND)
orget(HWND, int)
is used, the new history will be written toconfiguration
. Whenfalse
, ajson
object is never accessed unless explicitly specified in a call topeek
,get
orput
.- In all cases, functions which include:
HWND w, int id
among their parameters are equivalent to the same-named functions withHWND w
and noint id
, substituting:GetDlgItem(w, id)
forw
.
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 andtrue
is returned; otherwise it is unchanged andfalse
is returned.j
designates ajson
object (in the C++ sense of object) which contains an object (in the JSON sense of object); thename
member determines the name of the member of the JSON object which contains an array that will be copied tov
.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 noid
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 noid
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 toname
from the globalconfiguration
object ifautoconfig
istrue
andloaded
isfalse
, then store it inhistory
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 tohistory
.j
designates ajson
object (in the C++ sense of object) which contains an object (in the JSON sense of object); thename
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 ofhistory
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 noid
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 ajson
object (in the C++ sense of object) which contains an object (in the JSON sense of object); thename
member determines the name of the member of the JSON object to which an array of strings corresponding tohistory
is assigned. This form ofput
never changeshistory
.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 ofput
(with or withoutid
) can changehistory
. Ifautoconfig
istrue
andloaded
isfalse
,put
-to-HWND
first attempts to retrieve the history corresponding toname
from the globalconfiguration
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 tohistory
. Regardless of whether retrieval was successful, the first element ofhistory
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 noid
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.