From 896784665788ac927ad57b4ced2638530ec520d4 Mon Sep 17 00:00:00 2001 From: Asuro Date: Wed, 10 Aug 2022 14:17:50 +0200 Subject: [PATCH] Separate windows shell interaction into it's own file --- AsuroTool/AsuroTool.cpp | 100 +++------------------------ AsuroTool/AsuroTool.h | 2 - AsuroTool/AsuroTool.rc | 2 +- AsuroTool/AsuroTool.vcxproj | 6 ++ AsuroTool/AsuroTool.vcxproj.filters | 6 ++ AsuroTool/WindowsShell.cpp | 102 ++++++++++++++++++++++++++++ AsuroTool/WindowsShell.h | 8 +++ 7 files changed, 131 insertions(+), 95 deletions(-) create mode 100644 AsuroTool/WindowsShell.cpp create mode 100644 AsuroTool/WindowsShell.h diff --git a/AsuroTool/AsuroTool.cpp b/AsuroTool/AsuroTool.cpp index 25f72f8..0a8c08d 100644 --- a/AsuroTool/AsuroTool.cpp +++ b/AsuroTool/AsuroTool.cpp @@ -8,25 +8,18 @@ #pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"") #pragma comment(lib, "comctl32.lib") -#include +#include "Util.h" +#include "AudioApi.h" +#include "Settings.h" +#include "AsuroTool.h" +#include "WindowsShell.h" #include #include #include #include -#include -#include -#include - -#include "Util.h" -#include "AudioApi.h" -#include "Settings.h" -#include "resource.h" -#include "AsuroTool.h" const size_t MAX_FONT_PATH_LENGTH = 2048; -const UINT TRAY_ID = 420; -const UINT WMAPP_NOTIFYCALLBACK = WM_APP + 1; // Globals for use in callbacks DrawData* gDrawData; @@ -80,59 +73,9 @@ void init(DrawData& drawData, ApplicationData& appData) iconFontPath.append("\\remixicon.ttf"); io.Fonts->AddFontFromFileTTF(iconFontPath.c_str(), 14.0f, &icons_config, icons_ranges); - // Set window icon - HINSTANCE instance = GetModuleHandle(NULL); - LPWSTR iconId = MAKEINTRESOURCE(IDI_ICON1); - HANDLE iconLarge = LoadImageW(instance, iconId, IMAGE_ICON, 64, 64, 0); - HANDLE iconSmall = LoadImageW(instance, iconId, IMAGE_ICON, 32, 32, 0); - SendMessage(drawData.window_handle, WM_SETICON, ICON_BIG, (LPARAM)iconLarge); - SendMessage(drawData.window_handle, WM_SETICON, ICON_SMALL, (LPARAM)iconSmall); - SendMessage(drawData.window_handle, WM_SETICON, ICON_SMALL2, (LPARAM)iconSmall); - - // Set tray icon - NOTIFYICONDATA nid = { sizeof(nid) }; - nid.hWnd = drawData.window_handle; - nid.uFlags = NIF_ICON | NIF_TIP | NIF_MESSAGE | NIF_SHOWTIP; - nid.uID = TRAY_ID; - nid.uCallbackMessage = WMAPP_NOTIFYCALLBACK; - - HRESULT iconResult; - iconResult = LoadIconMetric(instance, iconId, LIM_SMALL, &nid.hIcon); - isError(iconResult, "Failed to load tray icon image: "); - - iconResult = LoadString(instance, IDS_STRING_TOOLTIP, nid.szTip, ARRAYSIZE(nid.szTip)); - isError(iconResult, "Failed to load tray icon text: "); - - Shell_NotifyIcon(NIM_ADD, &nid); - - nid.uVersion = NOTIFYICON_VERSION_4; - Shell_NotifyIcon(NIM_SETVERSION, &nid); - - if (!SetWindowsHookEx(WH_CALLWNDPROC, trayIconEventHandler, instance, GetCurrentThreadId())) - { - std::cout << "Failed to hook tray icon events: " << std::hex << GetLastError() << std::endl; - } - - // Set window minimize behavior - glfwSetWindowIconifyCallback(drawData.window, [](GLFWwindow* window, int isIconified) { - if (isIconified && gAppData->settings.docked) - { - glfwHideWindow(window); - } - isHidden = isIconified; - }); - - glfwSetWindowFocusCallback(drawData.window, [](GLFWwindow* window, int isFocused) { - if (!isFocused && gAppData->settings.docked && !justDocked) - { - glfwIconifyWindow(window); - } - }); - - // Load settings + + initShell(drawData); initSettings(drawData, appData); - - // Set up audio device api initAudio(appData); } @@ -140,7 +83,6 @@ void draw(DrawData& drawData, ApplicationData& appData) { justDocked = false; - // Actual Drawing if (isHidden) { glfwWaitEvents(); @@ -178,11 +120,7 @@ void draw(DrawData& drawData, ApplicationData& appData) void cleanup(DrawData& drawData, ApplicationData& appData) { - // Remove tray icon - NOTIFYICONDATA nid = { sizeof(nid) }; - nid.hWnd = drawData.window_handle; - nid.uID = TRAY_ID; - Shell_NotifyIcon(NIM_DELETE, &nid); + cleanupShell(drawData); } ImVec2 menuBar(DrawData& drawData, ApplicationData& appData) @@ -408,25 +346,3 @@ void drawCircle(float radius, ImU32 color) ImVec2 windowPos = ImGui::GetWindowPos(); drawList->AddCircleFilled(ImVec2(cursorPos.x + windowPos.x, cursorPos.y + windowPos.y + ImGui::GetTextLineHeight() / 2.), radius, color); } - -LRESULT CALLBACK trayIconEventHandler(int code, WPARAM wParam, LPARAM lParam) -{ - if (code >= 0) - { - CWPSTRUCT* data = (CWPSTRUCT*)lParam; - - if (data->message == WMAPP_NOTIFYCALLBACK) - { - auto id = HIWORD(data->lParam); - auto trayEvent = LOWORD(data->lParam); - - if (id == TRAY_ID && trayEvent == WM_LBUTTONUP) - { - glfwShowWindow(gDrawData->window); - glfwRestoreWindow(gDrawData->window); - } - } - } - - return CallNextHookEx(NULL, code, wParam, lParam); -} diff --git a/AsuroTool/AsuroTool.h b/AsuroTool/AsuroTool.h index 0e6004e..24ce7a1 100644 --- a/AsuroTool/AsuroTool.h +++ b/AsuroTool/AsuroTool.h @@ -12,5 +12,3 @@ void cleanup(DrawData& drawData, ApplicationData& appData); ImVec2 menuBar(DrawData& drawData, ApplicationData& appData); ImVec2 audioDeviceWindow(ApplicationData& appData, std::vector& deviceList, const char* title); void drawCircle(float radius, ImU32 color); - -LRESULT trayIconEventHandler(int code, WPARAM wParam, LPARAM lParam); diff --git a/AsuroTool/AsuroTool.rc b/AsuroTool/AsuroTool.rc index 639a9f1..f611f4e 100644 --- a/AsuroTool/AsuroTool.rc +++ b/AsuroTool/AsuroTool.rc @@ -111,7 +111,7 @@ END STRINGTABLE BEGIN - IDS_STRING_TOOLTIP "uwu" + IDS_STRING_TOOLTIP "Audio Thingy" END #endif // English (United Kingdom) resources diff --git a/AsuroTool/AsuroTool.vcxproj b/AsuroTool/AsuroTool.vcxproj index 4a0a73a..8f2b359 100644 --- a/AsuroTool/AsuroTool.vcxproj +++ b/AsuroTool/AsuroTool.vcxproj @@ -93,6 +93,7 @@ WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true 4305; 4244 + stdcpp17 Console @@ -111,6 +112,7 @@ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true 4305; 4244 + stdcpp17 Console @@ -129,6 +131,7 @@ _DEBUG;_CONSOLE;%(PreprocessorDefinitions) true 4305; 4244 + stdcpp17 Console @@ -147,6 +150,7 @@ NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true 4305; 4244 + stdcpp17 Console @@ -164,6 +168,7 @@ + @@ -175,6 +180,7 @@ + diff --git a/AsuroTool/AsuroTool.vcxproj.filters b/AsuroTool/AsuroTool.vcxproj.filters index 3b195b4..e579936 100644 --- a/AsuroTool/AsuroTool.vcxproj.filters +++ b/AsuroTool/AsuroTool.vcxproj.filters @@ -39,6 +39,9 @@ Source Files + + Source Files + @@ -65,6 +68,9 @@ Header Files\Audio + + Header Files + diff --git a/AsuroTool/WindowsShell.cpp b/AsuroTool/WindowsShell.cpp new file mode 100644 index 0000000..83b891a --- /dev/null +++ b/AsuroTool/WindowsShell.cpp @@ -0,0 +1,102 @@ +#include "WindowsShell.h" +#include "resource.h" +#include "ApplicationData.h" +#include "Util.h" + +#include +#include +#include +#include + +#include + +const UINT TRAY_ID = 420; +const UINT WMAPP_NOTIFYCALLBACK = WM_APP + 1; + +extern DrawData* gDrawData; +extern ApplicationData* gAppData; +extern bool justDocked; +extern bool isHidden; + +void initShell(DrawData& drawData) +{ + // Set window icon + HINSTANCE instance = GetModuleHandle(NULL); + LPWSTR iconId = MAKEINTRESOURCE(IDI_ICON1); + HANDLE iconLarge = LoadImageW(instance, iconId, IMAGE_ICON, 64, 64, 0); + HANDLE iconSmall = LoadImageW(instance, iconId, IMAGE_ICON, 32, 32, 0); + SendMessage(drawData.window_handle, WM_SETICON, ICON_BIG, (LPARAM)iconLarge); + SendMessage(drawData.window_handle, WM_SETICON, ICON_SMALL, (LPARAM)iconSmall); + SendMessage(drawData.window_handle, WM_SETICON, ICON_SMALL2, (LPARAM)iconSmall); + + // Set tray icon + NOTIFYICONDATA nid = { sizeof(nid) }; + nid.hWnd = drawData.window_handle; + nid.uFlags = NIF_ICON | NIF_TIP | NIF_MESSAGE | NIF_SHOWTIP; + nid.uID = TRAY_ID; + nid.uCallbackMessage = WMAPP_NOTIFYCALLBACK; + + HRESULT iconResult; + iconResult = LoadIconMetric(instance, iconId, LIM_SMALL, &nid.hIcon); + isError(iconResult, "Failed to load tray icon image: "); + + iconResult = LoadString(instance, IDS_STRING_TOOLTIP, nid.szTip, ARRAYSIZE(nid.szTip)); + isError(iconResult, "Failed to load tray icon text: "); + + Shell_NotifyIcon(NIM_ADD, &nid); + + nid.uVersion = NOTIFYICON_VERSION_4; + Shell_NotifyIcon(NIM_SETVERSION, &nid); + + if (!SetWindowsHookEx(WH_CALLWNDPROC, trayIconEventHandler, instance, GetCurrentThreadId())) + { + std::cout << "Failed to hook tray icon events: " << std::hex << GetLastError() << std::endl; + } + + // Set window minimize behavior + glfwSetWindowIconifyCallback(drawData.window, [](GLFWwindow* window, int isIconified) { + if (isIconified && gAppData->settings.docked) + { + glfwHideWindow(window); + } + isHidden = isIconified; + }); + + glfwSetWindowFocusCallback(drawData.window, [](GLFWwindow* window, int isFocused) { + if (!isFocused && gAppData->settings.docked && !justDocked) + { + glfwIconifyWindow(window); + } + }); +} + +void cleanupShell(DrawData& drawData) +{ + // Remove tray icon + NOTIFYICONDATA nid = { sizeof(nid) }; + nid.hWnd = drawData.window_handle; + nid.uID = TRAY_ID; + Shell_NotifyIcon(NIM_DELETE, &nid); +} + +LRESULT CALLBACK trayIconEventHandler(int code, WPARAM wParam, LPARAM lParam) +{ + if (code >= 0) + { + CWPSTRUCT* data = (CWPSTRUCT*)lParam; + + if (data->message == WMAPP_NOTIFYCALLBACK) + { + auto id = HIWORD(data->lParam); + auto trayEvent = LOWORD(data->lParam); + + if (id == TRAY_ID && (trayEvent == WM_LBUTTONUP || trayEvent == WM_RBUTTONUP)) + { + glfwShowWindow(gDrawData->window); + glfwRestoreWindow(gDrawData->window); + } + } + } + + return CallNextHookEx(NULL, code, wParam, lParam); +} diff --git a/AsuroTool/WindowsShell.h b/AsuroTool/WindowsShell.h new file mode 100644 index 0000000..032b0c1 --- /dev/null +++ b/AsuroTool/WindowsShell.h @@ -0,0 +1,8 @@ +#pragma once +#include + +void initShell(DrawData& drawData); + +void cleanupShell(DrawData& drawData); + +LRESULT trayIconEventHandler(int code, WPARAM wParam, LPARAM lParam);