#pragma once #include #include namespace PowerToysSettings { class HotkeyObject; class Settings { public: Settings( const HINSTANCE hinstance, // Module handle of the PowerToy DLL 'IMAGE_DOS_HEADER __ImageBase' const std::wstring& powertoy_name ); // Add additional general information to the PowerToy settings. void set_description(UINT resource_id); void set_description(const std::wstring& description); void set_icon_key(const std::wstring& icon_key); void set_overview_link(const std::wstring& overview_link); void set_video_link(const std::wstring& video_link); // Add properties to the PowerToy settings. void add_bool_toogle(const std::wstring& name, UINT description_resource_id, bool value); void add_bool_toogle(const std::wstring& name, const std::wstring& description, bool value); void add_int_spinner(const std::wstring& name, UINT description_resource_id, int value, int min, int max, int step); void add_int_spinner(const std::wstring& name, const std::wstring& description, int value, int min, int max, int step); void add_string(const std::wstring& name, UINT description_resource_id, const std::wstring& value); void add_string(const std::wstring& name, const std::wstring& description, const std::wstring& value); void add_multiline_string(const std::wstring& name, UINT description_resource_id, const std::wstring& value); void add_multiline_string(const std::wstring& name, const std::wstring& description, const std::wstring& value); void add_color_picker(const std::wstring& name, UINT description_resource_id, const std::wstring& value); void add_color_picker(const std::wstring& name, const std::wstring& description, const std::wstring& value); void add_hotkey(const std::wstring& name, UINT description_resource_id, const HotkeyObject& hotkey); void add_hotkey(const std::wstring& name, const std::wstring& description, const HotkeyObject& hotkey); void add_choice_group(const std::wstring& name, UINT description_resource_id, const std::wstring& value, const std::vector>& keys_and_text_ids); void add_choice_group(const std::wstring& name, const std::wstring& description, const std::wstring& value, const std::vector>& keys_and_texts); void add_dropdown(const std::wstring& name, UINT description_resource_id, const std::wstring& value, const std::vector>& keys_and_text_ids); void add_dropdown(const std::wstring& name, const std::wstring& description, const std::wstring& value, const std::vector>& keys_and_texts); void add_custom_action(const std::wstring& name, UINT description_resource_id, UINT button_text_resource_id, UINT ext_description_resource_id); void add_custom_action(const std::wstring& name, UINT description_resource_id, UINT button_text_resource_id, const std::wstring& value); void add_custom_action(const std::wstring& name, const std::wstring& description, const std::wstring& button_text, const std::wstring& value); // Serialize the internal json to a string. std::wstring serialize(); // Serialize the internal json to the input buffer. bool serialize_to_buffer(wchar_t* buffer, int* buffer_size); private: web::json::value m_json; int m_curr_priority = 0; // For keeping order when adding elements. HINSTANCE m_instance; std::wstring get_resource(UINT resource_id); }; class PowerToyValues { public: PowerToyValues(const std::wstring& powertoy_name); static PowerToyValues from_json_string(const std::wstring& json); static PowerToyValues load_from_settings_file(const std::wstring& powertoy_name); template void add_property(const std::wstring& name, T value); // Check property value type bool is_bool_value(const std::wstring& property_name); bool is_int_value(const std::wstring& property_name); bool is_string_value(const std::wstring& property_name); bool is_object_value(const std::wstring& property_name); // Get property value bool get_bool_value(const std::wstring& property_name); int get_int_value(const std::wstring& property_name); std::wstring get_string_value(const std::wstring& property_name); web::json::value get_json(const std::wstring& property_name); std::wstring serialize(); void save_to_settings_file(); private: const std::wstring m_version = L"1.0"; void set_version(); web::json::value m_json; std::wstring _name; PowerToyValues() {} }; class CustomActionObject { public: static CustomActionObject from_json_string(const std::wstring& json) { web::json::value parsed_json = web::json::value::parse(json); return CustomActionObject(parsed_json); } std::wstring get_name() { return m_json[L"action_name"].as_string(); } std::wstring get_value() { return m_json[L"value"].as_string(); } protected: CustomActionObject(web::json::value action_json) : m_json(action_json) {}; web::json::value m_json; }; class HotkeyObject { public: static HotkeyObject from_json(web::json::value json) { return HotkeyObject(json); } static HotkeyObject from_json_string(const std::wstring& json) { web::json::value parsed_json = web::json::value::parse(json); return HotkeyObject(parsed_json); } static HotkeyObject from_settings(bool win_pressed, bool ctrl_pressed, bool alt_pressed, bool shift_pressed, UINT vk_code) { web::json::value json = web::json::value::object(); json.as_object()[L"win"] = web::json::value::boolean(win_pressed); json.as_object()[L"ctrl"] = web::json::value::boolean(ctrl_pressed); json.as_object()[L"alt"] = web::json::value::boolean(alt_pressed); json.as_object()[L"shift"] = web::json::value::boolean(shift_pressed); json.as_object()[L"code"] = web::json::value::number(vk_code); json.as_object()[L"key"] = web::json::value::string(key_from_code(vk_code)); return HotkeyObject(json); } const web::json::value& get_json() const { return m_json; } std::wstring get_key() { return key_from_code(get_code()); } UINT get_code() { return m_json[L"code"].as_integer(); } bool win_pressed() { return m_json[L"win"].as_bool(); } bool ctrl_pressed() { return m_json[L"ctrl"].as_bool(); } bool alt_pressed() { return m_json[L"alt"].as_bool(); } bool shift_pressed() { return m_json[L"shift"].as_bool(); } UINT get_modifiers_repeat() { return (win_pressed() ? MOD_WIN : 0) | (ctrl_pressed() ? MOD_CONTROL : 0) | (alt_pressed() ? MOD_ALT : 0) | (shift_pressed() ? MOD_SHIFT : 0); } UINT get_modifiers() { return get_modifiers_repeat() | MOD_NOREPEAT; } protected: static std::wstring key_from_code(UINT key_code) { auto scan_code = MapVirtualKeyW(key_code, MAPVK_VK_TO_VSC); auto layout = GetKeyboardLayout(0); std::array key_states{}; // zero-initialize, no key pressed std::array output; auto output_bytes = ToUnicodeEx(key_code, scan_code, key_states.data(), output.data(), (int)output.size() - 1, 0, layout); if (output_bytes == 0) { return L"(unknown)"; } else { if (output_bytes == -1) { output_bytes = 1; } output[output_bytes] = 0; return output.data(); } } HotkeyObject(web::json::value hotkey_json) : m_json(hotkey_json) { if (m_json.has_number_field(L"code")) { m_json.as_object()[L"key"] = web::json::value::string(key_from_code(get_code())); } }; web::json::value m_json; }; }