diff --git a/enc_temp_folder/1833592448cd2768ab9e3cba28aa33/MainWindow.xaml.cpp b/enc_temp_folder/1833592448cd2768ab9e3cba28aa33/MainWindow.xaml.cpp deleted file mode 100644 index 9c7206b..0000000 --- a/enc_temp_folder/1833592448cd2768ab9e3cba28aa33/MainWindow.xaml.cpp +++ /dev/null @@ -1,79 +0,0 @@ -#include "pch.h" -#include "MainWindow.xaml.h" -#if __has_include("MainWindow.g.cpp") -#include "MainWindow.g.cpp" -#endif - -using namespace winrt; -using namespace Microsoft::UI::Xaml; - -// To learn more about WinUI, the WinUI project structure, -// and more about our project templates, see: http://aka.ms/winui-project-info. - -namespace winrt::vertical_tasks::implementation -{ - MainWindow::MainWindow() - { - InitializeComponent(); - } - - int32_t MainWindow::MyProperty() - { - throw hresult_not_implemented(); - } - - void MainWindow::MyProperty(int32_t /* value */) - { - throw hresult_not_implemented(); - } - struct WinData - { - HWND hwnd; - std::wstring title; - - }; - - std::vector g_windows; - - BOOL CALLBACK WindowEnumerationCallBack(HWND hwnd, LPARAM /*lParam*/) - { - if (IsWindow(hwnd) && IsWindowVisible(hwnd) && (0 == GetWindow(hwnd, GW_OWNER))) - { - std::wstring title; - const auto size = GetWindowTextLength(hwnd); - if (size > 0) - { - - std::vector buffer(size + 1); - GetWindowText(hwnd, buffer.data(), size + 1); - - g_windows.emplace_back(WinData{ hwnd, std::wstring(std::begin(buffer), std::end(buffer)) }); - } - } - // keep on looping - return true; - } - - void MainWindow::myButton_Click(IInspectable const&, RoutedEventArgs const&) - { - myButton().Content(box_value(L"Clicked")); - EnumWindows(&WindowEnumerationCallBack, 0); - std::vector newTitles; - newTitles.reserve(g_windows.size()); - - for (auto&& winData : g_windows) - { - if (!winData.title.empty()) - { - newTitles.emplace_back(winrt::box_value(winData.title)); - } - } - m_windowTitles.ReplaceAll(newTitles); - } - - Windows::Foundation::Collections::IObservableVector MainWindow::WindowTitles() - { - return m_windowTitles; - } - -} diff --git a/enc_temp_folder/afd2ce2136732e5a1fb517b019afd650/MainWindow.xaml.cpp b/enc_temp_folder/afd2ce2136732e5a1fb517b019afd650/MainWindow.xaml.cpp deleted file mode 100644 index 31e5eb9..0000000 --- a/enc_temp_folder/afd2ce2136732e5a1fb517b019afd650/MainWindow.xaml.cpp +++ /dev/null @@ -1,75 +0,0 @@ -#include "pch.h" -#include "MainWindow.xaml.h" -#if __has_include("MainWindow.g.cpp") -#include "MainWindow.g.cpp" -#endif - -using namespace winrt; -using namespace Microsoft::UI::Xaml; - -// To learn more about WinUI, the WinUI project structure, -// and more about our project templates, see: http://aka.ms/winui-project-info. - -namespace winrt::vertical_tasks::implementation -{ - MainWindow::MainWindow() - { - InitializeComponent(); - } - - int32_t MainWindow::MyProperty() - { - throw hresult_not_implemented(); - } - - void MainWindow::MyProperty(int32_t /* value */) - { - throw hresult_not_implemented(); - } - struct WinData - { - HWND hwnd; - std::wstring title; - - }; - - std::vector g_windows; - - BOOL CALLBACK WindowEnumerationCallBack(HWND hwnd, LPARAM /*lParam*/) - { - std::wstring title; - const auto size = GetWindowTextLength(hwnd); - if (size > 0) - { - std::vector buffer(size+1); - GetWindowText(hwnd, buffer.data(), size+1); - - g_windows.emplace_back(WinData{ hwnd, std::wstring(std::begin(buffer), std::end(buffer)) }); - } - // keep on looping - return true; - } - - void MainWindow::myButton_Click(IInspectable const&, RoutedEventArgs const&) - { - myButton().Content(box_value(L"Clicked")); - EnumWindows(&WindowEnumerationCallBack, 0); - std::vector newTitles; - newTitles.reserve(g_windows.size()); - - for (auto&& winData : g_windows) - { - if (!winData.title.empty()) - { - newTitles.emplace_back(winrt::box_value(winData.title)); - } - } - m_windowTitles.ReplaceAll(newTitles); - } - - Windows::Foundation::Collections::IObservableVector MainWindow::WindowTitles() - { - return m_windowTitles; - } - -} diff --git a/enc_temp_folder/c3545e6cd3c76d8eb39ef886a3f8ca/MainWindow.xaml.cpp b/enc_temp_folder/c3545e6cd3c76d8eb39ef886a3f8ca/MainWindow.xaml.cpp deleted file mode 100644 index e227cd7..0000000 --- a/enc_temp_folder/c3545e6cd3c76d8eb39ef886a3f8ca/MainWindow.xaml.cpp +++ /dev/null @@ -1,75 +0,0 @@ -#include "pch.h" -#include "MainWindow.xaml.h" -#if __has_include("MainWindow.g.cpp") -#include "MainWindow.g.cpp" -#endif - -using namespace winrt; -using namespace Microsoft::UI::Xaml; - -// To learn more about WinUI, the WinUI project structure, -// and more about our project templates, see: http://aka.ms/winui-project-info. - -namespace winrt::vertical_tasks::implementation -{ - MainWindow::MainWindow() - { - InitializeComponent(); - } - - int32_t MainWindow::MyProperty() - { - throw hresult_not_implemented(); - } - - void MainWindow::MyProperty(int32_t /* value */) - { - throw hresult_not_implemented(); - } - struct WinData - { - HWND hwnd; - std::wstring title; - - }; - - std::vector g_windows; - - BOOL CALLBACK WindowEnumerationCallBack(HWND hwnd, LPARAM /*lParam*/) - { - std::wstring title; - const auto size = GetWindowTextLength(hwnd); - if (size > 0) - { - std::vector buffer(size+1); - GetWindowText(hwnd, buffer.data(), size); - - g_windows.emplace_back(WinData{ hwnd, std::wstring(std::begin(buffer), std::end(buffer)) }); - } - // keep on looping - return true; - } - - void MainWindow::myButton_Click(IInspectable const&, RoutedEventArgs const&) - { - myButton().Content(box_value(L"Clicked")); - EnumWindows(&WindowEnumerationCallBack, 0); - std::vector newTitles; - newTitles.reserve(g_windows.size()); - - for (auto&& winData : g_windows) - { - if (!winData.title.empty()) - { - newTitles.emplace_back(winrt::box_value(winData.title)); - } - } - m_windowTitles.ReplaceAll(newTitles); - } - - Windows::Foundation::Collections::IObservableVector MainWindow::WindowTitles() - { - return m_windowTitles; - } - -} diff --git a/vertical_tasks/App.xaml.cpp b/vertical_tasks/App.xaml.cpp index 12181f9..83101a3 100644 --- a/vertical_tasks/App.xaml.cpp +++ b/vertical_tasks/App.xaml.cpp @@ -2,45 +2,50 @@ #include "App.xaml.h" #include "MainWindow.xaml.h" +#include -using namespace winrt; -using namespace Windows::Foundation; -using namespace Microsoft::UI::Xaml; -using namespace Microsoft::UI::Xaml::Controls; -using namespace Microsoft::UI::Xaml::Navigation; -using namespace vertical_tasks; -using namespace vertical_tasks::implementation; - -// To learn more about WinUI, the WinUI project structure, -// and more about our project templates, see: http://aka.ms/winui-project-info. +namespace winrt +{ + using namespace Windows::Foundation; + using namespace Microsoft::UI::Xaml; + using namespace Microsoft::UI::Xaml::Controls; + using namespace Microsoft::UI::Xaml::Navigation; + using namespace vertical_tasks; +} -/// -/// Initializes the singleton application object. This is the first line of authored code -/// executed, and as such is the logical equivalent of main() or WinMain(). -/// -App::App() +namespace winrt::vertical_tasks::implementation { - InitializeComponent(); + // To learn more about WinUI, the WinUI project structure, + // and more about our project templates, see: http://aka.ms/winui-project-info. -#if defined _DEBUG && !defined DISABLE_XAML_GENERATED_BREAK_ON_UNHANDLED_EXCEPTION - UnhandledException([this](IInspectable const&, UnhandledExceptionEventArgs const& e) + /// + /// Initializes the singleton application object. This is the first line of authored code + /// executed, and as such is the logical equivalent of main() or WinMain(). + /// + App::App() { - if (IsDebuggerPresent()) - { - auto errorMessage = e.Message(); - __debugbreak(); - } - }); + InitializeComponent(); + +#if defined _DEBUG && !defined DISABLE_XAML_GENERATED_BREAK_ON_UNHANDLED_EXCEPTION + UnhandledException([this](winrt::IInspectable const&, winrt::UnhandledExceptionEventArgs const& e) + { + if (IsDebuggerPresent()) + { + auto errorMessage = e.Message(); + __debugbreak(); + } + }); #endif -} + } -/// -/// Invoked when the application is launched normally by the end user. Other entry points -/// will be used such as when the application is launched to open a specific file. -/// -/// Details about the launch request and process. -void App::OnLaunched(LaunchActivatedEventArgs const&) -{ - window = make(); - window.Activate(); + /// + /// Invoked when the application is launched normally by the end user. Other entry points + /// will be used such as when the application is launched to open a specific file. + /// + /// Details about the launch request and process. + void App::OnLaunched(winrt::LaunchActivatedEventArgs const&) + { + window = winrt::make(); + window.Activate(); + } } \ No newline at end of file diff --git a/vertical_tasks/MainWindow.idl b/vertical_tasks/MainWindow.idl index 7ce84ab..d384da3 100644 --- a/vertical_tasks/MainWindow.idl +++ b/vertical_tasks/MainWindow.idl @@ -1,10 +1,21 @@ namespace vertical_tasks { + [default_interface] + runtimeclass TaskVM : Windows.UI.Xaml.Data.INotifyPropertyChanged + { + TaskVM(UInt64 hwnd); + String Title{ get; }; + Microsoft.UI.Xaml.Controls.IconSource IconSource{ get; }; + + void Select(); + void Close(); + + } + [default_interface] runtimeclass MainWindow : Microsoft.UI.Xaml.Window { MainWindow(); - Int32 MyProperty; - Windows.Foundation.Collections.IObservableVector WindowTitles{ get; }; + Windows.Foundation.Collections.IObservableVector Tasks{ get; }; } } diff --git a/vertical_tasks/MainWindow.xaml b/vertical_tasks/MainWindow.xaml index 56a13a6..4125db2 100644 --- a/vertical_tasks/MainWindow.xaml +++ b/vertical_tasks/MainWindow.xaml @@ -9,6 +9,60 @@ - + + + + + + + + + + + + + + + + + + + + + diff --git a/vertical_tasks/MainWindow.xaml.cpp b/vertical_tasks/MainWindow.xaml.cpp index c0bafc2..022e996 100644 --- a/vertical_tasks/MainWindow.xaml.cpp +++ b/vertical_tasks/MainWindow.xaml.cpp @@ -4,9 +4,21 @@ #include "MainWindow.g.cpp" #endif -using namespace winrt; -using namespace Microsoft::UI::Xaml; +#include +#include +#include +#include + +#include "ShellHookMessages.h" + +#include + +#include +namespace winrt +{ + using namespace Microsoft::UI::Xaml; +} // To learn more about WinUI, the WinUI project structure, // and more about our project templates, see: http://aka.ms/winui-project-info. @@ -17,64 +29,214 @@ namespace winrt::vertical_tasks::implementation InitializeComponent(); } - int32_t MainWindow::MyProperty() + UINT g_shellHookMsgId{ UINT_MAX }; + bool g_initialized{ false }; + + // returns true if window already existed + winrt::vertical_tasks::TaskVM MainWindow::AddOrUpdateWindow(HWND hwnd, bool shouldUpdate) { - throw hresult_not_implemented(); + if (IsWindow(hwnd) && IsWindowVisible(hwnd) && (0 == GetWindow(hwnd, GW_OWNER))) + { + auto found= m_tasks->find(hwnd); + + if (found != m_tasks->end()) + { + // todo call recalculate + return found->as(); + } + else + { + winrt::vertical_tasks::TaskVM newItem(reinterpret_cast(hwnd)); + if (shouldUpdate) + { + m_tasks->Append(newItem); + } + else + { + // don't update, add to the internal + m_tasks->get_container().push_back(newItem); + } + return newItem; + } + } + return nullptr; } - void MainWindow::MyProperty(int32_t /* value */) + BOOL CALLBACK WindowEnumerationCallBack(HWND hwnd, LPARAM lParam) { - throw hresult_not_implemented(); + auto thisRef = reinterpret_cast(lParam); + + thisRef->AddOrUpdateWindow(hwnd); + // keep on looping + return true; } - struct WinData + + winrt::fire_and_forget MainWindow::FetchIcon(HWND hwnd) { - HWND hwnd; - std::wstring title; + co_await winrt::resume_background(); + + HICON icon; + SendMessageTimeout(hwnd, WM_GETICON, ICON_SMALL2, 0, SMTO_BLOCK | SMTO_ABORTIFHUNG, + 500/*ms*/, reinterpret_cast(&icon)); + if (!icon) + { + SendMessageTimeout(hwnd, WM_GETICON, ICON_SMALL, 0, SMTO_BLOCK | SMTO_ABORTIFHUNG, + 500/*ms*/, reinterpret_cast(&icon)); + } + wil::unique_hicon iconCopy(CopyIcon(icon)); - }; + co_await wil::resume_foreground(DispatcherQueue()); + auto found = m_tasks->find(hwnd); - std::vector g_windows; + if (found != m_tasks->end()) + { + //found->second.icon = std::move(iconCopy); + } + // TODO update icon in ViewModel + } - BOOL CALLBACK WindowEnumerationCallBack(HWND hwnd, LPARAM /*lParam*/) + //int i = 0; + void MainWindow::myButton_Click(IInspectable const&, RoutedEventArgs const&) { - if (IsWindow(hwnd) && IsWindowVisible(hwnd) && (0 == GetWindow(hwnd, GW_OWNER))) + if (!g_initialized) { - std::wstring title; - const auto size = GetWindowTextLength(hwnd); - if (size > 0) - { + myButton().Content(box_value(L"Clicked")); + EnumWindows(&WindowEnumerationCallBack, reinterpret_cast(this)); + + m_tasks->do_call_changed(winrt::Windows::Foundation::Collections::CollectionChange::Reset, 0u); - std::vector buffer(size + 1); - GetWindowText(hwnd, buffer.data(), size + 1); - g_windows.emplace_back(WinData{ hwnd, std::wstring(std::begin(buffer), std::end(buffer)) }); - } + static ShellHookMessages s_myMessages; + s_myMessages.Register([weak_this = get_weak()](WPARAM wParam, LPARAM lParam) + { + auto strong_this = weak_this.get(); + { + strong_this->OnShellMessage(wParam, lParam); + } + }); + g_initialized = true; + } + else + { + /*g_windows[i].ShowWindow(); + i++;*/ } - // keep on looping - return true; } - void MainWindow::myButton_Click(IInspectable const&, RoutedEventArgs const&) + winrt::fire_and_forget MainWindow::OnItemClick(Windows::Foundation::IInspectable const& /*sender*/, Microsoft::UI::Xaml::Controls::ItemClickEventArgs const& /*args*/) { - myButton().Content(box_value(L"Clicked")); - g_windows.clear(); - EnumWindows(&WindowEnumerationCallBack, 0); - std::vector newTitles; - newTitles.reserve(g_windows.size()); + + co_return; + } + + winrt::fire_and_forget MainWindow::OnSelectionChanged(Windows::Foundation::IInspectable const& /*sender*/, Microsoft::UI::Xaml::Controls::SelectionChangedEventArgs const& /*args*/) + { + if (selectionFromShell) + { + // seleciton change from shell + co_return; + } - for (auto&& winData : g_windows) + std::vector windowsToShow; { - if (!winData.title.empty()) + auto scope = selectionFromClick.onInScope(); + + auto selection = myList().SelectedItems(); + for (auto&& item : selection) + { + auto& taskVM = item.as(); + // select window + windowsToShow.emplace_back(taskVM->Hwnd()); + } + } + co_await winrt::resume_background(); + for (auto&& hwnd : windowsToShow) + { + SetForegroundWindow(hwnd); + + if (!ShowWindow(hwnd, SW_RESTORE)) { - newTitles.emplace_back(winrt::box_value(winData.title)); + // ShowWindow doesn't work if the process is running elevated: fallback to SendMessage + SendMessage(hwnd, WM_SYSCOMMAND, SC_RESTORE, 0); } } - m_windowTitles.ReplaceAll(newTitles); } - Windows::Foundation::Collections::IObservableVector MainWindow::WindowTitles() + + void MainWindow::SelectItem(HWND hwnd) + { + if (selectionFromClick) + { + // we caused the selection, so ignore it. + return; + } + auto scope = selectionFromShell.onInScope(); + auto found = m_tasks->find(hwnd); + + if (found != m_tasks->end()) + { + myList().SelectedItem(*found); + } + else + { + LOG_HR(E_ACCESSDENIED); + } + } + + void MainWindow::DeleteItem(HWND hwnd) + { + auto found = m_tasks->find(hwnd); + + if (found != m_tasks->end()) + { + const auto indexToErase{ std::distance(m_tasks->begin(), found) }; + m_tasks->get_container().erase(found); + m_tasks->do_call_changed(Windows::Foundation::Collections::CollectionChange::ItemRemoved, indexToErase); + + } + else + { + LOG_HR(E_ACCESSDENIED); + } + } + + winrt::fire_and_forget MainWindow::OnShellMessage(WPARAM wParam, LPARAM lParam) { - return m_windowTitles; + co_await wil::resume_foreground(DispatcherQueue()); + std::wstringstream myString; + myString << L"shell message: " << std::hex << wParam << L", " << lParam; + switch (wParam) + { + case HSHELL_WINDOWACTIVATED: + case HSHELL_RUDEAPPACTIVATED: + { + SelectItem(reinterpret_cast(lParam)); + } + break; + case HSHELL_WINDOWCREATED: + { + // add the window + auto&& added = AddOrUpdateWindow(reinterpret_cast(lParam), true /*send change update*/); + if (added) + { + SelectItem(reinterpret_cast(lParam)); + } + } + break; + case HSHELL_WINDOWDESTROYED: + { + DeleteItem(reinterpret_cast(lParam)); + } + break; + default: + { + myString << L" ! UNKNOWN"; + } + break; + } + myString << std::endl; + OutputDebugString(myString.str().c_str()); + } } diff --git a/vertical_tasks/MainWindow.xaml.h b/vertical_tasks/MainWindow.xaml.h index 3646332..005f092 100644 --- a/vertical_tasks/MainWindow.xaml.h +++ b/vertical_tasks/MainWindow.xaml.h @@ -1,20 +1,91 @@ #pragma once #include "MainWindow.g.h" +#include "TaskVM.h" namespace winrt::vertical_tasks::implementation { + using namespace Windows::Foundation::Collections; + + struct MyTasks : public implements, IVector, IVectorView, IIterable>, + winrt::observable_vector_base + { + auto& get_container() const noexcept + { + return m_values; + } + + auto& get_container() noexcept + { + return m_values; + } + + auto begin() + { + return get_container().begin(); + + } + auto end() + { + return get_container().end(); + } + + auto find(HWND hwnd) + { + return std::find_if(begin(), end(), [hwnd](IInspectable& other) + { + return hwnd == other.as()->Hwnd(); + }); + } + + void do_call_changed(Windows::Foundation::Collections::CollectionChange const change, uint32_t const index) + { + call_changed(change, index); + } + private: + std::vector m_values{ }; + }; + struct MainWindow : MainWindowT { MainWindow(); - int32_t MyProperty(); - void MyProperty(int32_t value); void myButton_Click(Windows::Foundation::IInspectable const& sender, Microsoft::UI::Xaml::RoutedEventArgs const& args); - Windows::Foundation::Collections::IObservableVector WindowTitles(); + winrt::fire_and_forget OnItemClick(Windows::Foundation::IInspectable const& sender, Microsoft::UI::Xaml::Controls::ItemClickEventArgs const& args); + winrt::fire_and_forget OnSelectionChanged(Windows::Foundation::IInspectable const& sender, Microsoft::UI::Xaml::Controls::SelectionChangedEventArgs const& args); + + IObservableVector Tasks() { return m_tasks.as< winrt::Windows::Foundation::Collections::IObservableVector>(); }; + + winrt::vertical_tasks::TaskVM AddOrUpdateWindow(HWND hwnd, bool shouldUpdate = false); + void SelectItem(HWND hwnd); + void DeleteItem(HWND hwnd); private: - Windows::Foundation::Collections::IObservableVector m_windowTitles{winrt::single_threaded_observable_vector()}; + winrt::fire_and_forget OnShellMessage(WPARAM wParam, LPARAM lParam); + winrt::fire_and_forget FetchIcon(HWND hwnd); + + winrt::com_ptr m_tasks{ winrt::make_self() }; + + struct scope_toggle + { + operator bool() + { + return toggle; + } + auto onInScope() + { + toggle = true; + return wil::scope_exit([this]() { + toggle = false; }); + } + private: + bool toggle{ false }; + + }; + + scope_toggle selectionFromShell; + scope_toggle selectionFromClick; + }; } diff --git a/vertical_tasks/ShellHookMessages.h b/vertical_tasks/ShellHookMessages.h new file mode 100644 index 0000000..e7a64c8 --- /dev/null +++ b/vertical_tasks/ShellHookMessages.h @@ -0,0 +1,103 @@ +#include +#include +#include +#include +#include + +const wchar_t* c_wzShellHookMessage = L"SHELLHOOK"; + +// retrieve the HINSTANCE for the current DLL or EXE using this symbol that +// the linker provides for every module, avoids the need for a global HINSTANCE variable +// and provides access to this value for static libraries +EXTERN_C IMAGE_DOS_HEADER __ImageBase; +__inline HINSTANCE GetModuleHINSTANCE() { return (HINSTANCE)&__ImageBase; } + +struct ShellHookMessages : std::enable_shared_from_this +{ + wil::unique_hwnd m_hwnd{}; + DWORD threadId{}; + UINT shellHookMsgId{}; + std::function callback; + + static LRESULT WINAPI StaticWndProc(HWND hwnd, UINT msgId, WPARAM wParam, LPARAM lParam) + { + ShellHookMessages* thisRef{ nullptr }; + if (msgId == WM_NCCREATE) + { + auto lpcs = reinterpret_cast(lParam); + thisRef = static_cast(lpcs->lpCreateParams); + SetWindowLongPtr(hwnd, GWLP_USERDATA, reinterpret_cast(thisRef)); + } + else + { + thisRef = reinterpret_cast(GetWindowLongPtr(hwnd, GWLP_USERDATA)); + } + if (thisRef) + { + return thisRef->WndProc(hwnd, msgId, wParam, lParam); + } + return DefWindowProc(hwnd, msgId, wParam, lParam); + } + + ShellHookMessages() + { + WNDCLASSEX wc = { 0 }; + wc.lpfnWndProc = ShellHookMessages::StaticWndProc; + wc.cbSize = sizeof(wc); + wc.style = CS_DBLCLKS | CS_NOCLOSE; + wc.cbWndExtra = sizeof(ShellHookMessages*); + wc.hCursor = LoadCursor(NULL, IDC_ARROW); + wc.lpszClassName = L"ShellHookMessages"; + wc.hInstance = GetModuleHINSTANCE(); + THROW_LAST_ERROR_IF(RegisterClassEx(&wc) == 0); + + // Create the window. + // Pass "this" param so we can use derived class implementation later. + m_hwnd.reset(CreateWindowEx( + 0, // dwExStyle + L"ShellHookMessages", // lpClassName + L"ShellHookMessages", // lpClassName + 0, // dwStyle + 0, 0, 0, 0, // x, y, width, height + HWND_MESSAGE, // parent + nullptr, // hMenu + GetModuleHINSTANCE(), //hInstance + this // lParam + )); + THROW_LAST_ERROR_IF_NULL(m_hwnd); + } + + LRESULT WndProc(HWND hwnd, UINT msgId, WPARAM wParam, LPARAM lParam) + { + switch (msgId) + { + case WM_CREATE: + { + shellHookMsgId = RegisterWindowMessage(c_wzShellHookMessage); + RegisterShellHookWindow(hwnd); + return 0; + break; + } + case WM_DESTROY: + { + DeregisterShellHookWindow(hwnd); + + return 0; + break; + } + default: + if (msgId == shellHookMsgId) + { + callback(wParam, lParam); + } + break; + } + + return -1; + } + + void Register(std::function&& toRegister) + { + callback = toRegister; + } +}; \ No newline at end of file diff --git a/vertical_tasks/TaskVM.cpp b/vertical_tasks/TaskVM.cpp new file mode 100644 index 0000000..ce0c8dc --- /dev/null +++ b/vertical_tasks/TaskVM.cpp @@ -0,0 +1,17 @@ +#include "pch.h" +#include "TaskVM.h" +#include "TaskVM.g.cpp" + + +namespace winrt::vertical_tasks::implementation +{ + + void TaskVM::Select() + { + throw hresult_not_implemented(); + } + void TaskVM::Close() + { + throw hresult_not_implemented(); + } +} diff --git a/vertical_tasks/TaskVM.h b/vertical_tasks/TaskVM.h new file mode 100644 index 0000000..a6bf6fe --- /dev/null +++ b/vertical_tasks/TaskVM.h @@ -0,0 +1,69 @@ +#pragma once +#include + +#include "TaskVM.g.h" + + +namespace winrt::vertical_tasks::implementation +{ + struct TaskVM : TaskVMT + { + TaskVM() = default; + + TaskVM(uint64_t hwnd): m_hwnd(reinterpret_cast(hwnd)) + { + const auto size = GetWindowTextLength(m_hwnd); + if (size > 0) + { + std::vector buffer(size + 1); + GetWindowText(m_hwnd, buffer.data(), size + 1); + + m_title = std::wstring_view(buffer.data(), buffer.size()); + } + else + { + LOG_HR(E_INVALIDARG); + } + } + + hstring Title() + { + return m_title; + }; + + winrt::Microsoft::UI::Xaml::Controls::IconSource IconSource() + { + return m_iconSource; + }; + + void Select(); + void Close(); + + winrt::event_token PropertyChanged(winrt::Windows::UI::Xaml::Data::PropertyChangedEventHandler const& handler) + { + return m_propertyChanged.add(handler); + }; + void PropertyChanged(winrt::event_token const& token) noexcept + { + m_propertyChanged.remove(token); + }; + + HWND Hwnd() + { + return m_hwnd; + } + private: + HWND m_hwnd; + winrt::hstring m_title; + wil::unique_hicon m_icon; + winrt::Microsoft::UI::Xaml::Controls::IconSource m_iconSource{nullptr}; + winrt::event m_propertyChanged; + + }; +} +namespace winrt::vertical_tasks::factory_implementation +{ + struct TaskVM : TaskVMT + { + }; +} diff --git a/vertical_tasks/pch.h b/vertical_tasks/pch.h index 87057b1..905d67a 100644 --- a/vertical_tasks/pch.h +++ b/vertical_tasks/pch.h @@ -6,8 +6,9 @@ #include #include #include - - +#include +#include +#include // Undefine GetCurrentTime macro to prevent // conflict with Storyboard::GetCurrentTime #undef GetCurrentTime diff --git a/vertical_tasks/vertical_tasks.vcxproj b/vertical_tasks/vertical_tasks.vcxproj index 08a254b..4f75fc1 100644 --- a/vertical_tasks/vertical_tasks.vcxproj +++ b/vertical_tasks/vertical_tasks.vcxproj @@ -109,6 +109,8 @@ MainWindow.xaml + + @@ -125,6 +127,7 @@ MainWindow.xaml + diff --git a/vertical_tasks/vertical_tasks.vcxproj.filters b/vertical_tasks/vertical_tasks.vcxproj.filters index c60a1c5..689e8b7 100644 --- a/vertical_tasks/vertical_tasks.vcxproj.filters +++ b/vertical_tasks/vertical_tasks.vcxproj.filters @@ -13,9 +13,12 @@ + + +