mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-02-24 04:00:02 +01:00
Add taskbar indicators
This commit is contained in:
@@ -718,6 +718,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PowerRename.FuzzingTest", "
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ShortcutGuide.IndexYmlGenerator", "src\modules\ShortcutGuideV2\ShortcutGuide.IndexYmlGenerator\ShortcutGuide.IndexYmlGenerator\ShortcutGuide.IndexYmlGenerator.csproj", "{D640B00C-9149-4C4F-8B7D-E2B8B2590A0B}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ShortcutGuide.CPPProject", "src\modules\ShortcutGuideV2\ShortcutGuide.CPPProject\ShortcutGuide.CPPProject.vcxproj", "{C992FD2C-83B8-4941-9FC1-09730068D8EC}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|ARM64 = Debug|ARM64
|
||||
@@ -2632,6 +2634,14 @@ Global
|
||||
{D640B00C-9149-4C4F-8B7D-E2B8B2590A0B}.Release|ARM64.Build.0 = Release|ARM64
|
||||
{D640B00C-9149-4C4F-8B7D-E2B8B2590A0B}.Release|x64.ActiveCfg = Release|x64
|
||||
{D640B00C-9149-4C4F-8B7D-E2B8B2590A0B}.Release|x64.Build.0 = Release|x64
|
||||
{C992FD2C-83B8-4941-9FC1-09730068D8EC}.Debug|ARM64.ActiveCfg = Debug|x64
|
||||
{C992FD2C-83B8-4941-9FC1-09730068D8EC}.Debug|ARM64.Build.0 = Debug|x64
|
||||
{C992FD2C-83B8-4941-9FC1-09730068D8EC}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{C992FD2C-83B8-4941-9FC1-09730068D8EC}.Debug|x64.Build.0 = Debug|x64
|
||||
{C992FD2C-83B8-4941-9FC1-09730068D8EC}.Release|ARM64.ActiveCfg = Release|x64
|
||||
{C992FD2C-83B8-4941-9FC1-09730068D8EC}.Release|ARM64.Build.0 = Release|x64
|
||||
{C992FD2C-83B8-4941-9FC1-09730068D8EC}.Release|x64.ActiveCfg = Release|x64
|
||||
{C992FD2C-83B8-4941-9FC1-09730068D8EC}.Release|x64.Build.0 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
@@ -2908,6 +2918,7 @@ Global
|
||||
{5F63C743-F6CE-4DBA-A200-2B3F8A14E8C2} = {3846508C-77EB-4034-A702-F8BB263C4F79}
|
||||
{2694E2FB-DCD5-4BFF-A418-B6C3C7CE3B8E} = {89E20BCE-EB9C-46C8-8B50-E01A82E6FDC3}
|
||||
{D640B00C-9149-4C4F-8B7D-E2B8B2590A0B} = {21275C57-1C20-4F07-8A56-21BFA8363BDB}
|
||||
{C992FD2C-83B8-4941-9FC1-09730068D8EC} = {21275C57-1C20-4F07-8A56-21BFA8363BDB}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {C3A2F9D1-7930-4EF4-A6FC-7EE0A99821D0}
|
||||
|
||||
@@ -65,14 +65,12 @@
|
||||
<ClInclude Include="Generated Files\resource.h" />
|
||||
<ClInclude Include="native_event_waiter.h" />
|
||||
<ClInclude Include="overlay_window.h" />
|
||||
<ClInclude Include="pch.h" />
|
||||
<ClInclude Include="resource.base.h" />
|
||||
<ClInclude Include="ShortcutGuideSettings.h" />
|
||||
<ClInclude Include="ShortcutGuideConstants.h" />
|
||||
<ClInclude Include="shortcut_guide.h" />
|
||||
<ClInclude Include="start_visible.h" />
|
||||
<ClInclude Include="target_state.h" />
|
||||
<ClInclude Include="tasklist_positions.h" />
|
||||
<ClInclude Include="trace.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
@@ -83,13 +81,9 @@
|
||||
<ClCompile Include="main.cpp" />
|
||||
<ClCompile Include="native_event_waiter.cpp" />
|
||||
<ClCompile Include="overlay_window.cpp" />
|
||||
<ClCompile Include="pch.cpp">
|
||||
<PrecompiledHeader Condition="'$(UsePrecompiledHeaders)' != 'false'">Create</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="shortcut_guide.cpp" />
|
||||
<ClCompile Include="start_visible.cpp" />
|
||||
<ClCompile Include="target_state.cpp" />
|
||||
<ClCompile Include="tasklist_positions.cpp" />
|
||||
<ClCompile Include="trace.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
||||
@@ -18,9 +18,6 @@
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="pch.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="animation.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
@@ -51,9 +48,6 @@
|
||||
<ClInclude Include="target_state.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="tasklist_positions.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="trace.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
@@ -68,9 +62,6 @@
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="pch.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="main.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
@@ -101,9 +92,6 @@
|
||||
<ClCompile Include="target_state.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="tasklist_positions.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="trace.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
@@ -116,7 +104,79 @@
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<CopyFileToFolders Include="Assets\ShortcutGuide\**">
|
||||
<CopyFileToFolders Include="Assets\ShortcutGuide\1.svg">
|
||||
<Filter>Resource Files</Filter>
|
||||
</CopyFileToFolders>
|
||||
<CopyFileToFolders Include="Assets\ShortcutGuide\2.svg">
|
||||
<Filter>Resource Files</Filter>
|
||||
</CopyFileToFolders>
|
||||
<CopyFileToFolders Include="Assets\ShortcutGuide\3.svg">
|
||||
<Filter>Resource Files</Filter>
|
||||
</CopyFileToFolders>
|
||||
<CopyFileToFolders Include="Assets\ShortcutGuide\4.svg">
|
||||
<Filter>Resource Files</Filter>
|
||||
</CopyFileToFolders>
|
||||
<CopyFileToFolders Include="Assets\ShortcutGuide\5.svg">
|
||||
<Filter>Resource Files</Filter>
|
||||
</CopyFileToFolders>
|
||||
<CopyFileToFolders Include="Assets\ShortcutGuide\6.svg">
|
||||
<Filter>Resource Files</Filter>
|
||||
</CopyFileToFolders>
|
||||
<CopyFileToFolders Include="Assets\ShortcutGuide\7.svg">
|
||||
<Filter>Resource Files</Filter>
|
||||
</CopyFileToFolders>
|
||||
<CopyFileToFolders Include="Assets\ShortcutGuide\8.svg">
|
||||
<Filter>Resource Files</Filter>
|
||||
</CopyFileToFolders>
|
||||
<CopyFileToFolders Include="Assets\ShortcutGuide\9.svg">
|
||||
<Filter>Resource Files</Filter>
|
||||
</CopyFileToFolders>
|
||||
<CopyFileToFolders Include="Assets\ShortcutGuide\no_active_window.svg">
|
||||
<Filter>Resource Files</Filter>
|
||||
</CopyFileToFolders>
|
||||
<CopyFileToFolders Include="Assets\ShortcutGuide\overlay.svg">
|
||||
<Filter>Resource Files</Filter>
|
||||
</CopyFileToFolders>
|
||||
<CopyFileToFolders Include="Assets\ShortcutGuide\overlay_portrait.svg">
|
||||
<Filter>Resource Files</Filter>
|
||||
</CopyFileToFolders>
|
||||
<CopyFileToFolders Include="Assets\ShortcutGuide\0.svg">
|
||||
<Filter>Resource Files</Filter>
|
||||
</CopyFileToFolders>
|
||||
<CopyFileToFolders Include="Assets\ShortcutGuide\1.svg">
|
||||
<Filter>Resource Files</Filter>
|
||||
</CopyFileToFolders>
|
||||
<CopyFileToFolders Include="Assets\ShortcutGuide\2.svg">
|
||||
<Filter>Resource Files</Filter>
|
||||
</CopyFileToFolders>
|
||||
<CopyFileToFolders Include="Assets\ShortcutGuide\3.svg">
|
||||
<Filter>Resource Files</Filter>
|
||||
</CopyFileToFolders>
|
||||
<CopyFileToFolders Include="Assets\ShortcutGuide\4.svg">
|
||||
<Filter>Resource Files</Filter>
|
||||
</CopyFileToFolders>
|
||||
<CopyFileToFolders Include="Assets\ShortcutGuide\5.svg">
|
||||
<Filter>Resource Files</Filter>
|
||||
</CopyFileToFolders>
|
||||
<CopyFileToFolders Include="Assets\ShortcutGuide\6.svg">
|
||||
<Filter>Resource Files</Filter>
|
||||
</CopyFileToFolders>
|
||||
<CopyFileToFolders Include="Assets\ShortcutGuide\7.svg">
|
||||
<Filter>Resource Files</Filter>
|
||||
</CopyFileToFolders>
|
||||
<CopyFileToFolders Include="Assets\ShortcutGuide\8.svg">
|
||||
<Filter>Resource Files</Filter>
|
||||
</CopyFileToFolders>
|
||||
<CopyFileToFolders Include="Assets\ShortcutGuide\9.svg">
|
||||
<Filter>Resource Files</Filter>
|
||||
</CopyFileToFolders>
|
||||
<CopyFileToFolders Include="Assets\ShortcutGuide\no_active_window.svg">
|
||||
<Filter>Resource Files</Filter>
|
||||
</CopyFileToFolders>
|
||||
<CopyFileToFolders Include="Assets\ShortcutGuide\overlay.svg">
|
||||
<Filter>Resource Files</Filter>
|
||||
</CopyFileToFolders>
|
||||
<CopyFileToFolders Include="Assets\ShortcutGuide\overlay_portrait.svg">
|
||||
<Filter>Resource Files</Filter>
|
||||
</CopyFileToFolders>
|
||||
</ItemGroup>
|
||||
|
||||
@@ -25,5 +25,4 @@
|
||||
#include <tuple>
|
||||
#include <unordered_set>
|
||||
#include <string>
|
||||
#include <filesystem>
|
||||
#include <common/logger/logger.h>
|
||||
#include <filesystem>
|
||||
@@ -1,116 +1,193 @@
|
||||
#include "pch.h"
|
||||
#include "tasklist_positions.h"
|
||||
#include <windows.h>
|
||||
#include <vector>
|
||||
#include <winrt/base.h>
|
||||
#include <UIAutomation.h>
|
||||
|
||||
void Tasklist::update()
|
||||
extern "C"
|
||||
{
|
||||
// Get HWND of the tasklist
|
||||
auto tasklist_hwnd = FindWindowA("Shell_TrayWnd", nullptr);
|
||||
if (!tasklist_hwnd)
|
||||
return;
|
||||
tasklist_hwnd = FindWindowExA(tasklist_hwnd, 0, "ReBarWindow32", nullptr);
|
||||
if (!tasklist_hwnd)
|
||||
return;
|
||||
tasklist_hwnd = FindWindowExA(tasklist_hwnd, 0, "MSTaskSwWClass", nullptr);
|
||||
if (!tasklist_hwnd)
|
||||
return;
|
||||
tasklist_hwnd = FindWindowExA(tasklist_hwnd, 0, "MSTaskListWClass", nullptr);
|
||||
if (!tasklist_hwnd)
|
||||
return;
|
||||
if (!automation)
|
||||
{
|
||||
winrt::check_hresult(CoCreateInstance(CLSID_CUIAutomation,
|
||||
nullptr,
|
||||
CLSCTX_INPROC_SERVER,
|
||||
IID_IUIAutomation,
|
||||
automation.put_void()));
|
||||
winrt::check_hresult(automation->CreateTrueCondition(true_condition.put()));
|
||||
}
|
||||
element = nullptr;
|
||||
winrt::check_hresult(automation->ElementFromHandle(tasklist_hwnd, element.put()));
|
||||
}
|
||||
winrt::com_ptr<IUIAutomation> automation;
|
||||
winrt::com_ptr<IUIAutomationElement> element;
|
||||
winrt::com_ptr<IUIAutomationCondition> true_condition;
|
||||
|
||||
bool Tasklist::update_buttons(std::vector<TasklistButton>& buttons)
|
||||
{
|
||||
if (!automation || !element)
|
||||
// Helper to get the taskbar HWND for the monitor under the cursor
|
||||
HWND GetTaskbarHwndForCursorMonitor(HMONITOR monitor)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
winrt::com_ptr<IUIAutomationElementArray> elements;
|
||||
if (element->FindAll(TreeScope_Children, true_condition.get(), elements.put()) < 0)
|
||||
return false;
|
||||
if (!elements)
|
||||
return false;
|
||||
int count;
|
||||
if (elements->get_Length(&count) < 0)
|
||||
return false;
|
||||
winrt::com_ptr<IUIAutomationElement> child;
|
||||
std::vector<TasklistButton> found_buttons;
|
||||
found_buttons.reserve(count);
|
||||
for (int i = 0; i < count; ++i)
|
||||
{
|
||||
child = nullptr;
|
||||
if (elements->GetElement(i, child.put()) < 0)
|
||||
return false;
|
||||
TasklistButton button;
|
||||
if (VARIANT var_rect; child->GetCurrentPropertyValue(UIA_BoundingRectanglePropertyId, &var_rect) >= 0)
|
||||
POINT pt;
|
||||
if (!GetCursorPos(&pt))
|
||||
return nullptr;
|
||||
|
||||
// Find the primary taskbar
|
||||
HWND primaryTaskbar = FindWindowW(L"Shell_TrayWnd", nullptr);
|
||||
if (primaryTaskbar)
|
||||
{
|
||||
if (var_rect.vt == (VT_R8 | VT_ARRAY))
|
||||
MONITORINFO mi = { sizeof(mi) };
|
||||
if (GetWindowRect(primaryTaskbar, &mi.rcMonitor))
|
||||
{
|
||||
LONG pos;
|
||||
double value;
|
||||
pos = 0;
|
||||
SafeArrayGetElement(var_rect.parray, &pos, &value);
|
||||
button.x = static_cast<long>(value);
|
||||
pos = 1;
|
||||
SafeArrayGetElement(var_rect.parray, &pos, &value);
|
||||
button.y = static_cast<long>(value);
|
||||
pos = 2;
|
||||
SafeArrayGetElement(var_rect.parray, &pos, &value);
|
||||
button.width = static_cast<long>(value);
|
||||
pos = 3;
|
||||
SafeArrayGetElement(var_rect.parray, &pos, &value);
|
||||
button.height = static_cast<long>(value);
|
||||
HMONITOR primaryMonitor = MonitorFromRect(&mi.rcMonitor, MONITOR_DEFAULTTONEAREST);
|
||||
if (primaryMonitor == monitor)
|
||||
return primaryTaskbar;
|
||||
}
|
||||
VariantClear(&var_rect);
|
||||
}
|
||||
|
||||
// Find the secondary taskbar(s)
|
||||
HWND secondaryTaskbar = nullptr;
|
||||
while ((secondaryTaskbar = FindWindowExW(nullptr, secondaryTaskbar, L"Shell_SecondaryTrayWnd", nullptr)) != nullptr)
|
||||
{
|
||||
MONITORINFO mi = { sizeof(mi) };
|
||||
RECT rc;
|
||||
if (GetWindowRect(secondaryTaskbar, &rc))
|
||||
{
|
||||
HMONITOR monitor = MonitorFromRect(&rc, MONITOR_DEFAULTTONEAREST);
|
||||
if (monitor == monitor)
|
||||
return secondaryTaskbar;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
__declspec(dllexport) void update(HMONITOR monitor)
|
||||
{
|
||||
// Get HWND of the tasklist for the monitor under the cursor
|
||||
auto taskbar_hwnd = GetTaskbarHwndForCursorMonitor(monitor);
|
||||
if (!taskbar_hwnd)
|
||||
return;
|
||||
|
||||
wchar_t class_name[64] = {};
|
||||
GetClassNameW(taskbar_hwnd, class_name, 64);
|
||||
|
||||
HWND tasklist_hwnd = nullptr;
|
||||
|
||||
if (wcscmp(class_name, L"Shell_TrayWnd") == 0)
|
||||
{
|
||||
// Primary taskbar structure
|
||||
tasklist_hwnd = FindWindowExW(taskbar_hwnd, 0, L"ReBarWindow32", nullptr);
|
||||
if (!tasklist_hwnd)
|
||||
return;
|
||||
tasklist_hwnd = FindWindowExW(tasklist_hwnd, 0, L"MSTaskSwWClass", nullptr);
|
||||
if (!tasklist_hwnd)
|
||||
return;
|
||||
tasklist_hwnd = FindWindowExW(tasklist_hwnd, 0, L"MSTaskListWClass", nullptr);
|
||||
if (!tasklist_hwnd)
|
||||
return;
|
||||
}
|
||||
else if (wcscmp(class_name, L"Shell_SecondaryTrayWnd") == 0)
|
||||
{
|
||||
// Secondary taskbar structure
|
||||
HWND workerw = FindWindowExW(taskbar_hwnd, 0, L"WorkerW", nullptr);
|
||||
if (!workerw)
|
||||
return;
|
||||
tasklist_hwnd = FindWindowExW(workerw, 0, L"MSTaskListWClass", nullptr);
|
||||
if (!tasklist_hwnd)
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Unknown taskbar type
|
||||
return;
|
||||
}
|
||||
|
||||
if (!automation)
|
||||
{
|
||||
winrt::check_hresult(CoCreateInstance(CLSID_CUIAutomation,
|
||||
nullptr,
|
||||
CLSCTX_INPROC_SERVER,
|
||||
IID_IUIAutomation,
|
||||
automation.put_void()));
|
||||
winrt::check_hresult(automation->CreateTrueCondition(true_condition.put()));
|
||||
}
|
||||
element = nullptr;
|
||||
winrt::check_hresult(automation->ElementFromHandle(tasklist_hwnd, element.put()));
|
||||
}
|
||||
|
||||
__declspec(dllexport) bool update_buttons(std::vector<TasklistButton>& buttons)
|
||||
{
|
||||
if (!automation || !element)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (BSTR automation_id; child->get_CurrentAutomationId(&automation_id) >= 0)
|
||||
winrt::com_ptr<IUIAutomationElementArray> elements;
|
||||
if (element->FindAll(TreeScope_Children, true_condition.get(), elements.put()) < 0)
|
||||
return false;
|
||||
if (!elements)
|
||||
return false;
|
||||
int count;
|
||||
if (elements->get_Length(&count) < 0)
|
||||
return false;
|
||||
winrt::com_ptr<IUIAutomationElement> child;
|
||||
std::vector<TasklistButton> found_buttons;
|
||||
found_buttons.reserve(count);
|
||||
for (int i = 0; i < count; ++i)
|
||||
{
|
||||
button.name = automation_id;
|
||||
SysFreeString(automation_id);
|
||||
child = nullptr;
|
||||
if (elements->GetElement(i, child.put()) < 0)
|
||||
return false;
|
||||
TasklistButton button;
|
||||
if (VARIANT var_rect; child->GetCurrentPropertyValue(UIA_BoundingRectanglePropertyId, &var_rect) >= 0)
|
||||
{
|
||||
if (var_rect.vt == (VT_R8 | VT_ARRAY))
|
||||
{
|
||||
LONG pos;
|
||||
double value;
|
||||
pos = 0;
|
||||
SafeArrayGetElement(var_rect.parray, &pos, &value);
|
||||
button.x = static_cast<long>(value);
|
||||
pos = 1;
|
||||
SafeArrayGetElement(var_rect.parray, &pos, &value);
|
||||
button.y = static_cast<long>(value);
|
||||
pos = 2;
|
||||
SafeArrayGetElement(var_rect.parray, &pos, &value);
|
||||
button.width = static_cast<long>(value);
|
||||
pos = 3;
|
||||
SafeArrayGetElement(var_rect.parray, &pos, &value);
|
||||
button.height = static_cast<long>(value);
|
||||
}
|
||||
VariantClear(&var_rect);
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (BSTR automation_id; child->get_CurrentAutomationId(&automation_id) >= 0)
|
||||
{
|
||||
wcsncpy_s(button.name, automation_id, _countof(button.name));
|
||||
SysFreeString(automation_id);
|
||||
}
|
||||
found_buttons.push_back(button);
|
||||
}
|
||||
found_buttons.push_back(button);
|
||||
// assign keynums
|
||||
buttons.clear();
|
||||
for (auto& button : found_buttons)
|
||||
{
|
||||
if (buttons.empty())
|
||||
{
|
||||
button.keynum = 1;
|
||||
buttons.push_back(std::move(button));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (button.x < buttons.back().x || button.y < buttons.back().y) // skip 2nd row
|
||||
break;
|
||||
if (wcsncmp(button.name, buttons.back().name, _countof(button.name)) == 0)
|
||||
continue; // skip buttons from the same app
|
||||
button.keynum = buttons.back().keynum + 1;
|
||||
buttons.push_back(std::move(button));
|
||||
if (buttons.back().keynum == 10)
|
||||
break; // no more than 10 buttons
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
// assign keynums
|
||||
buttons.clear();
|
||||
for (auto& button : found_buttons)
|
||||
|
||||
__declspec(dllexport) TasklistButton* get_buttons(HMONITOR monitor, int* size)
|
||||
{
|
||||
if (buttons.empty())
|
||||
{
|
||||
button.keynum = 1;
|
||||
buttons.push_back(std::move(button));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (button.x < buttons.back().x || button.y < buttons.back().y) // skip 2nd row
|
||||
break;
|
||||
if (button.name == buttons.back().name)
|
||||
continue; // skip buttons from the same app
|
||||
button.keynum = buttons.back().keynum + 1;
|
||||
buttons.push_back(std::move(button));
|
||||
if (buttons.back().keynum == 10)
|
||||
break; // no more than 10 buttons
|
||||
}
|
||||
update(monitor);
|
||||
static std::vector<TasklistButton> buttons;
|
||||
update_buttons(buttons);
|
||||
*size = static_cast<int>(buttons.size());
|
||||
return buttons.data();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
std::vector<TasklistButton> Tasklist::get_buttons()
|
||||
{
|
||||
std::vector<TasklistButton> buttons;
|
||||
update_buttons(buttons);
|
||||
return buttons;
|
||||
}
|
||||
@@ -7,23 +7,10 @@
|
||||
|
||||
struct TasklistButton
|
||||
{
|
||||
std::wstring name;
|
||||
long x{};
|
||||
long y{};
|
||||
long width{};
|
||||
long height{};
|
||||
long keynum{};
|
||||
};
|
||||
|
||||
class Tasklist
|
||||
{
|
||||
public:
|
||||
void update();
|
||||
std::vector<TasklistButton> get_buttons();
|
||||
bool update_buttons(std::vector<TasklistButton>& buttons);
|
||||
|
||||
private:
|
||||
winrt::com_ptr<IUIAutomation> automation;
|
||||
winrt::com_ptr<IUIAutomationElement> element;
|
||||
winrt::com_ptr<IUIAutomationCondition> true_condition;
|
||||
wchar_t name[256];
|
||||
int x;
|
||||
int y;
|
||||
int width;
|
||||
int height;
|
||||
int keynum;
|
||||
};
|
||||
|
||||
@@ -0,0 +1,149 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>17.0</VCProjectVersion>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<ProjectGuid>{c992fd2c-83b8-4941-9fc1-09730068d8ec}</ProjectGuid>
|
||||
<RootNamespace>ShortcutGuideCPPProject</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0.22621.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<OutDir>..\..\..\..\$(Platform)\$(Configuration)\WinUI3Apps\</OutDir>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\ShortcutGuide\ShortcutGuide\pch.cpp">
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\ShortcutGuide\ShortcutGuide\tasklist_positions.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\ShortcutGuide\ShortcutGuide\pch.h" />
|
||||
<ClInclude Include="..\..\ShortcutGuide\ShortcutGuide\tasklist_positions.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\common\logger\logger.vcxproj">
|
||||
<Project>{d9b8fc84-322a-4f9f-bbb9-20915c47ddfd}</Project>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,33 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Resource Files">
|
||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\ShortcutGuide\ShortcutGuide\tasklist_positions.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\ShortcutGuide\ShortcutGuide\pch.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\ShortcutGuide\ShortcutGuide\tasklist_positions.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\ShortcutGuide\ShortcutGuide\pch.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -12,6 +12,21 @@ Shortcuts:
|
||||
Alt: true
|
||||
Keys:
|
||||
- F4
|
||||
- Name: Test shortcut
|
||||
Shortcut:
|
||||
- Win: false
|
||||
Ctrl: true
|
||||
Shift: false
|
||||
Alt: false
|
||||
Keys:
|
||||
- K
|
||||
- Win: false
|
||||
Ctrl: true
|
||||
Shift: false
|
||||
Alt: false
|
||||
Keys:
|
||||
- C
|
||||
|
||||
- Name: Open shutdown box
|
||||
Description: When no windows are open
|
||||
Shortcut:
|
||||
@@ -29,12 +44,6 @@ Shortcuts:
|
||||
Alt: true
|
||||
Keys:
|
||||
- Esc
|
||||
- Win: false
|
||||
Ctrl: false
|
||||
Shift: false
|
||||
Alt: true
|
||||
Keys:
|
||||
- Esc
|
||||
- Name: Reveal typed password
|
||||
Description: On sign-in screen
|
||||
Shortcut:
|
||||
|
||||
@@ -19,6 +19,7 @@ namespace ShortcutGuide
|
||||
public static Rect GetWorkAreaForDisplayWithWindow(IntPtr hwnd)
|
||||
{
|
||||
foundMonitorIndex = -1;
|
||||
monitorIndex = 0;
|
||||
var monitor = MonitorFromWindow(hwnd, (int)MonitorFromWindowDwFlags.MONITOR_DEFAULTTONEAREST);
|
||||
EnumDisplayMonitors(IntPtr.Zero, IntPtr.Zero, MonitorEnumProc, new LPARAM(monitor));
|
||||
return MonitorInfo.GetDisplayMonitors()[foundMonitorIndex].RectWork;
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace ShortcutGuide.Helpers
|
||||
{
|
||||
internal sealed class TaskListPositions
|
||||
{
|
||||
public static List<RECT> GetTaskbarIconPositions()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct RECT
|
||||
{
|
||||
public int Left;
|
||||
public int Top;
|
||||
public int Right;
|
||||
public int Bottom;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -26,10 +26,10 @@ internal static partial class NativeMethods
|
||||
internal static partial int SetWindowLongW(IntPtr hWnd, int nIndex, int dwNewLong);
|
||||
|
||||
[LibraryImport("user32.dll", StringMarshalling = StringMarshalling.Utf16)]
|
||||
internal static partial int FindWindowA(in string lpClassName, in string? lpWindowName);
|
||||
internal static partial IntPtr FindWindowA(in string lpClassName, in string? lpWindowName);
|
||||
|
||||
[LibraryImport("user32.dll", StringMarshalling = StringMarshalling.Utf16)]
|
||||
internal static partial int FindWindowExA(int hwndParent, int hwndChildAfter, in string lpClassName, in string? lpWindowName);
|
||||
public static partial IntPtr FindWindowExA(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);
|
||||
|
||||
[LibraryImport("User32.dll")]
|
||||
internal static partial IntPtr MonitorFromWindow(int hwnd, int dwFlags);
|
||||
@@ -47,6 +47,14 @@ internal static partial class NativeMethods
|
||||
[DllImport("user32.dll", SetLastError = true)]
|
||||
public static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint processId);
|
||||
|
||||
[DllImport("ole32.dll", SetLastError = true)]
|
||||
public static extern uint CoCreateInstance(
|
||||
in Guid rclsid,
|
||||
IntPtr pUnkOuter,
|
||||
uint dwClsContext,
|
||||
in Guid riid,
|
||||
out IntPtr ppv);
|
||||
|
||||
public struct POINT
|
||||
{
|
||||
public int X;
|
||||
|
||||
@@ -60,6 +60,17 @@
|
||||
<ItemGroup>
|
||||
<ApplicationDefinition Include="ShortcutGuideXAML\App.xaml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<COMReference Include="UIAutomationClient">
|
||||
<WrapperTool>tlbimp</WrapperTool>
|
||||
<VersionMinor>0</VersionMinor>
|
||||
<VersionMajor>1</VersionMajor>
|
||||
<Guid>944de083-8fb8-45cf-bcb7-c477acb2f897</Guid>
|
||||
<Lcid>0</Lcid>
|
||||
<Isolated>false</Isolated>
|
||||
<EmbedInteropTypes>true</EmbedInteropTypes>
|
||||
</COMReference>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Include="Assets\Hosts\Hosts.ico" />
|
||||
@@ -95,6 +106,7 @@
|
||||
<ProjectReference Include="..\..\..\common\GPOWrapper\GPOWrapper.vcxproj" />
|
||||
<ProjectReference Include="..\..\..\common\ManagedCommon\ManagedCommon.csproj" />
|
||||
<ProjectReference Include="..\..\..\settings-ui\Settings.UI.Library\Settings.UI.Library.csproj" />
|
||||
<ProjectReference Include="..\ShortcutGuide.CPPProject\ShortcutGuide.CPPProject.vcxproj" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Update="Properties\Resource.Designer.cs">
|
||||
|
||||
@@ -28,6 +28,8 @@ namespace ShortcutGuide
|
||||
/// </summary>
|
||||
public sealed partial class MainWindow : WindowEx
|
||||
{
|
||||
public static nint WindowHwnd { get; set; }
|
||||
|
||||
private AppWindow _appWindow;
|
||||
|
||||
private string[] _currentApplicationIds;
|
||||
@@ -41,6 +43,7 @@ namespace ShortcutGuide
|
||||
Title = Resource.ResourceManager.GetString("Title", CultureInfo.InvariantCulture)!;
|
||||
|
||||
var hwnd = WinRT.Interop.WindowNative.GetWindowHandle(this);
|
||||
WindowHwnd = hwnd;
|
||||
WindowId windowId = Win32Interop.GetWindowIdFromWindow(hwnd);
|
||||
_appWindow = AppWindow.GetFromWindowId(windowId);
|
||||
#if !DEBUG
|
||||
@@ -75,7 +78,9 @@ namespace ShortcutGuide
|
||||
{
|
||||
if (e.WindowActivationState == WindowActivationState.Deactivated)
|
||||
{
|
||||
#if !DEBUG
|
||||
Environment.Exit(0);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (!_setPosition)
|
||||
@@ -96,6 +101,16 @@ namespace ShortcutGuide
|
||||
// Move top of the window to the center of the monitor
|
||||
_appWindow.Move(new PointInt32((int)monitorRect.X, (int)(monitorRect.Y + (int)(monitorRect.Height / 2))));
|
||||
_setPosition = true;
|
||||
AppWindow.Changed += (_, a) =>
|
||||
{
|
||||
if (a.DidPresenterChange)
|
||||
{
|
||||
Rect monitorRect = DisplayHelper.GetWorkAreaForDisplayWithWindow(hwnd);
|
||||
float dpiScale = DpiHelper.GetDPIScaleForWindow((int)hwnd);
|
||||
this.SetWindowSize(monitorRect.Width / dpiScale, monitorRect.Height / dpiScale / 2);
|
||||
_appWindow.Move(new PointInt32((int)monitorRect.X, (int)(monitorRect.Y + (int)(monitorRect.Height / 2))));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
if (WindowSelector.Items.Count == 0)
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
<SelectorBar Grid.Row="0" x:Name="CategorySelector" />
|
||||
<TextBlock x:Name="ErrorMessage" Style="{StaticResource SubheaderTextBlockStyle}" Grid.Row="1" Margin="6,0,6,0"></TextBlock>
|
||||
@@ -78,5 +79,47 @@
|
||||
</GridView>
|
||||
</Grid>
|
||||
</ScrollViewer>
|
||||
<Canvas Grid.Row="2" x:Name="TaskbarIndicators" Visibility="Collapsed" Height="20">
|
||||
<Canvas x:Name="TaskbarIndicator1" Height="10" Width="10">
|
||||
<Rectangle Fill="Blue" Height="10" Width="10" />
|
||||
<TextBlock Text="1" Foreground="White" TextAlignment="Center" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="14" FontWeight="Bold"/>
|
||||
</Canvas>
|
||||
<Canvas x:Name="TaskbarIndicator2" Canvas.Left="20" Height="10" Width="10">
|
||||
<Rectangle Fill="Blue" Height="10" Width="10" />
|
||||
<TextBlock Text="2" Foreground="White" TextAlignment="Center" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="14" FontWeight="Bold"/>
|
||||
</Canvas>
|
||||
<Canvas x:Name="TaskbarIndicator3" Canvas.Left="40" Height="10" Width="10">
|
||||
<Rectangle Fill="Blue" Height="10" Width="10" />
|
||||
<TextBlock Text="3" Foreground="White" TextAlignment="Center" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="14" FontWeight="Bold"/>
|
||||
</Canvas>
|
||||
<Canvas x:Name="TaskbarIndicator4" Canvas.Left="60" Height="10" Width="10">
|
||||
<Rectangle Fill="Blue" Height="10" Width="10" />
|
||||
<TextBlock Text="4" Foreground="White" TextAlignment="Center" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="14" FontWeight="Bold"/>
|
||||
</Canvas>
|
||||
<Canvas x:Name="TaskbarIndicator5" Canvas.Left="80" Height="10" Width="10">
|
||||
<Rectangle Fill="Blue" Height="10" Width="10" />
|
||||
<TextBlock Text="5" Foreground="White" TextAlignment="Center" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="14" FontWeight="Bold"/>
|
||||
</Canvas>
|
||||
<Canvas x:Name="TaskbarIndicator6" Canvas.Left="100" Height="10" Width="10">
|
||||
<Rectangle Fill="Blue" Height="10" Width="10" />
|
||||
<TextBlock Text="6" Foreground="White" TextAlignment="Center" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="14" FontWeight="Bold"/>
|
||||
</Canvas>
|
||||
<Canvas x:Name="TaskbarIndicator7" Canvas.Left="120" Height="10" Width="10">
|
||||
<Rectangle Fill="Blue" Height="10" Width="10" />
|
||||
<TextBlock Text="7" Foreground="White" TextAlignment="Center" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="14" FontWeight="Bold"/>
|
||||
</Canvas>
|
||||
<Canvas x:Name="TaskbarIndicator8" Canvas.Left="140" Height="10" Width="10">
|
||||
<Rectangle Fill="Blue" Height="10" Width="10" />
|
||||
<TextBlock Text="8" Foreground="White" TextAlignment="Center" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="14" FontWeight="Bold"/>
|
||||
</Canvas>
|
||||
<Canvas x:Name="TaskbarIndicator9" Canvas.Left="160" Height="10" Width="10">
|
||||
<Rectangle Fill="Blue" Height="10" Width="10" />
|
||||
<TextBlock Text="9" Foreground="White" TextAlignment="Center" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="14" FontWeight="Bold"/>
|
||||
</Canvas>
|
||||
<Canvas x:Name="TaskbarIndicator10" Canvas.Left="180" Height="10" Width="10">
|
||||
<Rectangle Fill="Blue" Height="10" Width="10" />
|
||||
<TextBlock Text="0" Foreground="White" TextAlignment="Center" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="14" FontWeight="Bold"/>
|
||||
</Canvas>
|
||||
</Canvas>
|
||||
</Grid>
|
||||
</Page>
|
||||
|
||||
@@ -7,13 +7,16 @@ using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text.Json;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
using Microsoft.UI;
|
||||
using Microsoft.UI.Windowing;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Microsoft.UI.Xaml.Media;
|
||||
using ShortcutGuide;
|
||||
using Microsoft.UI.Xaml.Media.Animation;
|
||||
using Microsoft.UI.Xaml.Shapes;
|
||||
using ShortcutGuide.Models;
|
||||
using Windows.Foundation;
|
||||
|
||||
@@ -21,6 +24,8 @@ namespace ShortcutGuide
|
||||
{
|
||||
public sealed partial class ShortcutView : Page, INotifyPropertyChanged
|
||||
{
|
||||
private readonly DispatcherTimer _taskbarUpdateTimer = new() { Interval = TimeSpan.FromMilliseconds(500) };
|
||||
private bool _showTaskbarShortcuts = true;
|
||||
private ShortcutFile shortcutList = ManifestInterpreter.GetShortcutsOfApplication(ShortcutPageParameters.CurrentPageName);
|
||||
|
||||
public ShortcutView()
|
||||
@@ -41,7 +46,7 @@ namespace ShortcutGuide
|
||||
switch (category.SectionName)
|
||||
{
|
||||
case string name when name.StartsWith("<TASKBAR1-9>", StringComparison.Ordinal):
|
||||
// Todo: Implement GetTaskbarIconPositions
|
||||
_showTaskbarShortcuts = true;
|
||||
break;
|
||||
case string name when name.StartsWith('<') && name.EndsWith('>'):
|
||||
break;
|
||||
@@ -69,6 +74,13 @@ namespace ShortcutGuide
|
||||
ShortcutPageParameters.PinnedShortcuts.Add(ShortcutPageParameters.CurrentPageName, []);
|
||||
}
|
||||
|
||||
if (_showTaskbarShortcuts)
|
||||
{
|
||||
TaskbarIndicators.Visibility = Visibility.Visible;
|
||||
_taskbarUpdateTimer.Tick += UpdateTaskbarIndicators;
|
||||
_taskbarUpdateTimer.Start();
|
||||
}
|
||||
|
||||
OpenOverview();
|
||||
}
|
||||
catch (Exception)
|
||||
@@ -79,6 +91,59 @@ namespace ShortcutGuide
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateTaskbarIndicators(object? sender, object? e)
|
||||
{
|
||||
var buttons = TasklistPositions.GetButtons();
|
||||
Canvas[] canvases = [
|
||||
TaskbarIndicator1,
|
||||
TaskbarIndicator2,
|
||||
TaskbarIndicator3,
|
||||
TaskbarIndicator4,
|
||||
TaskbarIndicator5,
|
||||
TaskbarIndicator6,
|
||||
TaskbarIndicator7,
|
||||
TaskbarIndicator8,
|
||||
TaskbarIndicator9,
|
||||
TaskbarIndicator10,
|
||||
];
|
||||
|
||||
for (int i = 0; i < canvases.Length; i++)
|
||||
{
|
||||
if (i < buttons.Length)
|
||||
{
|
||||
canvases[i].Visibility = Visibility.Visible;
|
||||
Rect workArea = DisplayHelper.GetWorkAreaForDisplayWithWindow(MainWindow.WindowHwnd);
|
||||
DoubleAnimation animation = new DoubleAnimation
|
||||
{
|
||||
To = (buttons[i].X - workArea.Left) / DpiHelper.GetDPIScaleForWindow(MainWindow.WindowHwnd.ToInt32()),
|
||||
Duration = TimeSpan.FromMilliseconds(500),
|
||||
};
|
||||
|
||||
// Create the storyboard
|
||||
Storyboard storyboard = new Storyboard();
|
||||
storyboard.Children.Add(animation);
|
||||
|
||||
// Set the target and property
|
||||
Storyboard.SetTarget(animation, canvases[i]);
|
||||
Storyboard.SetTargetProperty(animation, "(Canvas.Left)");
|
||||
|
||||
// Start the animation
|
||||
storyboard.Begin();
|
||||
|
||||
canvases[i].Width = buttons[i].Width / DpiHelper.GetDPIScaleForWindow(MainWindow.WindowHwnd.ToInt32());
|
||||
canvases[i].Height = buttons[i].Height / DpiHelper.GetDPIScaleForWindow(MainWindow.WindowHwnd.ToInt32());
|
||||
((Rectangle)canvases[i].Children[0]).Width = buttons[i].Width / DpiHelper.GetDPIScaleForWindow(MainWindow.WindowHwnd.ToInt32());
|
||||
((Rectangle)canvases[i].Children[0]).Height = buttons[i].Height / DpiHelper.GetDPIScaleForWindow(MainWindow.WindowHwnd.ToInt32());
|
||||
((TextBlock)canvases[i].Children[1]).Width = buttons[i].Width / DpiHelper.GetDPIScaleForWindow(MainWindow.WindowHwnd.ToInt32());
|
||||
((TextBlock)canvases[i].Children[1]).Height = buttons[i].Height / DpiHelper.GetDPIScaleForWindow(MainWindow.WindowHwnd.ToInt32());
|
||||
}
|
||||
else
|
||||
{
|
||||
canvases[i].Visibility = Visibility.Collapsed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void OnPropertyChanged([CallerMemberName] string? propertyName = null)
|
||||
{
|
||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
||||
|
||||
@@ -0,0 +1,188 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
using UIAutomationClient;
|
||||
|
||||
namespace ShortcutGuide
|
||||
{
|
||||
internal sealed partial class TasklistPositions
|
||||
{
|
||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
|
||||
public struct TasklistButton
|
||||
{
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
|
||||
public string Name;
|
||||
|
||||
public int X;
|
||||
|
||||
public int Y;
|
||||
|
||||
public int Width;
|
||||
|
||||
public int Height;
|
||||
|
||||
public int Keynum;
|
||||
}
|
||||
|
||||
/*
|
||||
private IUIAutomation? _automation;
|
||||
private IUIAutomationElement? _element;
|
||||
private IUIAutomationCondition? _trueCondition;
|
||||
public void Update()
|
||||
{
|
||||
|
||||
// Get HWND of the tasklist
|
||||
var tasklistHwnd = NativeMethods.FindWindowA("Shell_TrayWnd", null);
|
||||
if (tasklistHwnd == IntPtr.Zero)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
tasklistHwnd = NativeMethods.FindWindowExA(tasklistHwnd, IntPtr.Zero, "ReBarWindow32", string.Empty);
|
||||
if (tasklistHwnd == IntPtr.Zero)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
tasklistHwnd = NativeMethods.FindWindowExA(tasklistHwnd, IntPtr.Zero, "MSTaskSwWClass", string.Empty);
|
||||
if (tasklistHwnd == IntPtr.Zero)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
tasklistHwnd = NativeMethods.FindWindowExA(tasklistHwnd, IntPtr.Zero, "MSTaskListWClass", string.Empty);
|
||||
if (tasklistHwnd == IntPtr.Zero)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (_automation == null)
|
||||
{
|
||||
_automation = new CUIAutomation();
|
||||
_trueCondition = _automation.CreateTrueCondition();
|
||||
}
|
||||
|
||||
_element = null;
|
||||
_element = _automation.ElementFromHandle(tasklistHwnd);
|
||||
}
|
||||
|
||||
public bool UpdateButtons(List<TasklistButton> buttons)
|
||||
{
|
||||
if (_automation == null || _element == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
IUIAutomationElementArray elements = _element.FindAll(TreeScope.TreeScope_Children, _trueCondition);
|
||||
if (elements == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
int count = elements.Length;
|
||||
var foundButtons = new List<TasklistButton>(count);
|
||||
|
||||
for (int i = 0; i < count; ++i)
|
||||
{
|
||||
var child = elements.GetElement(i);
|
||||
var button = default(TasklistButton);
|
||||
|
||||
object rectObj = child.GetCurrentPropertyValue(30001);
|
||||
if (rectObj is double[] arr && arr.Length == 4)
|
||||
{
|
||||
button.X = (long)arr[0];
|
||||
button.Y = (long)arr[1];
|
||||
button.Width = (long)arr[2];
|
||||
button.Height = (long)arr[3];
|
||||
}
|
||||
else if (rectObj is Windows.Foundation.Rect wrect)
|
||||
{
|
||||
button.X = (long)wrect.X;
|
||||
button.Y = (long)wrect.Y;
|
||||
button.Width = (long)wrect.Width;
|
||||
button.Height = (long)wrect.Height;
|
||||
}
|
||||
else
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine($"rectObj type: {rectObj?.GetType()} value: {rectObj}");
|
||||
continue; // Don't return false, just skip
|
||||
}
|
||||
|
||||
object nameObj = child.GetCurrentPropertyValue(30011);
|
||||
button.Name = nameObj as string ?? string.Empty;
|
||||
|
||||
foundButtons.Add(button);
|
||||
}
|
||||
|
||||
// assign keynums
|
||||
buttons.Clear();
|
||||
foreach (var button in foundButtons)
|
||||
{
|
||||
if (buttons.Count == 0)
|
||||
{
|
||||
var b = button;
|
||||
b.KeyNumber = 1;
|
||||
buttons.Add(b);
|
||||
}
|
||||
else
|
||||
{
|
||||
var last = buttons[^1];
|
||||
if (button.X < last.X || button.Y < last.Y)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (button.Name == last.Name)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var b = button;
|
||||
b.KeyNumber = last.KeyNumber + 1;
|
||||
buttons.Add(b);
|
||||
if (b.KeyNumber == 10)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}*/
|
||||
|
||||
[DllImport("ShortcutGuide.CPPProject.dll", EntryPoint = "get_buttons")]
|
||||
public static extern IntPtr GetTasklistButtons(nint monitor, out int size);
|
||||
|
||||
[LibraryImport("User32.dll")]
|
||||
private static partial IntPtr MonitorFromWindow(nint hwnd, int dwFlags);
|
||||
|
||||
public static TasklistButton[] GetButtons()
|
||||
{
|
||||
var monitor = MonitorFromWindow(MainWindow.WindowHwnd, 0);
|
||||
IntPtr ptr = GetTasklistButtons(monitor, out int size);
|
||||
if (ptr == IntPtr.Zero)
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
if (size <= 0)
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
TasklistButton[] buttons = new TasklistButton[size];
|
||||
IntPtr currentPtr = ptr;
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
buttons[i] = Marshal.PtrToStructure<TasklistButton>(currentPtr);
|
||||
currentPtr += Marshal.SizeOf<TasklistButton>();
|
||||
}
|
||||
|
||||
return buttons;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user