forked from microsoft/PowerToys
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsystem_menu_helper.cpp
129 lines (114 loc) · 4 KB
/
system_menu_helper.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
#include "pch.h"
#include "system_menu_helper.h"
#include <interface/powertoy_module_interface.h>
namespace {
constexpr int KSeparatorPos = 1;
constexpr int KNewItemPos = 2;
unsigned int GenerateItemId() {
static unsigned int generator = 0x70777479;
return ++generator;
}
}
SystemMenuHelper& SystemMenuHelperInstace() {
static SystemMenuHelper instance;
return instance;
}
void SystemMenuHelper::SetConfiguration(PowertoyModuleIface* module, const std::vector<ItemInfo>& config) {
Reset(module);
Configurations[module] = config;
for (auto& [window, modules] : ProcessedModules) {
// Unregister module. After system menu is opened again, new configuration will be applied.
modules.erase(std::remove(std::begin(modules), std::end(modules), module), std::end(modules));
}
}
void SystemMenuHelper::ProcessSelectedItem(PowertoyModuleIface* module, HWND window, const wchar_t* itemName) {
for (const auto& item : Configurations[module]) {
if (itemName == item.name && item.checkBox) {
// Handle check/uncheck action only if specified by module configuration.
for (const auto& [id, data] : IdMappings) {
if (data.second == itemName) {
HMENU systemMenu = GetSystemMenu(window, false);
int state = (GetMenuState(systemMenu, id, MF_BYCOMMAND) == MF_CHECKED) ? MF_UNCHECKED : MF_CHECKED;
CheckMenuItem(systemMenu, id, MF_BYCOMMAND | state);
break;
}
}
break;
}
}
}
bool SystemMenuHelper::Customize(PowertoyModuleIface* module, HWND window) {
auto& modules = ProcessedModules[window];
for (const auto& m : modules) {
if (module == m) {
return false;
}
}
AddSeparator(module, window);
for (const auto& info : Configurations[module]) {
AddItem(module, window, info.name, info.enable);
}
modules.push_back(module);
return true;
}
void SystemMenuHelper::Reset(PowertoyModuleIface* module) {
for (auto& [window, modules] : ProcessedModules) {
if (HMENU systemMenu{ GetSystemMenu(window, false) }) {
for (auto& [id, data] : IdMappings) {
if (data.first == module) {
DeleteMenu(systemMenu, id, MF_BYCOMMAND);
}
}
}
}
}
bool SystemMenuHelper::HasCustomConfig(PowertoyModuleIface* module) {
return Configurations.find(module) != Configurations.end();
}
bool SystemMenuHelper::AddItem(PowertoyModuleIface* module, HWND window, const std::wstring& name, const bool enable) {
if (HMENU systemMenu{ GetSystemMenu(window, false) }) {
MENUITEMINFO item;
item.cbSize = sizeof(item);
item.fMask = MIIM_ID | MIIM_STRING | MIIM_STATE;
item.fState = MF_UNCHECKED | MF_DISABLED; // Item is disabled by default.
item.wID = GenerateItemId();
item.dwTypeData = const_cast<WCHAR*>(name.c_str());
item.cch = (UINT)name.size() + 1;
if (InsertMenuItem(systemMenu, GetMenuItemCount(systemMenu) - KNewItemPos, true, &item)) {
IdMappings[item.wID] = { module, name };
if (enable) {
EnableMenuItem(systemMenu, item.wID, MF_BYCOMMAND | MF_ENABLED);
}
return true;
}
}
return false;
}
bool SystemMenuHelper::AddSeparator(PowertoyModuleIface* module, HWND window) {
if (HMENU systemMenu{ GetSystemMenu(window, false) }) {
MENUITEMINFO separator;
separator.cbSize = sizeof(separator);
separator.fMask = MIIM_ID | MIIM_FTYPE;
separator.fType = MFT_SEPARATOR;
separator.wID = GenerateItemId();
if (InsertMenuItem(systemMenu, GetMenuItemCount(systemMenu) - KSeparatorPos, true, &separator)) {
IdMappings[separator.wID] = { module, L"sepparator_dummy_name" };
return true;
}
}
return false;
}
PowertoyModuleIface* SystemMenuHelper::ModuleFromItemId(const int& id) {
auto it = IdMappings.find(id);
if (it != IdMappings.end()) {
return it->second.first;
}
return nullptr;
}
const std::wstring SystemMenuHelper::ItemNameFromItemId(const int& id) {
auto itemIt = IdMappings.find(id);
if (itemIt != IdMappings.end()) {
return itemIt->second.second;
}
return std::wstring{};
}