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.
To install the template, download NppCppMSVS-n.nn.zip from the latest release and place it in the Visual Studio 2022\Templates\ProjectTemplates folder within your Documents folder. Don’t unzip it! The next time you start Visual Studio and choose Create a new project, you’ll find C++ Plugin for Notepad++ available as a C++ project template.
(If you don’t have the folder described above: Open Visual Studio 2022 and choose Continue without code; from the menu bar, select Tools | Options...; in the Projects and Solutions section, select Locations. User project template location shows the path to the correct folder in which to place the zip file.)
When you create a project from this template, the initial Visual Studio project settings 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 the directory 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.
You will still have to set the debugging path manually. Right-click your project in the Solution Explorer in Visual Studio and select Properties from the menu. In the Configuration Properties section, select Debugging; then click Command, click the drop-down arrow at the right, select Browse..., then navigate to and select the copy of Notepad++ you will use for debugging. You will have to do this separately for 32-bit and 64-bit targets (pay attention to the selections at the top of the Properties dialog).
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.
- Watcher.cpp displays a dockable 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 and config_rect structs 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++ | part of this framework |
src\Framework\PluginFramework.h | declares PluginData struct which holds information needed to communicate with Notepad++ and Scintilla | part of this framework |
src\Framework\ScintillaCallEx.cpp | preprocessor modification of ScintillaCall to make exception derive from std::exception, which is handled better by Notepad++ | part of this framework |
src\Framework\ScintillaCallEx.h | part of this framework | |
src\Framework\UtilityFramework.h | define a few helpful functions as described in the Utility functions section of this help | part of this framework |
src\Framework\UtilityFrameworkMIT.h | part of this framework | |
src\Host\BoostRegexSearch.h | defines constants used for communicating Boost search options to Scintilla | Scintilla within Notepad++ |
src\Host\Docking.h | defines the docking window interface | Notepad++ |
src\Host\menuCmdID.h | defines Notepad++ menu commands | Notepad++ |
src\Host\Notepad_plus_msgs.h | defines NPPM_ and NPPN_ messages | Notepad++ |
src\Host\PluginInterface.h | defines the Notepad++ plugin interface | Notepad++ |
src\Host\Sci_Position.h | define various structures, functions and constants used in the Scintilla interface | Scintilla within 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\nlohmann\json.hpp | maps a JSON configuration file to a C++ container | Niels Lohmann’s JSON for Modern C++ |
One additional file, ZipForRelease.ps1, is included in the Support Files section. This is a PowerShell file in the root folder of the project which you can run to produce zip files to be included as artifacts in a GitHub release. The files are stored in the Releases folder, and the SHA-256 hashes of the zip files, which are needed when preparing an entry in the Notepad++ Plugin List, are added to Releases\Hashes.txt.
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 and a structure 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.
DialogStretch name; ... name.setup(dialog-window-handle); ... name.adjust(control-ID, xStretch, yStretch, xMove, yMove)[.adjust(...)...];
DialogStretch
helps manage the sizing and placement of controls in resizable dialogs. Settings.cpp and Watcher.cpp include examples of its use. A full description of the structure is in the DialogStretch
section of this help. To use it:
- Define an instance of
DialogStretch
outside your dialog procedure, or asstatic
within your procedure, so that it will persist throughout the life of the dialog. - When you process
WM_INITDIALOG
, before doing anything that would resize the dialog from the size implied by its template, call thesetup
function with the handle to the dialog window as argument. This will analyze and record the default size and placement of your dialog and its controls. - Process
WM_SIZE
. Upon receiving that message, call theadjust
function for each control that should be moved or sized when the dialog size changes. Specify the control ID of the control and one to fourdouble
s representing the fraction of the change in horizontal and vertical size of the dialog that should be applied to the horizontal and vertical size and position of the control. For example, if IDC_BUTTON1 is meant to stay centered at the bottom of the dialog — so that it should not change size, should move to the right half as far as the dialog increases in width and should move downward as far as the dialog increases in height — writeadjust(IDC_BUTTON1, 0, 0, .5, 1)
. - You can chain
adjust
calls for all the controls in the dialog one after another. This is (slightly) more efficient than calling each one independently on theDialogStretch
object.
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. - Watcher.cpp displays a docking dialog.
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 { std::string name; nlohmann::json* store; T value; bool loaded = false; static bool peek(T& v, const nlohmann::json& j, std::string_view n); static bool peek(T& v, HWND w); static bool peek(T& v, HWND w, int id); T peek(const nlohmann::json& j, std::string_view n) 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, std::string_view n); T& get(HWND w); T& get(HWND w, int id); T& get(); const T& put(nlohmann::json& j, std::string_view n) const; const T& put(HWND w); const T& put(HWND w, int id); operator T&(); config<T>& operator=(const T& v); config(const T& initial); config(const std::string& name, const T& initial, nlohmann::json& store = configuration); };
config<typename T>(const T& initial); config<typename T>(const std::string& name, const T& initial, nlohmann::json& store = configuration);
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. Ifname
is omitted, ajson
object is never accessed unless explicitly specified in a call topeek
,get
orput
.store
specifies thenlohmann::json
object in which values are stored. If omitted whenname
is specified, the global objectconfiguration
is used.initial
specifies an initial value for the variable.- You normally use the
get
andput
functions, assignment, and implicit or explicit conversion to typeT
to access the value of aconfig
variable. If the first access is through assignment orget
with anHWND
, the assigned or retrieved value is set and, ifname
was specified, a copy is written to thejson
store. If the first access is through conversion,get
without arguments orput
with anHWND
andname
was specified, an attempt is made to read the value from thejson
store; if the attempt fails, or ifname
was not specified, theinitial
value is used. - 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
.
std::string name
The name
member contains the name under which the variable is saved in a json
store. Normally you should set this using the name
argument to the config
constructor and never change it.
nlohmann::json* store
The store
member contains a pointer to the json
store in which a copy of this variable is kept, or null if no store is used. Normally you should let the constructor set this to the address of the global configuration
object (or to null if name
is not specified) and never change it.
T value
Ordinarily, you should use implict or explicit conversion to type T
or the get()
member function without arguments to read the value of a config
variable, and assignment or one of the get
functions with an HWND
to update it, since these will maintain synchronization with the json
store. However, you can access the value directly 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 reading from the json
store: once a value has been set, whatever value is present is used, and the json
store is not read again.
static bool peek(T& v, const nlohmann::json& j, std::string_view n); static bool peek(T& v, HWND w); static bool peek(T& v, HWND w, int id); T peek(const nlohmann::json& j, std::string_view n) 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).n
specifies 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, std::string_view n); 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 associatedjson
store (usually the globalconfiguration
object) ifname
was specified in the constructor 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).n
specifies the name of the member of the JSON object the value of which 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, std::string_view n) 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).n
specifies 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
. Ifname
was specified in the constructor andloaded
isfalse
,put
-to-HWND
first attempts to retrieve the value corresponding toname
from thejson
store. 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 name
was specified in the constructor it then writes the new value to the name
member of the associated json
store (usually 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; nlohmann::json* store; std::vector<std::wstring> history; int depth; bool retainBlank; bool retainDuplicate; bool retainEmpty; bool loaded = false; std::wstring& value(); const std::wstring& value() const; static bool peek(std::vector<std::wstring>& v, const nlohmann::json& j, std::string_view n); static std::wstring peek(HWND w); static std::wstring peek(HWND w, int id); 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::string_view n); std::wstring& get(HWND w); std::wstring& get(HWND w, int id); std::wstring& get(); const std::wstring& put(nlohmann::json& j, std::string_view n) 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::vector<std::wstring>& initial, int depth = 10, int retain = 0); config_history(const std::string& name, const std::vector<std::wstring>& initial = {}, int depth = 10, int retain = 0, nlohmann::json& store = configuration); };
constexpr static int Blank = 1; constexpr static int Duplicate = 2; constexpr static int Empty = 4; config_history(const std::vector<std::wstring>& initial, int depth = 10, int retain = 0); config_history(const std::string& name, const std::vector<std::wstring>& initial = {}, int depth = 10, int retain = 0, nlohmann::json& store = configuration);
Constructs a config_history
object as wrapper for a vector of wide strings which can be read from or written to an array stored as a member in an 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. Ifname
is omitted, ajson
object is never accessed unless explicitly specified in a call topeek
,get
orput
.store
specifies thenlohmann::json
object in which values are stored. If omitted whenname
is specified, the global objectconfiguration
is used.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 during+=
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 during+=
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.- You normally use the
get
andput
functions, assignment, and implicit or explicit conversion tostd::wstring
to access the value of aconfig_history
variable. If the first access is through assignment orget
with anHWND
, the assigned or retrieved value is set and, ifname
was specified, a copy is written to thejson
store. If the first access is through conversion,get
without arguments orput
with anHWND
andname
was specified, an attempt is made to read the value from thejson
store; if the attempt fails, or ifname
was not specified, theinitial
value is used. - 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::string name
The name
member contains the name under which the vector is saved in a json
store. Normally you should set this using the name
argument to the config_history
constructor and never change it.
nlohmann::json* store
The store
member contains a pointer to the json
store in which a copy of this vector is kept as an array, or null if no store is used. Normally you should let the constructor set this to the address of the global configuration
object (or to null if name
is not specified) and never change it.
std::vector<std::wstring> history
Ordinarily, you should use implicit or explicit conversion to std::wstring
or the get()
member function without arguments to read the most recent entry in a config_history
variable, and assignment or one of the get
functions with an HWND
to update it, since these will maintain synchronization with the json
store. However, you can access the vector directly using the history
member.
int depth
This member holds the depth setting from the constructor, which determines the maximum number of entries that will be retained in the history.
bool retainBlank bool retainDuplicate bool retainEmpty
These three members hold the settings from the constructor for retaining blanks, duplicates and empty items in the history.
bool loaded
The loaded
member is initially false
, and is set to true
when any operation (other than direct access to the history
member or value()
reference) updates history
. Its purpose is to control reading from the json
store: once a value has been set, whatever value is present is used, and the json
store is not read again.
std::wstring& value() const std::wstring& value() const
Ordinarily, you should use implicit or explicit conversion to std::wstring
or the get()
member function without arguments to read the most recent entry in a config_history
variable, and assignment or one of the get
functions with an HWND
to update it, since these will maintain synchronization with the json
store. However, you can access the most recent entry (element zero) of the vector directly using the value()
member function. The const
form never modifies history
; however, when the history vector is empty, it returns a reference to a static constant empty string. The non-const
form always returns a reference to the first (most recent) element in the history, but if history
is empty, it inserts an empty string as the only element of the vector and returns a reference to that element.
static bool peek(std::vector<std::wstring>& v, const nlohmann::json& j, std::string_view n) static std::wstring peek(HWND w) static std::wstring peek(HWND w, int id)
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).n
specifies 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.s
specifies the text to be displayed in the edit control of the combobox.
std::wstring& get(const nlohmann::json& j, std::string_view n) 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 associatedjson
store ifname
was specified in the constructor 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).n
specifies the name of the member of the JSON object which contains an array of strings 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, std::string_view n) 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). This form ofput
never changeshistory
.n
specifies the name of the member of the JSON object to which an array of strings corresponding tohistory
is assigned.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
. Ifname
was specified in the constructor andloaded
isfalse
,put
-to-HWND
first attempts to retrieve the history corresponding toname
from the JSON store. 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 name
was specified in the constructor it then writes the new history to the name
member of the JSON store. 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 name
was specified in the constructor it then writes the new history to the name
member of the JSON store. 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 name
was specified in the constructor it then writes the new history to the name
member of the JSON store.
Detailed specifications for config_rect
Variables defined using the config_rect
structure help save and restore the size and position of a dialog or other top-level window.
struct config_rect { std::string name; nlohmann::json* store; RECT value = { 0, 0, 0, 0 }; bool loaded = false; static bool peek(RECT& v, const nlohmann::json& j, std::string_view n); static bool peek(RECT& v, HWND w); RECT peek(const nlohmann::json& j, std::string_view n) const; RECT peek(HWND w) const; static void show(HWND w, const RECT& v = RECT()); RECT& get(const nlohmann::json& j, std::string_view n); RECT& get(HWND w); RECT& get(); const RECT& put(nlohmann::json& j, std::string_view n) const; const RECT& put(HWND w); operator RECT&(); config_rect& operator=(const RECT& v); config_rect(); config_rect(const std::string& name, nlohmann::json& store = configuration); };
config_rect() config_rect(const std::string& name, nlohmann::json& store = configuration)
Constructs a config_rect
object.
name
(usually given as a character literal) specifies the name used for the member that will store this array in ajson
object. Ifname
is omitted, ajson
object is never accessed unless explicitly specified in a call topeek
,get
orput
.store
specifies thenlohmann::json
object containing a member in which this array is stored. If omitted whenname
is specified, the global objectconfiguration
is used.- You normally use the
get
andput
functions, assignment, and implicit or explicit conversion to RECT to access the value of aconfig_rect
variable. If the first access is through assignment orget
with anHWND
, the assigned or retrieved value is set and, ifname
was specified, a copy is written to thejson
store. If the first access is through conversion,get
without arguments orput
with anHWND
andname
was specified, an attempt is made to read the value from thejson
store; if the attempt fails, or ifname
was not specified, the value is set to{0, 0, 0, 0}
.
std::string name
The name
member contains the name under which the array is saved in a json
store. Normally you should set this using the name
argument to the config_rect
constructor and never change it.
nlohmann::json* store
The store
member contains a pointer to the json
store in which a copy of this array is kept, or null if no store is used. Normally you should let the constructor set this to the address of the global configuration
object (or to null if name
is not specified) and never change it.
RECT value
Ordinarily, you should use implicit or explicit conversion to RECT
or the get()
member function without arguments to read the value of a config_rect
variable, and assignment or one of the get
functions with an HWND
to update it, since these will maintain synchronization with the json
store. However, you can access the RECT directly 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) updates value
. Its purpose is to control reading from the json
store: once a value has been set, whatever value is present is used, and the json
store is not read again.
static bool peek(RECT& v, const nlohmann::json& j, std::string_view n) static bool peek(RECT& v, HWND w) RECT peek(const nlohmann::json& j, std::string_view n) const RECT peek(HWND w) const
The peek
member functions retrieve a value from a json
object or from the current bounding rectangle of a dialog or other top-level window without setting the value
member.
v
is a reference to a RECT. If retrieval is successful, it is set to the retrieved rectangle 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).n
specifies the name of the member of the JSON object which contains an array that will be copied tov
.w
specifies the window handle of a dialog or other top-level window.- The forms that return a
RECT
return the retrieved value or the current bounding rectangle of the specified window; if retrieval fails, they return the current value of thevalue
member.
static void show(HWND w, const RECT& v = RECT())
The show
member function displays the specified dialog or other top-level window at the position and size indicated by the specified RECT
. No data from the config_rect
object is used. If the RECT
is {0, 0, 0, 0}
(the default), the size of the dialog or other top-level window is unchanged, and it is centered on its owner window, or on the desktop if it has no owner window.
w
specifies the window handle of a dialog or other top-level window to be positioned.v
specifies the RECT containing the desired window bounds.
RECT& get(const nlohmann::json& j, std::string_view n) RECT& get(HWND w) RECT& get()
The get
member functions retrieve the RECT structure from either a json
object or the current bounds of a dialog or other top-level window and return a reference to the value
member.
get()
, with no arguments, attempts to retrieve the JSON array corresponding toname
from the associated JSON store ifname
was specified in the constructor andloaded
isfalse
, then store it invalue
. In all other cases, or if the attempt to retrieve the array fails,value
is not changed.j
designates ajson
object (in the C++ sense of object) which contains an object (in the JSON sense of object).n
specifies the name of the member of the JSON object which contains the array to be retrieved.w
specifies the window handle of a dialog or other top-level window the bounds of which are to be retrieved.
const RECT& put(nlohmann::json& j, std::string_view n) const const RECT& put(HWND w)
The put
member functions copy the value of a config_rect
object to a json
object or set the bounds of a dialog or other top-level window to the stored rectangle. If the value
is {0, 0, 0, 0}
, the size of the dialog or other top-level window is unchanged, and it is centered on its owner window, or on the desktop if it has no owner window. 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). This form ofput
never changesvalue
.n
specifies the name of the member of the JSON object to which an array representing the rectangle is assigned.w
specifies the window handle of a dialog or other top-level window to be positioned. This form ofput
can changevalue
. Ifname
was specified in the constructor andloaded
isfalse
,put
-to-HWND
first attempts to retrieve the windows bounds corresponding toname
from the JSON store. In all other cases, or if the attempt to retrieve the bounds fails,value
is not changed.
operator RECT&()
Conversion to RECT&
is identical to get()
.
config_rect& operator=(const RECT& v);
Assignment from a RECT copies the RECT
to value
and sets loaded
to true
. If name
was specified in the constructor it then writes the new array to the name
member of the JSON store.
Detailed specifications for DialogStretch
DialogStretch
helps manage the sizing and placement of controls in resizable dialogs.
struct DialogStretch { HWND dialog; RECT original; std::map<HWND, RECT> controls; DialogStretch(); void setup(HWND hwndDlg); int originalWidth () const; int originalHeight() const; class Stretched { public: Stretched& adjust(HWND h, double xStretch, double yStretch = 0, double xMove = 0, double yMove = 0); Stretched& adjust(int control, double xStretch, double yStretch = 0, double xMove = 0, double yMove = 0); }; Stretched adjust(HWND h, double xStretch, double yStretch = 0, double xMove = 0, double yMove = 0); Stretched adjust(int control, double xStretch, double yStretch = 0, double xMove = 0, double yMove = 0); };
DialogStretch()
Constructs a DialogStretch
object. This object must persist throughout the lifetime of the dialog box.
HWND dialog
Holds the handle to the dialog window. The setup
member function sets this; you should not change it.
RECT original
Holds the bounds of the dialog window at the time setup
was called; you should not change this.
std::map<HWND, RECT> controls
Maps the IDs of all controls in the dialog to the bounds of their windows at the time setup
was called; you should not change this.
void setup(HWND hwndDlg)
Saves information about a dialog that will allow the adjust
function to adjust the size and position of controls in the dialog. This function must be called during WM_INITDIALOG
before there are any changes to the size of the dialog window, so it can record the positions and sizes established by the dialog template.
hwndDlg
specifies the handle of the dialog window.
int originalWidth () const
Returns the width of the dialog box at the time setup
was called.
int originalHeight() const
Returns the height of the dialog box at the time setup
was called.
Stretched adjust(HWND h, double xStretch, double yStretch = 0, double xMove = 0, double yMove = 0); Stretched adjust(int control, double xStretch, double yStretch = 0, double xMove = 0, double yMove = 0);
Resizes a control in a dialog based on the original size of the dialog and the control, the new size of the dialog, and specified ratios for stretching and moving. This function is normally called when the dialog procedure receives a WM_SIZE
message.
h
specifies the window handle of a control in the dialog box.control
specifies the control ID of a control in the dialog box.xStretch
specifies the fraction of change in the width of the dialog box which should be reflected as a change in the width of the control. Typically this will be either0
, meaning the width of the control does not change, or1
, meaning the control stretches as much as the dialog box stretches; but other values can be used as needed.yStretch
specifies the fraction of change in the height of the dialog box which should be reflected as a change in the height of the control. Typically this will be either0
, meaning the height of the control does not change, or1
, meaning the control stretches as much as the dialog box stretches; but other values can be used as needed.xMove
specifies the fraction of change in the width of the dialog box which should be reflected as a change in the horizontal position of the control, as measured from the left edge of the dialog box. Typically this will be either0
, meaning the left edge of the control does not move relative to the left edge of the dialog;1
, meaning the left edge of the control does not move relative to the right edge of the dialog; or0.5
, meaning the left edge of the control does not move relative to the horizontal center of the dialog; but other values can be used as needed.yMove
specifies the fraction of change in the height of the dialog box which should be reflected as a change in the vertical position of the control, as measured from the top of the dialog box. Typically this will be either0
, meaning the top of the control does not move relative to the top of the dialog;1
, meaning the top of the control does not move relative to the bottom of the dialog; or0.5
, meaning the top of the control does not move relative to the vertical center of the dialog; but other values can be used as needed.- The
adjust
functions can be applied to either aDialogStretch
object or to the object returned by anotheradjust
function. This allowsadjust
functions to be chained, which is slightly more efficient than repeating theDialogStretch
reference for eachadjust
call, since the first call must retrieve information about the current size of the dialog.