- Put the `ModuleTemplate.zip` file inside the `%USERPROFILE%\Documents\Visual Studio 2019\Templates\ProjectTemplates\` folder, which is the default *User project templates location*. You can change that location via `Tools > Options > Projects and Solutions`.
If you'd like to work on a PowerToy template, make required modifications to `\tools\project_template\ModuleTemplate.vcxproj` and then use the dedicated solution `PowerToyTemplate.sln` to export it as a template. Note that `ModuleTemplate.vcxproj` is actually a project template, therefore uncompilable, so we also have a dedicated `ModuleTemplateCompileTest.vcxproj` project referenced from the `PowerToys.sln` to help keeping the template sources up to date and verify it compiles correctly.
- Add the new PowerToy project to the `src\modules\` folder for all the relative paths to work.
- For the module interface implementation take a look at [the interface](/src/modules/interface) and
[the example PowerToy implementation](/src/modules/example_powertoy/dllmain.cpp)
- Each PowerToy is built as a DLL and in order to be loaded at run-time, the PowerToy's DLL name needs to be added to the `known_dlls` map in [src/runner/main.cpp](/src/runner/main.cpp).
## DPI Awareness
All PowerToy modules need to be DPI aware and calculate dimensions and positions of the UI elements using the Windows API for DPI awareness.
The `/src/common` library has some helpers that you can use and extend:
PowerToys provides a settings infrastructure to add a settings page for new modules. The PowerToys Settings application is accessed from the PowerToys tray icon, it provides a global settings page and a dedicated settings page for each module.
The PowerToys settings API provides a way to define the required information and controls for the module's settings page and methods to read and persist the settings values. A module may need a more complex way to configure the user's preferences, in that case it can provide its own custom settings editor that can be invoked from the module's settings page through a dedicated button.
The settings specification can be read at [doc/specs/PowerToys-settings.md](/doc/specs/PowerToys-settings.md).
A PowerToy can provide this general information about itself:
- **[name](#name)**: The name of the PowerToy.
- **[description](#description)**: A text describing the PowerToy.
- **[icon_key](#icon_key)**: The identifier of the PowerToy icon in the [`settings-web` project](/src/settings-web#updating-the-icons).
- **[overview_link](#overview_link)**: A link to an extended overview of the PowerToy.
- **[video_link](#video_link)**: A link to a video showcasing the PowerToy.
A PowerToy can define settings of the following types:
- **[bool_toggle](#bool_toggle)**: A boolean property, edited with a Toggle control.
- **[int_spinner](#int_spinner)**: An integer property, edited with a Spinner control.
- **[string](#string)**: A string property, edited with a TextBox control.
- **[color_picker](#color_picker)**: A color property, edited with a ColorPicker control.
- **[custom_action](#custom_action)**: A custom action property, invoked from the settings by a Button control.
Here's an example of what the settings look like in the Settings screen:
![Image of the Options](/doc/images/example_powertoy/settings.png)
### How to add your module's settings page
The PowerToy can set its settings information and controls by overriding the [PowerToy's Interface `get_config` method](/src/modules/interface/README.md#get_config) and returning a serialized [`PowerToysSettings::Settings`](/src/common/settings_object.h) object that's been filled with the required informations and controls.
The PowerToy can receive the new values by overriding the [PowerToy's Interface `set_config` method](/src/modules/interface/README.md#set_config), parsing the serialized [`PowerToysSettings::PowerToyValues`](/src/common/settings_object.h) object and applying the new settings.
Here's an example from [the example PowerToy implementation](/src/modules/example_powertoy/dllmain.cpp):
A color property, edited with a ColorPicker control. Its value is a string with the `'#RRGGBB'` format, with two hexadecimal digits for each color component.
It can be added to a `Settings` object by calling `add_color_picker`.
```cpp
// Add a string property with a color picker editor.
settings.add_color_picker(
L"test_color_picker", // property name.
L"This is what a ColorPicker property looks like", // description or resource id of the localized string.
g_settings.test_color_prop // property value.
);
```
The `'#RRGGBB'`-format string can be read from a `PowerToyValues` object by calling `get_string_value`.
```cpp
// Update the color property.
if (values.is_string_value(L"test_color_picker")) {
L"This is what a CustomAction property looks like", // label above the field: a string literal or a resource id
L"Call a custom action", // button text: a string literal or a resource id
L"Press the button to call a custom action in the Example PowerToy" // display values / extended info: a string literal or a resource id
);
```
When the custom action button is pressed, the PowerToy's `call_custom_action()` is called with a serialized [`PowerToysSettings::CustomActionObject`](/src/common/settings_object.h) object.
```cpp
// Signal from the Settings editor to call a custom action.
// This can be used to spawn more complex editors.
By default, the PowerToys settings are persisted in the User's `%LocalAppData%\Microsoft\PowerToys` path.
Each PowerToy has its own folder for saving the persisted settings data.
Loading and saving the settings in the default location can be achieved through the use of a [`PowerToysSettings::PowerToyValues`](/src/common/settings_object.h) object.
#### Loading settings
The PowerToy can load the saved `PowerToyValues` object through the use of the `load_from_settings_file` method.
Here's an example from [the example PowerToy implementation](/src/modules/example_powertoy/dllmain.cpp):
```cpp
// Load the settings file.
void ExamplePowertoy::init_settings() {
try {
// Load and parse the settings file for this PowerToy.
// Save the PowerToyValues JSON to the power toy settings file.
values.save_to_settings_file();
}
catch (std::exception ex) {
// Couldn't save the settings.
}
}
```
## Add a new PowerToy to the Installer
In the `installer` folder, open the `PowerToysSetup.sln` solution.
Under the `PowerToysSetup` project, edit `Product.wxs`.
You will need to add a component for your module DLL. Search for `Module_ShortcutGuide` to see where to add the component declaration and where to reference that declaration so the DLL is added to the installer.
Each component requires a newly generated GUID (you can use the Visual Studio integrated tool to generate one).
Repeat the process for each extra file your PowerToy module requires.
If your PowerToy comes with a subfolder containing for example images, follow the example of the `PowerToysSvgs` component.