tasklist_positions.cpp
1 #include "pch.h" 2 #include "tasklist_positions.h" 3 4 void Tasklist::update() 5 { 6 // Get HWND of the tasklist 7 auto tasklist_hwnd = FindWindowA("Shell_TrayWnd", nullptr); 8 if (!tasklist_hwnd) 9 return; 10 tasklist_hwnd = FindWindowExA(tasklist_hwnd, 0, "ReBarWindow32", nullptr); 11 if (!tasklist_hwnd) 12 return; 13 tasklist_hwnd = FindWindowExA(tasklist_hwnd, 0, "MSTaskSwWClass", nullptr); 14 if (!tasklist_hwnd) 15 return; 16 tasklist_hwnd = FindWindowExA(tasklist_hwnd, 0, "MSTaskListWClass", nullptr); 17 if (!tasklist_hwnd) 18 return; 19 if (!automation) 20 { 21 winrt::check_hresult(CoCreateInstance(CLSID_CUIAutomation, 22 nullptr, 23 CLSCTX_INPROC_SERVER, 24 IID_IUIAutomation, 25 automation.put_void())); 26 winrt::check_hresult(automation->CreateTrueCondition(true_condition.put())); 27 } 28 element = nullptr; 29 winrt::check_hresult(automation->ElementFromHandle(tasklist_hwnd, element.put())); 30 } 31 32 bool Tasklist::update_buttons(std::vector<TasklistButton>& buttons) 33 { 34 if (!automation || !element) 35 { 36 return false; 37 } 38 winrt::com_ptr<IUIAutomationElementArray> elements; 39 if (element->FindAll(TreeScope_Children, true_condition.get(), elements.put()) < 0) 40 return false; 41 if (!elements) 42 return false; 43 int count; 44 if (elements->get_Length(&count) < 0) 45 return false; 46 winrt::com_ptr<IUIAutomationElement> child; 47 std::vector<TasklistButton> found_buttons; 48 found_buttons.reserve(count); 49 for (int i = 0; i < count; ++i) 50 { 51 child = nullptr; 52 if (elements->GetElement(i, child.put()) < 0) 53 return false; 54 TasklistButton button; 55 if (VARIANT var_rect; child->GetCurrentPropertyValue(UIA_BoundingRectanglePropertyId, &var_rect) >= 0) 56 { 57 if (var_rect.vt == (VT_R8 | VT_ARRAY)) 58 { 59 LONG pos; 60 double value; 61 pos = 0; 62 SafeArrayGetElement(var_rect.parray, &pos, &value); 63 button.x = static_cast<long>(value); 64 pos = 1; 65 SafeArrayGetElement(var_rect.parray, &pos, &value); 66 button.y = static_cast<long>(value); 67 pos = 2; 68 SafeArrayGetElement(var_rect.parray, &pos, &value); 69 button.width = static_cast<long>(value); 70 pos = 3; 71 SafeArrayGetElement(var_rect.parray, &pos, &value); 72 button.height = static_cast<long>(value); 73 } 74 VariantClear(&var_rect); 75 } 76 else 77 { 78 return false; 79 } 80 if (BSTR automation_id; child->get_CurrentAutomationId(&automation_id) >= 0) 81 { 82 button.name = automation_id; 83 SysFreeString(automation_id); 84 } 85 found_buttons.push_back(button); 86 } 87 // assign keynums 88 buttons.clear(); 89 for (auto& button : found_buttons) 90 { 91 if (buttons.empty()) 92 { 93 button.keynum = 1; 94 buttons.push_back(std::move(button)); 95 } 96 else 97 { 98 if (button.x < buttons.back().x || button.y < buttons.back().y) // skip 2nd row 99 break; 100 if (button.name == buttons.back().name) 101 continue; // skip buttons from the same app 102 button.keynum = buttons.back().keynum + 1; 103 buttons.push_back(std::move(button)); 104 if (buttons.back().keynum == 10) 105 break; // no more than 10 buttons 106 } 107 } 108 return true; 109 } 110 111 std::vector<TasklistButton> Tasklist::get_buttons() 112 { 113 std::vector<TasklistButton> buttons; 114 update_buttons(buttons); 115 return buttons; 116 }