From 90c062fd579b54b2a74d7d7e8d7f8f9cf2449be6 Mon Sep 17 00:00:00 2001 From: KnockKnockP Date: Thu, 27 Jun 2024 00:04:28 +0900 Subject: [PATCH 01/12] Add minimize to tray support. --- src/discord/Frontend.hpp | 3 +++ src/discord/LocalSettings.cpp | 3 +++ src/discord/LocalSettings.hpp | 7 +++++++ src/resource.rc | 2 +- src/windows/Frontend_Win32.cpp | 10 ++++++++++ src/windows/Frontend_Win32.hpp | 2 ++ src/windows/Main.cpp | 6 ++++++ src/windows/OptionsDialog.cpp | 7 +++++-- src/windows/ShellNotification.cpp | 22 +++++++++++++++++++++- src/windows/ShellNotification.hpp | 1 + 10 files changed, 59 insertions(+), 4 deletions(-) diff --git a/src/discord/Frontend.hpp b/src/discord/Frontend.hpp index 9d6edbd..1241aa7 100644 --- a/src/discord/Frontend.hpp +++ b/src/discord/Frontend.hpp @@ -98,6 +98,9 @@ class Frontend virtual std::string GetFormatTimeShortText() = 0; virtual std::string GetFormatTimeShorterText() = 0; + virtual void MinimizeWindow() = 0; + virtual void RestoreWindow() = 0; + // Debugging #ifdef USE_DEBUG_PRINTS virtual void DebugPrint(const char* fmt, va_list vl) = 0; diff --git a/src/discord/LocalSettings.cpp b/src/discord/LocalSettings.cpp index c7d81b5..2207d99 100644 --- a/src/discord/LocalSettings.cpp +++ b/src/discord/LocalSettings.cpp @@ -135,6 +135,8 @@ bool LocalSettings::Load() if (j.contains("AddExtraHeaders")) m_bAddExtraHeaders = j["AddExtraHeaders"]; + if (j.contains("MinimizeToNotif")) + m_bMinimizeToNotif = j["MinimizeToNotif"]; return true; } @@ -168,6 +170,7 @@ bool LocalSettings::Save() j["ShowEmbedContent"] = m_bShowEmbedContent; j["EnableNotifications"] = m_bEnableNotifications; j["FlashOnNotification"] = m_bFlashOnNotification; + j["MinimizeToNotif"] = m_bMinimizeToNotif; if (m_bSaveWindowSize) { j["WindowWidth"] = m_width; diff --git a/src/discord/LocalSettings.hpp b/src/discord/LocalSettings.hpp index d94e0ca..c47e003 100644 --- a/src/discord/LocalSettings.hpp +++ b/src/discord/LocalSettings.hpp @@ -74,6 +74,12 @@ class LocalSettings bool GetStartMaximized() const { return m_bStartMaximized; } + void SetMinimizeToNotif(bool b) { + m_bMinimizeToNotif = b; + } + bool GetMinimizeToNotif() const { + return m_bMinimizeToNotif; + } bool IsFirstStart() const { return m_bIsFirstStart; } @@ -193,6 +199,7 @@ class LocalSettings bool m_bReplyMentionDefault = true; bool m_bSaveWindowSize = false; bool m_bStartMaximized = false; + bool m_bMinimizeToNotif = true; bool m_bIsFirstStart = false; bool m_bCheckUpdates = false; bool m_bAskToCheckUpdates = true; diff --git a/src/resource.rc b/src/resource.rc index a09b95e..56840c4 100644 --- a/src/resource.rc +++ b/src/resource.rc @@ -687,7 +687,7 @@ BEGIN CONTROL "Open minimized to notification area",IDC_START_MINIMIZED, "Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,32,60,222,10 CONTROL "Minimize to notification area when clicking the close button",IDC_MINIMIZE_TO_NOTIF, - "Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,12,74,242,10 + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,74,242,10 END diff --git a/src/windows/Frontend_Win32.cpp b/src/windows/Frontend_Win32.cpp index a1ab383..b8286cf 100644 --- a/src/windows/Frontend_Win32.cpp +++ b/src/windows/Frontend_Win32.cpp @@ -399,6 +399,16 @@ void Frontend_Win32::RequestQuit() ::WantQuit(); } +void Frontend_Win32::MinimizeWindow() +{ + ShowWindow(g_Hwnd, SW_HIDE); +} + +void Frontend_Win32::RestoreWindow() +{ + ShowWindow(g_Hwnd, SW_RESTORE); +} + bool Frontend_Win32::IsWindowMinimized() { return IsIconic(g_Hwnd); diff --git a/src/windows/Frontend_Win32.hpp b/src/windows/Frontend_Win32.hpp index 0f3ebd9..29b9849 100644 --- a/src/windows/Frontend_Win32.hpp +++ b/src/windows/Frontend_Win32.hpp @@ -59,6 +59,8 @@ class Frontend_Win32 : public Frontend void RegisterAttachment(Snowflake sf, const std::string& avatarlnk) override; void RegisterChannelIcon(Snowflake sf, const std::string& avatarlnk) override; void RequestQuit() override; + void MinimizeWindow() override; + void RestoreWindow() override; bool IsWindowMinimized() override; std::string GetDirectMessagesText() override; std::string GetPleaseWaitText() override; diff --git a/src/windows/Main.cpp b/src/windows/Main.cpp index 3e5628c..b0f2df1 100644 --- a/src/windows/Main.cpp +++ b/src/windows/Main.cpp @@ -1121,6 +1121,12 @@ LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) ProfilePopout::Dismiss(); AutoComplete::DismissAutoCompleteWindowsIfNeeded(hWnd); g_pLoadingMessage->Hide(); + + if (GetLocalSettings()->GetMinimizeToNotif()) + { + GetFrontend()->MinimizeWindow(); + return 1; + } break; case WM_SIZE: { diff --git a/src/windows/OptionsDialog.cpp b/src/windows/OptionsDialog.cpp index 573a0e7..242abfb 100644 --- a/src/windows/OptionsDialog.cpp +++ b/src/windows/OptionsDialog.cpp @@ -242,8 +242,9 @@ void WINAPI OnChildDialogInit(HWND hwndDlg) } case PG_WINDOW: { - CheckDlgButton(hwndDlg, IDC_SAVE_WINDOW_SIZE, GetLocalSettings()->GetSaveWindowSize() ? BST_CHECKED : BST_UNCHECKED); - CheckDlgButton(hwndDlg, IDC_START_MAXIMIZED, GetLocalSettings()->GetStartMaximized() ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_SAVE_WINDOW_SIZE, GetLocalSettings()->GetSaveWindowSize() ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_START_MAXIMIZED, GetLocalSettings()->GetStartMaximized() ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_MINIMIZE_TO_NOTIF, GetLocalSettings()->GetMinimizeToNotif() ? BST_CHECKED : BST_UNCHECKED); break; } case PG_CONNECTION: @@ -491,6 +492,8 @@ INT_PTR CALLBACK ChildDialogProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPa case IDC_START_MAXIMIZED: GetLocalSettings()->SetStartMaximized(IsDlgButtonChecked(hWnd, IDC_START_MAXIMIZED)); break; + case IDC_MINIMIZE_TO_NOTIF: + GetLocalSettings()->SetMinimizeToNotif(IsDlgButtonChecked(hWnd, IDC_MINIMIZE_TO_NOTIF)); } break; } diff --git a/src/windows/ShellNotification.cpp b/src/windows/ShellNotification.cpp index f1a7a3a..3a93c5f 100644 --- a/src/windows/ShellNotification.cpp +++ b/src/windows/ShellNotification.cpp @@ -195,6 +195,24 @@ void ShellNotification::OnNotification() m_bAnyNotificationsSinceLastTime = false; } +void ShellNotification::ShowContextMenu() +{ + POINT cursor; + GetCursorPos(&cursor); + + const HMENU popupMenu = CreatePopupMenu(); + InsertMenu(popupMenu, 0, MF_BYPOSITION | MF_STRING, WM_DESTROY, L"Exit"); + + SetForegroundWindow(g_Hwnd); + const int command = TrackPopupMenu(popupMenu, TPM_LEFTBUTTON | TPM_RETURNCMD, cursor.x, cursor.y, 0, g_Hwnd, NULL); + PostMessage(g_Hwnd, WM_NULL, 0, 0); + + if (command == WM_DESTROY) + { + PostMessage(g_Hwnd, WM_DESTROY, 0, 0); + } +} + void ShellNotification::Callback(WPARAM wParam, LPARAM lParam) { switch (LOWORD(lParam)) @@ -228,6 +246,8 @@ void ShellNotification::Callback(WPARAM wParam, LPARAM lParam) } case WM_LBUTTONUP: + GetFrontend()->RestoreWindow(); + break; case WM_RBUTTONUP: { POINT pt; @@ -236,7 +256,7 @@ void ShellNotification::Callback(WPARAM wParam, LPARAM lParam) break; } - //ShowPopupMenu(pt, LOWORD(wParam) == WM_RBUTTONUP); + ShowContextMenu(); break; } } diff --git a/src/windows/ShellNotification.hpp b/src/windows/ShellNotification.hpp index 0d3e7d5..062cf7d 100644 --- a/src/windows/ShellNotification.hpp +++ b/src/windows/ShellNotification.hpp @@ -22,6 +22,7 @@ class ShellNotification void ShowBalloon(const std::string& titleString, const std::string& contents); void ShowBalloonForOneNotification(Notification* pNotif); void ShowBalloonForNotifications(const std::vector& pNotifs); + void ShowContextMenu(); private: bool m_bInitialized = false; From 8ebae27311c20528b43ca3cd0d7977aea64eb6c3 Mon Sep 17 00:00:00 2001 From: KnockKnockP Date: Thu, 27 Jun 2024 00:07:31 +0900 Subject: [PATCH 02/12] Fix formatting. --- src/windows/OptionsDialog.cpp | 1 + src/windows/ShellNotification.cpp | 1 + 2 files changed, 2 insertions(+) diff --git a/src/windows/OptionsDialog.cpp b/src/windows/OptionsDialog.cpp index 242abfb..eec20f8 100644 --- a/src/windows/OptionsDialog.cpp +++ b/src/windows/OptionsDialog.cpp @@ -494,6 +494,7 @@ INT_PTR CALLBACK ChildDialogProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPa break; case IDC_MINIMIZE_TO_NOTIF: GetLocalSettings()->SetMinimizeToNotif(IsDlgButtonChecked(hWnd, IDC_MINIMIZE_TO_NOTIF)); + break; } break; } diff --git a/src/windows/ShellNotification.cpp b/src/windows/ShellNotification.cpp index 3a93c5f..6d969ed 100644 --- a/src/windows/ShellNotification.cpp +++ b/src/windows/ShellNotification.cpp @@ -248,6 +248,7 @@ void ShellNotification::Callback(WPARAM wParam, LPARAM lParam) case WM_LBUTTONUP: GetFrontend()->RestoreWindow(); break; + case WM_RBUTTONUP: { POINT pt; From 046517631325fb79cc066e4b1d438bca7c33fa8d Mon Sep 17 00:00:00 2001 From: KnockKnockP Date: Thu, 27 Jun 2024 01:59:34 +0900 Subject: [PATCH 03/12] Check for an existing instance. --- src/windows/Main.cpp | 57 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/src/windows/Main.cpp b/src/windows/Main.cpp index b0f2df1..6909839 100644 --- a/src/windows/Main.cpp +++ b/src/windows/Main.cpp @@ -29,6 +29,7 @@ #include "../discord/WebsocketClient.hpp" #include "../discord/UpdateChecker.hpp" +#include #include // proportions: @@ -1436,6 +1437,9 @@ LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) GetShellNotification()->Callback(wParam, lParam); break; } + case SW_RESTORE: + GetFrontend()->RestoreWindow(); + break; } return DefWindowProc(hWnd, uMsg, wParam, lParam); @@ -1569,8 +1573,61 @@ HTTPClient* GetHTTPClient() return g_pHTTPClient; } +//https://stackoverflow.com/a/48207646 +static void GetAllWindowsFromProcessID(const DWORD dwProcessID, std::vector & vhWnds) +{ + HWND hCurWnd = NULL; + do + { + hCurWnd = FindWindowEx(NULL, hCurWnd, NULL, NULL); + DWORD dwProcID = 0; + GetWindowThreadProcessId(hCurWnd, &dwProcID); + if (dwProcID == dwProcessID) + { + vhWnds.push_back(hCurWnd); + } + } while (hCurWnd != NULL); +} + +static bool CheckExistingProcesses() +{ + TCHAR fileNameRaw[MAX_PATH]; + GetModuleFileName(NULL, fileNameRaw, MAX_PATH); + TCHAR* fileName = PathFindFileName(fileNameRaw); + + PROCESSENTRY32 processEntry32; + processEntry32.dwSize = sizeof(PROCESSENTRY32); + + HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); + const DWORD selfPid = GetCurrentProcessId(); + + if (Process32First(snapshot, &processEntry32)) + { + while (Process32Next(snapshot, &processEntry32)) + { + if (!_tcscmp(processEntry32.szExeFile, fileName) && processEntry32.th32ProcessID != selfPid) + { + std::vector windows; + GetAllWindowsFromProcessID(processEntry32.th32ProcessID, windows); + + for (HWND window : windows) { + SendMessage(window, SW_RESTORE, 0, 0); + } + + return true; + } + } + } + + CloseHandle(snapshot); + return false; +} + int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR pCmdLine, int nShowCmd) { + if (CheckExistingProcesses()) + return 0; + g_hInstance = hInstance; ri::InitReimplementation(); From 989583f2e67b8d8948eab8884ec9199f5bf5d7de Mon Sep 17 00:00:00 2001 From: KnockKnockP Date: Thu, 27 Jun 2024 18:16:37 +0900 Subject: [PATCH 04/12] Use mutex to force single instance. --- src/windows/InstanceMutex.cpp | 32 +++++++++++++++ src/windows/InstanceMutex.hpp | 15 +++++++ src/windows/Main.cpp | 61 +++++++---------------------- src/windows/WindowMessages.hpp | 1 + vs/DiscordMessenger.vcxproj | 2 + vs/DiscordMessenger.vcxproj.filters | 6 +++ 6 files changed, 71 insertions(+), 46 deletions(-) create mode 100644 src/windows/InstanceMutex.cpp create mode 100644 src/windows/InstanceMutex.hpp diff --git a/src/windows/InstanceMutex.cpp b/src/windows/InstanceMutex.cpp new file mode 100644 index 0000000..a0b8a00 --- /dev/null +++ b/src/windows/InstanceMutex.cpp @@ -0,0 +1,32 @@ +#include "InstanceMutex.hpp" + +void InstanceMutex::Close() +{ + if (m_handle) + { + CloseHandle(m_handle); + m_handle = NULL; + } +} + +HRESULT InstanceMutex::Init() +{ +#ifdef DISABLE_SINGLE_INSTANCE + return 0; +#else + + SetLastError(NO_ERROR); + m_handle = CreateMutex(NULL, TRUE, L"DiscordMessenger"); + + const DWORD error = GetLastError(); + if (error == ERROR_ALREADY_EXISTS) + Close(); + + return error; +#endif +} + +InstanceMutex::~InstanceMutex() +{ + Close(); +} \ No newline at end of file diff --git a/src/windows/InstanceMutex.hpp b/src/windows/InstanceMutex.hpp new file mode 100644 index 0000000..fa004fc --- /dev/null +++ b/src/windows/InstanceMutex.hpp @@ -0,0 +1,15 @@ +#pragma once + +#include + +class InstanceMutex +{ +private: + HANDLE m_handle = NULL; + + void Close(); + +public: + HRESULT Init(); + ~InstanceMutex(); +}; \ No newline at end of file diff --git a/src/windows/Main.cpp b/src/windows/Main.cpp index 6909839..fc992fa 100644 --- a/src/windows/Main.cpp +++ b/src/windows/Main.cpp @@ -25,11 +25,11 @@ #include "ProgressDialog.hpp" #include "AutoComplete.hpp" #include "ShellNotification.hpp" +#include "InstanceMutex.hpp" #include "../discord/LocalSettings.hpp" #include "../discord/WebsocketClient.hpp" #include "../discord/UpdateChecker.hpp" -#include #include // proportions: @@ -1437,7 +1437,7 @@ LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) GetShellNotification()->Callback(wParam, lParam); break; } - case SW_RESTORE: + case WM_RESTORE: GetFrontend()->RestoreWindow(); break; } @@ -1573,59 +1573,28 @@ HTTPClient* GetHTTPClient() return g_pHTTPClient; } -//https://stackoverflow.com/a/48207646 -static void GetAllWindowsFromProcessID(const DWORD dwProcessID, std::vector & vhWnds) -{ - HWND hCurWnd = NULL; - do - { - hCurWnd = FindWindowEx(NULL, hCurWnd, NULL, NULL); - DWORD dwProcID = 0; - GetWindowThreadProcessId(hCurWnd, &dwProcID); - if (dwProcID == dwProcessID) - { - vhWnds.push_back(hCurWnd); - } - } while (hCurWnd != NULL); -} +InstanceMutex g_instanceMutex; -static bool CheckExistingProcesses() +static bool ForceSingleInstance(LPCWSTR pClassName) { - TCHAR fileNameRaw[MAX_PATH]; - GetModuleFileName(NULL, fileNameRaw, MAX_PATH); - TCHAR* fileName = PathFindFileName(fileNameRaw); - - PROCESSENTRY32 processEntry32; - processEntry32.dwSize = sizeof(PROCESSENTRY32); + HRESULT hResult = g_instanceMutex.Init(); - HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); - const DWORD selfPid = GetCurrentProcessId(); + if (hResult != ERROR_ALREADY_EXISTS) + return false; - if (Process32First(snapshot, &processEntry32)) + HWND hWnd = FindWindow(pClassName, NULL); + if (hWnd) { - while (Process32Next(snapshot, &processEntry32)) - { - if (!_tcscmp(processEntry32.szExeFile, fileName) && processEntry32.th32ProcessID != selfPid) - { - std::vector windows; - GetAllWindowsFromProcessID(processEntry32.th32ProcessID, windows); - - for (HWND window : windows) { - SendMessage(window, SW_RESTORE, 0, 0); - } - - return true; - } - } + SendMessage(hWnd, WM_RESTORE, 0, 0); } - - CloseHandle(snapshot); - return false; + return true; } int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR pCmdLine, int nShowCmd) { - if (CheckExistingProcesses()) + LPCWSTR pClassName = TEXT("DiscordMessengerClass"); + + if (ForceSingleInstance(pClassName)) return 0; g_hInstance = hInstance; @@ -1657,7 +1626,7 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR pCmdLin wc.lpfnWndProc = WindowProc; wc.hInstance = hInstance; - wc.lpszClassName = TEXT("DiscordMessengerClass"); + wc.lpszClassName = pClassName; wc.hbrBackground = g_backgroundBrush; wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hIcon = g_Icon = LoadIcon(hInstance, MAKEINTRESOURCE(DMIC(IDI_ICON))); diff --git a/src/windows/WindowMessages.hpp b/src/windows/WindowMessages.hpp index 6c85d53..4fc4f5d 100644 --- a/src/windows/WindowMessages.hpp +++ b/src/windows/WindowMessages.hpp @@ -67,4 +67,5 @@ enum eWmUserMsgs WM_RECREATEMEMBERLIST, WM_UPDATETEXTSIZE = WM_APP, // used by the MessageEditor + WM_RESTORE, }; diff --git a/vs/DiscordMessenger.vcxproj b/vs/DiscordMessenger.vcxproj index 34638a0..c053c46 100644 --- a/vs/DiscordMessenger.vcxproj +++ b/vs/DiscordMessenger.vcxproj @@ -504,6 +504,7 @@ + @@ -568,6 +569,7 @@ + diff --git a/vs/DiscordMessenger.vcxproj.filters b/vs/DiscordMessenger.vcxproj.filters index 9735827..d8e5a39 100644 --- a/vs/DiscordMessenger.vcxproj.filters +++ b/vs/DiscordMessenger.vcxproj.filters @@ -629,6 +629,9 @@ Header Files\Discord + + Header Files\Windows + @@ -799,5 +802,8 @@ Source Files\Discord + + Source Files\Windows + \ No newline at end of file From 552bb81c10b8741bff2430e14678507a99ec642a Mon Sep 17 00:00:00 2001 From: KnockKnockP Date: Thu, 27 Jun 2024 19:14:50 +0900 Subject: [PATCH 05/12] Code review. --- src/windows/InstanceMutex.cpp | 3 +-- src/windows/Main.cpp | 8 ++++---- src/windows/ShellNotification.cpp | 2 +- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/src/windows/InstanceMutex.cpp b/src/windows/InstanceMutex.cpp index a0b8a00..a963ee6 100644 --- a/src/windows/InstanceMutex.cpp +++ b/src/windows/InstanceMutex.cpp @@ -15,8 +15,7 @@ HRESULT InstanceMutex::Init() return 0; #else - SetLastError(NO_ERROR); - m_handle = CreateMutex(NULL, TRUE, L"DiscordMessenger"); + m_handle = CreateMutex(NULL, TRUE, TEXT("DiscordMessenger")); const DWORD error = GetLastError(); if (error == ERROR_ALREADY_EXISTS) diff --git a/src/windows/Main.cpp b/src/windows/Main.cpp index fc992fa..5019af7 100644 --- a/src/windows/Main.cpp +++ b/src/windows/Main.cpp @@ -1123,7 +1123,7 @@ LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) AutoComplete::DismissAutoCompleteWindowsIfNeeded(hWnd); g_pLoadingMessage->Hide(); - if (GetLocalSettings()->GetMinimizeToNotif()) + if (GetLocalSettings()->GetStartMaximized()) { GetFrontend()->MinimizeWindow(); return 1; @@ -1580,21 +1580,21 @@ static bool ForceSingleInstance(LPCWSTR pClassName) HRESULT hResult = g_instanceMutex.Init(); if (hResult != ERROR_ALREADY_EXISTS) - return false; + return true; HWND hWnd = FindWindow(pClassName, NULL); if (hWnd) { SendMessage(hWnd, WM_RESTORE, 0, 0); } - return true; + return false; } int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR pCmdLine, int nShowCmd) { LPCWSTR pClassName = TEXT("DiscordMessengerClass"); - if (ForceSingleInstance(pClassName)) + if (!ForceSingleInstance(pClassName)) return 0; g_hInstance = hInstance; diff --git a/src/windows/ShellNotification.cpp b/src/windows/ShellNotification.cpp index 6d969ed..29f7f5b 100644 --- a/src/windows/ShellNotification.cpp +++ b/src/windows/ShellNotification.cpp @@ -201,7 +201,7 @@ void ShellNotification::ShowContextMenu() GetCursorPos(&cursor); const HMENU popupMenu = CreatePopupMenu(); - InsertMenu(popupMenu, 0, MF_BYPOSITION | MF_STRING, WM_DESTROY, L"Exit"); + InsertMenu(popupMenu, 0, MF_BYPOSITION | MF_STRING, WM_DESTROY, TEXT("Exit")); SetForegroundWindow(g_Hwnd); const int command = TrackPopupMenu(popupMenu, TPM_LEFTBUTTON | TPM_RETURNCMD, cursor.x, cursor.y, 0, g_Hwnd, NULL); From c004757ad1000846daf0ed88757786add41d730b Mon Sep 17 00:00:00 2001 From: KnockKnockP Date: Fri, 28 Jun 2024 02:23:35 +0900 Subject: [PATCH 06/12] Tray context menu in resources, launch on startup, start minimized. --- src/discord/LocalSettings.cpp | 16 ++++++-- src/discord/LocalSettings.hpp | 14 +++++++ src/resource.h | 7 +++- src/resource.rc | 20 ++++++++- src/windows/Main.cpp | 68 ++++++++++++++++++++++++++++--- src/windows/OptionsDialog.cpp | 15 +++++++ src/windows/ShellNotification.cpp | 25 +++--------- src/windows/WindowMessages.hpp | 1 + 8 files changed, 134 insertions(+), 32 deletions(-) diff --git a/src/discord/LocalSettings.cpp b/src/discord/LocalSettings.cpp index 2207d99..50bbd91 100644 --- a/src/discord/LocalSettings.cpp +++ b/src/discord/LocalSettings.cpp @@ -71,6 +71,15 @@ bool LocalSettings::Load() if (j.contains("StartMaximized")) m_bStartMaximized = j["StartMaximized"]; + if (j.contains("OpenOnStartup")) + m_bOpenOnStartup = j["OpenOnStartup"]; + + if (j.contains("StartMinimized")) + m_bStartMinimized = j["StartMinimized"]; + + if (j.contains("MinimizeToNotif")) + m_bMinimizeToNotif = j["MinimizeToNotif"]; + if (j.contains("EnableTLSVerification")) m_bEnableTLSVerification = j["EnableTLSVerification"]; @@ -134,9 +143,6 @@ bool LocalSettings::Load() if (j.contains("AddExtraHeaders")) m_bAddExtraHeaders = j["AddExtraHeaders"]; - - if (j.contains("MinimizeToNotif")) - m_bMinimizeToNotif = j["MinimizeToNotif"]; return true; } @@ -155,6 +161,9 @@ bool LocalSettings::Save() j["ReplyMentionDefault"] = m_bReplyMentionDefault; j["StartMaximized"] = m_bStartMaximized; j["SaveWindowSize"] = m_bSaveWindowSize; + j["OpenOnStartup"] = m_bOpenOnStartup; + j["StartMinimized"] = m_bStartMinimized; + j["MinimizeToNotif"] = m_bMinimizeToNotif; j["CheckUpdates"] = m_bCheckUpdates; j["EnableTLSVerification"] = m_bEnableTLSVerification; j["DisableFormatting"] = m_bDisableFormatting; @@ -170,7 +179,6 @@ bool LocalSettings::Save() j["ShowEmbedContent"] = m_bShowEmbedContent; j["EnableNotifications"] = m_bEnableNotifications; j["FlashOnNotification"] = m_bFlashOnNotification; - j["MinimizeToNotif"] = m_bMinimizeToNotif; if (m_bSaveWindowSize) { j["WindowWidth"] = m_width; diff --git a/src/discord/LocalSettings.hpp b/src/discord/LocalSettings.hpp index c47e003..154d31f 100644 --- a/src/discord/LocalSettings.hpp +++ b/src/discord/LocalSettings.hpp @@ -74,6 +74,18 @@ class LocalSettings bool GetStartMaximized() const { return m_bStartMaximized; } + void SetOpenOnStartup(bool b) { + m_bOpenOnStartup = b; + } + bool GetOpenOnStartup() const { + return m_bOpenOnStartup; + } + void SetStartMinimized(bool b) { + m_bStartMinimized = b; + } + bool GetStartMinimized() const { + return m_bStartMinimized; + } void SetMinimizeToNotif(bool b) { m_bMinimizeToNotif = b; } @@ -199,6 +211,8 @@ class LocalSettings bool m_bReplyMentionDefault = true; bool m_bSaveWindowSize = false; bool m_bStartMaximized = false; + bool m_bOpenOnStartup = false; + bool m_bStartMinimized = false; bool m_bMinimizeToNotif = true; bool m_bIsFirstStart = false; bool m_bCheckUpdates = false; diff --git a/src/resource.h b/src/resource.h index 21e88de..6fc90fe 100644 --- a/src/resource.h +++ b/src/resource.h @@ -98,6 +98,7 @@ #define IDI_SCROLL 98 #define IDI_NOTIFICATION 99 #define IDI_NOTIFICATION_2K 100 +#define IDR_NOTIFICATION_CONTEXT 101 #define IDB_TARGET 200 #define IDB_CHANNEL 201 #define IDB_CATEGORY 202 @@ -475,6 +476,8 @@ #define IDM_BLOCK 1065 #define IDM_COPYID 1066 #define ID_ACTIONS_QUICKSWITCHER 1067 +#define ID_NOTIFICATION_SHOW 1068 +#define ID_NOTIFICATION_EXIT 1069 #define IDR_MAIN_ACCELS 1201 #define IDA_SEARCH 1301 #define IDA_QUICKSWITCHER 1302 @@ -484,8 +487,8 @@ // #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 101 -#define _APS_NEXT_COMMAND_VALUE 1069 +#define _APS_NEXT_RESOURCE_VALUE 102 +#define _APS_NEXT_COMMAND_VALUE 1079 #define _APS_NEXT_CONTROL_VALUE 904 #define _APS_NEXT_SYMED_VALUE 40000 #endif diff --git a/src/resource.rc b/src/resource.rc index 56840c4..e685c17 100644 --- a/src/resource.rc +++ b/src/resource.rc @@ -202,6 +202,24 @@ BEGIN END END +IDR_NOTIFICATION_CONTEXT MENU +BEGIN + POPUP "Notification" + BEGIN + MENUITEM "Show", ID_NOTIFICATION_SHOW + POPUP "Status" + BEGIN + MENUITEM "Online", ID_ONLINESTATUSPLACEHOLDER_ONLINE, CHECKED + MENUITEM SEPARATOR + MENUITEM "Idle", ID_ONLINESTATUSPLACEHOLDER_IDLE + MENUITEM "Do not disturb", ID_ONLINESTATUSPLACEHOLDER_DONOTDISTURB + MENUITEM "Invisible", ID_ONLINESTATUSPLACEHOLDER_INVISIBLE + END + MENUITEM SEPARATOR + MENUITEM "Exit", ID_NOTIFICATION_EXIT + END +END + ///////////////////////////////////////////////////////////////////////////// // @@ -683,7 +701,7 @@ BEGIN CONTROL "Save window size",IDC_SAVE_WINDOW_SIZE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,18,236,10 CONTROL "Start maximized",IDC_START_MAXIMIZED,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,32,236,10 CONTROL "Open Discord Messenger when your computer starts",IDC_OPEN_ON_STARTUP, - "Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,12,46,242,10 + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,46,242,10 CONTROL "Open minimized to notification area",IDC_START_MINIMIZED, "Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,32,60,222,10 CONTROL "Minimize to notification area when clicking the close button",IDC_MINIMIZE_TO_NOTIF, diff --git a/src/windows/Main.cpp b/src/windows/Main.cpp index 5019af7..f242030 100644 --- a/src/windows/Main.cpp +++ b/src/windows/Main.cpp @@ -416,6 +416,14 @@ int OnSSLError(const std::string& url) return MessageBox(g_Hwnd, buffer, TmGetTString(IDS_SSL_ERROR_TITLE), MB_ABORTRETRYIGNORE | MB_ICONWARNING); } +void CloseCleanup(HWND hWnd) +{ + KillImageViewer(); + ProfilePopout::Dismiss(); + AutoComplete::DismissAutoCompleteWindowsIfNeeded(hWnd); + g_pLoadingMessage->Hide(); +} + BOOL HandleCommand(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (LOWORD(wParam)) @@ -439,7 +447,7 @@ BOOL HandleCommand(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) } case ID_FILE_EXIT: { - SendMessage(hWnd, WM_CLOSE, 0, 0); + SendMessage(hWnd, WM_CLOSEBYPASSTRAY, 0, 0); return 0; } case ID_HELP_ABOUTDISCORDMESSENGER: @@ -597,6 +605,12 @@ BOOL HandleCommand(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) if (!isClipboardClosed) CloseClipboard(); break; } + case ID_NOTIFICATION_SHOW: + SendMessage(g_Hwnd, WM_RESTORE, 0, 0); + break; + case ID_NOTIFICATION_EXIT: + SendMessage(g_Hwnd, WM_CLOSEBYPASSTRAY, 0, 0); + break; } return DefWindowProc(hWnd, uMsg, wParam, lParam); @@ -623,6 +637,39 @@ void ResetTryAgainInTime() { g_tryAgainTimerElapse = 500; } +const LPTSTR g_tStartupArg = TEXT(" --startup"); +const LPSTR g_StartupArg = "--startup"; + +bool g_bFromStartup = false; + +void CheckIfItsStartup(const LPSTR pCmdLine) +{ + g_bFromStartup = StrStrA(pCmdLine, g_StartupArg); +} + +void AddOrRemoveAppFromStartup() +{ + HKEY hkey = NULL; + RegCreateKey(HKEY_CURRENT_USER, TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Run"), &hkey); + + LPCTSTR value = TmGetTString(IDS_PROGRAM_NAME); + + if (GetLocalSettings()->GetOpenOnStartup()) + { + TCHAR tPath[MAX_PATH]; + const DWORD length = GetModuleFileName(NULL, tPath, MAX_PATH); + + const std::string sPath = "\"" + MakeStringFromTString(tPath) + "\"" + MakeStringFromTString(g_tStartupArg); + const LPTSTR finalPath = ConvertCppStringToTString(sPath); + + RegSetValueEx(hkey, value, 0, REG_SZ, (BYTE *)finalPath, (wcslen(finalPath) + 1) * sizeof(TCHAR)); + } + else + { + RegDeleteValue(hkey, value); + } +} + int g_agerCounter = 0; LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) @@ -1094,6 +1141,10 @@ LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) g_tryAgainTimer = 0; } g_pLoadingMessage->Hide(); + + if (g_bFromStartup && GetLocalSettings()->GetStartMinimized()) { + GetFrontend()->MinimizeWindow(); + } break; case WM_CONNECTING: { g_pLoadingMessage->Show(); @@ -1117,13 +1168,16 @@ LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) break; } + case WM_CLOSEBYPASSTRAY: + AddOrRemoveAppFromStartup(); + CloseCleanup(hWnd); + DestroyWindow(hWnd); + break; + case WM_CLOSE: - KillImageViewer(); - ProfilePopout::Dismiss(); - AutoComplete::DismissAutoCompleteWindowsIfNeeded(hWnd); - g_pLoadingMessage->Hide(); + CloseCleanup(hWnd); - if (GetLocalSettings()->GetStartMaximized()) + if (GetLocalSettings()->GetMinimizeToNotif()) { GetFrontend()->MinimizeWindow(); return 1; @@ -1597,6 +1651,8 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR pCmdLin if (!ForceSingleInstance(pClassName)) return 0; + CheckIfItsStartup(pCmdLine); + g_hInstance = hInstance; ri::InitReimplementation(); diff --git a/src/windows/OptionsDialog.cpp b/src/windows/OptionsDialog.cpp index eec20f8..ea87eeb 100644 --- a/src/windows/OptionsDialog.cpp +++ b/src/windows/OptionsDialog.cpp @@ -244,6 +244,11 @@ void WINAPI OnChildDialogInit(HWND hwndDlg) { CheckDlgButton(hwndDlg, IDC_SAVE_WINDOW_SIZE, GetLocalSettings()->GetSaveWindowSize() ? BST_CHECKED : BST_UNCHECKED); CheckDlgButton(hwndDlg, IDC_START_MAXIMIZED, GetLocalSettings()->GetStartMaximized() ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_OPEN_ON_STARTUP, GetLocalSettings()->GetOpenOnStartup() ? BST_CHECKED : BST_UNCHECKED); + + CheckDlgButton(hwndDlg, IDC_START_MINIMIZED, GetLocalSettings()->GetStartMinimized() ? BST_CHECKED : BST_UNCHECKED); + EnableWindow(GetDlgItem(hwndDlg, IDC_START_MINIMIZED), GetLocalSettings()->GetOpenOnStartup()); + CheckDlgButton(hwndDlg, IDC_MINIMIZE_TO_NOTIF, GetLocalSettings()->GetMinimizeToNotif() ? BST_CHECKED : BST_UNCHECKED); break; } @@ -492,6 +497,16 @@ INT_PTR CALLBACK ChildDialogProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPa case IDC_START_MAXIMIZED: GetLocalSettings()->SetStartMaximized(IsDlgButtonChecked(hWnd, IDC_START_MAXIMIZED)); break; + case IDC_OPEN_ON_STARTUP: + { + const bool checked = IsDlgButtonChecked(hWnd, IDC_OPEN_ON_STARTUP); + GetLocalSettings()->SetOpenOnStartup(checked); + EnableWindow(GetDlgItem(hWnd, IDC_START_MINIMIZED), checked); + break; + } + case IDC_START_MINIMIZED: + GetLocalSettings()->SetStartMinimized(IsDlgButtonChecked(hWnd, IDC_START_MINIMIZED)); + break; case IDC_MINIMIZE_TO_NOTIF: GetLocalSettings()->SetMinimizeToNotif(IsDlgButtonChecked(hWnd, IDC_MINIMIZE_TO_NOTIF)); break; diff --git a/src/windows/ShellNotification.cpp b/src/windows/ShellNotification.cpp index 29f7f5b..410be9a 100644 --- a/src/windows/ShellNotification.cpp +++ b/src/windows/ShellNotification.cpp @@ -198,19 +198,14 @@ void ShellNotification::OnNotification() void ShellNotification::ShowContextMenu() { POINT cursor; - GetCursorPos(&cursor); - - const HMENU popupMenu = CreatePopupMenu(); - InsertMenu(popupMenu, 0, MF_BYPOSITION | MF_STRING, WM_DESTROY, TEXT("Exit")); + if (!GetCursorPos(&cursor)) { + DbgPrintW("Could not acquire cursor position."); + return; + } + const HMENU popupMenu = GetSubMenu(LoadMenu(g_hInstance, MAKEINTRESOURCE(IDR_NOTIFICATION_CONTEXT)), 0); SetForegroundWindow(g_Hwnd); - const int command = TrackPopupMenu(popupMenu, TPM_LEFTBUTTON | TPM_RETURNCMD, cursor.x, cursor.y, 0, g_Hwnd, NULL); - PostMessage(g_Hwnd, WM_NULL, 0, 0); - - if (command == WM_DESTROY) - { - PostMessage(g_Hwnd, WM_DESTROY, 0, 0); - } + TrackPopupMenu(popupMenu, TPM_LEFTBUTTON, cursor.x, cursor.y, 0, g_Hwnd, NULL); } void ShellNotification::Callback(WPARAM wParam, LPARAM lParam) @@ -250,16 +245,8 @@ void ShellNotification::Callback(WPARAM wParam, LPARAM lParam) break; case WM_RBUTTONUP: - { - POINT pt; - if (!GetCursorPos(&pt)) { - DbgPrintW("Could not acquire cursor position."); - break; - } - ShowContextMenu(); break; - } } diff --git a/src/windows/WindowMessages.hpp b/src/windows/WindowMessages.hpp index 4fc4f5d..cd3aa35 100644 --- a/src/windows/WindowMessages.hpp +++ b/src/windows/WindowMessages.hpp @@ -65,6 +65,7 @@ enum eWmUserMsgs WM_NOTIFMANAGERCALLBACK, WM_POSTINIT, WM_RECREATEMEMBERLIST, + WM_CLOSEBYPASSTRAY, WM_UPDATETEXTSIZE = WM_APP, // used by the MessageEditor WM_RESTORE, From 4ec73974656602f4ad6815fd82e76ba2c3193fcd Mon Sep 17 00:00:00 2001 From: KnockKnockP Date: Sat, 29 Jun 2024 18:09:45 +0900 Subject: [PATCH 07/12] Remember maximization when restoring. --- src/discord/Frontend.hpp | 3 ++- src/discord/LocalSettings.cpp | 4 ++++ src/discord/LocalSettings.hpp | 7 +++++++ src/windows/Frontend_Win32.cpp | 7 ++++++- src/windows/Frontend_Win32.hpp | 3 ++- src/windows/Main.cpp | 21 ++++++++++++++++++--- src/windows/ShellNotification.cpp | 2 +- 7 files changed, 40 insertions(+), 7 deletions(-) diff --git a/src/discord/Frontend.hpp b/src/discord/Frontend.hpp index 1241aa7..a993a85 100644 --- a/src/discord/Frontend.hpp +++ b/src/discord/Frontend.hpp @@ -98,8 +98,9 @@ class Frontend virtual std::string GetFormatTimeShortText() = 0; virtual std::string GetFormatTimeShorterText() = 0; - virtual void MinimizeWindow() = 0; + virtual void HideWindow() = 0; virtual void RestoreWindow() = 0; + virtual void MaximizeWindow() = 0; // Debugging #ifdef USE_DEBUG_PRINTS diff --git a/src/discord/LocalSettings.cpp b/src/discord/LocalSettings.cpp index 50bbd91..3921736 100644 --- a/src/discord/LocalSettings.cpp +++ b/src/discord/LocalSettings.cpp @@ -80,6 +80,9 @@ bool LocalSettings::Load() if (j.contains("MinimizeToNotif")) m_bMinimizeToNotif = j["MinimizeToNotif"]; + if (j.contains("m_bMaximized")) + m_bMinimizeToNotif = j["m_bMaximized"]; + if (j.contains("EnableTLSVerification")) m_bEnableTLSVerification = j["EnableTLSVerification"]; @@ -164,6 +167,7 @@ bool LocalSettings::Save() j["OpenOnStartup"] = m_bOpenOnStartup; j["StartMinimized"] = m_bStartMinimized; j["MinimizeToNotif"] = m_bMinimizeToNotif; + j["m_bMaximized"] = m_bMaximized; j["CheckUpdates"] = m_bCheckUpdates; j["EnableTLSVerification"] = m_bEnableTLSVerification; j["DisableFormatting"] = m_bDisableFormatting; diff --git a/src/discord/LocalSettings.hpp b/src/discord/LocalSettings.hpp index 154d31f..61647ea 100644 --- a/src/discord/LocalSettings.hpp +++ b/src/discord/LocalSettings.hpp @@ -92,6 +92,12 @@ class LocalSettings bool GetMinimizeToNotif() const { return m_bMinimizeToNotif; } + void SetMaximized(bool b) { + m_bMaximized = b; + } + bool GetMaximized() const { + return m_bMaximized; + } bool IsFirstStart() const { return m_bIsFirstStart; } @@ -214,6 +220,7 @@ class LocalSettings bool m_bOpenOnStartup = false; bool m_bStartMinimized = false; bool m_bMinimizeToNotif = true; + bool m_bMaximized = false; bool m_bIsFirstStart = false; bool m_bCheckUpdates = false; bool m_bAskToCheckUpdates = true; diff --git a/src/windows/Frontend_Win32.cpp b/src/windows/Frontend_Win32.cpp index b8286cf..9aaddba 100644 --- a/src/windows/Frontend_Win32.cpp +++ b/src/windows/Frontend_Win32.cpp @@ -399,7 +399,7 @@ void Frontend_Win32::RequestQuit() ::WantQuit(); } -void Frontend_Win32::MinimizeWindow() +void Frontend_Win32::HideWindow() { ShowWindow(g_Hwnd, SW_HIDE); } @@ -409,6 +409,11 @@ void Frontend_Win32::RestoreWindow() ShowWindow(g_Hwnd, SW_RESTORE); } +void Frontend_Win32::MaximizeWindow() +{ + ShowWindow(g_Hwnd, SW_MAXIMIZE); +} + bool Frontend_Win32::IsWindowMinimized() { return IsIconic(g_Hwnd); diff --git a/src/windows/Frontend_Win32.hpp b/src/windows/Frontend_Win32.hpp index 29b9849..e991a17 100644 --- a/src/windows/Frontend_Win32.hpp +++ b/src/windows/Frontend_Win32.hpp @@ -59,8 +59,9 @@ class Frontend_Win32 : public Frontend void RegisterAttachment(Snowflake sf, const std::string& avatarlnk) override; void RegisterChannelIcon(Snowflake sf, const std::string& avatarlnk) override; void RequestQuit() override; - void MinimizeWindow() override; + void HideWindow() override; void RestoreWindow() override; + void MaximizeWindow() override; bool IsWindowMinimized() override; std::string GetDirectMessagesText() override; std::string GetPleaseWaitText() override; diff --git a/src/windows/Main.cpp b/src/windows/Main.cpp index f242030..6f120eb 100644 --- a/src/windows/Main.cpp +++ b/src/windows/Main.cpp @@ -1143,7 +1143,7 @@ LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) g_pLoadingMessage->Hide(); if (g_bFromStartup && GetLocalSettings()->GetStartMinimized()) { - GetFrontend()->MinimizeWindow(); + GetFrontend()->HideWindow(); } break; case WM_CONNECTING: { @@ -1179,7 +1179,7 @@ LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) if (GetLocalSettings()->GetMinimizeToNotif()) { - GetFrontend()->MinimizeWindow(); + GetFrontend()->HideWindow(); return 1; } break; @@ -1190,6 +1190,16 @@ LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) // Save the new size GetLocalSettings()->SetWindowSize(UnscaleByDPI(width), UnscaleByDPI(height)); + switch (wParam) + { + case SIZE_MAXIMIZED: + GetLocalSettings()->SetMaximized(true); + break; + case SIZE_RESTORED: + GetLocalSettings()->SetMaximized(false); + break; + } + ProfilePopout::Dismiss(); ProperlySizeControls(hWnd); break; @@ -1492,7 +1502,12 @@ LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) break; } case WM_RESTORE: + bool wasMaximized = GetLocalSettings()->GetMaximized(); + GetFrontend()->RestoreWindow(); + + if (wasMaximized) + GetFrontend()->MaximizeWindow(); break; } @@ -1675,7 +1690,7 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR pCmdLin int wndWidth = 0, wndHeight = 0; bool startMaximized = false; GetLocalSettings()->GetWindowSize(wndWidth, wndHeight); - startMaximized = GetLocalSettings()->GetStartMaximized(); + startMaximized = GetLocalSettings()->GetStartMaximized() || GetLocalSettings()->GetMaximized(); // Initialize the window class. WNDCLASS& wc = g_MainWindowClass; diff --git a/src/windows/ShellNotification.cpp b/src/windows/ShellNotification.cpp index 410be9a..9c21f86 100644 --- a/src/windows/ShellNotification.cpp +++ b/src/windows/ShellNotification.cpp @@ -241,7 +241,7 @@ void ShellNotification::Callback(WPARAM wParam, LPARAM lParam) } case WM_LBUTTONUP: - GetFrontend()->RestoreWindow(); + SendMessage(g_Hwnd, WM_RESTORE, 0, 0); break; case WM_RBUTTONUP: From 2c65ea3fe2a5a8a509eed139a1a38a07c1273af2 Mon Sep 17 00:00:00 2001 From: KnockKnockP Date: Sat, 29 Jun 2024 18:12:20 +0900 Subject: [PATCH 08/12] Merge logic. --- src/windows/Main.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/windows/Main.cpp b/src/windows/Main.cpp index 6f120eb..53607ba 100644 --- a/src/windows/Main.cpp +++ b/src/windows/Main.cpp @@ -1502,12 +1502,10 @@ LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) break; } case WM_RESTORE: - bool wasMaximized = GetLocalSettings()->GetMaximized(); - - GetFrontend()->RestoreWindow(); - - if (wasMaximized) + if (GetLocalSettings()->GetMaximized()) GetFrontend()->MaximizeWindow(); + else + GetFrontend()->RestoreWindow(); break; } From 9d11260b33d2421e158ee7ab36fe1e6a75971078 Mon Sep 17 00:00:00 2001 From: KnockKnockP Date: Sat, 29 Jun 2024 20:22:19 +0900 Subject: [PATCH 09/12] Fix warnings. --- src/windows/Main.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/windows/Main.cpp b/src/windows/Main.cpp index 53607ba..c00967b 100644 --- a/src/windows/Main.cpp +++ b/src/windows/Main.cpp @@ -637,8 +637,8 @@ void ResetTryAgainInTime() { g_tryAgainTimerElapse = 500; } -const LPTSTR g_tStartupArg = TEXT(" --startup"); -const LPSTR g_StartupArg = "--startup"; +const TCHAR g_tStartupArg[] = TEXT(" --startup"); +const CHAR g_StartupArg[] = "--startup"; bool g_bFromStartup = false; From 46d2b83b4ca55383270093966d58360f93d470b4 Mon Sep 17 00:00:00 2001 From: KnockKnockP Date: Sun, 30 Jun 2024 04:07:06 +0900 Subject: [PATCH 10/12] Code review. --- src/discord/LocalSettings.cpp | 6 +++--- src/windows/Main.cpp | 17 ++++------------- src/windows/ShellNotification.cpp | 2 +- src/windows/WindowMessages.hpp | 2 +- 4 files changed, 9 insertions(+), 18 deletions(-) diff --git a/src/discord/LocalSettings.cpp b/src/discord/LocalSettings.cpp index 3921736..0371acc 100644 --- a/src/discord/LocalSettings.cpp +++ b/src/discord/LocalSettings.cpp @@ -80,8 +80,8 @@ bool LocalSettings::Load() if (j.contains("MinimizeToNotif")) m_bMinimizeToNotif = j["MinimizeToNotif"]; - if (j.contains("m_bMaximized")) - m_bMinimizeToNotif = j["m_bMaximized"]; + if (j.contains("Maximized")) + m_bMaximized = j["Maximized"]; if (j.contains("EnableTLSVerification")) m_bEnableTLSVerification = j["EnableTLSVerification"]; @@ -167,7 +167,7 @@ bool LocalSettings::Save() j["OpenOnStartup"] = m_bOpenOnStartup; j["StartMinimized"] = m_bStartMinimized; j["MinimizeToNotif"] = m_bMinimizeToNotif; - j["m_bMaximized"] = m_bMaximized; + j["Maximized"] = m_bMaximized; j["CheckUpdates"] = m_bCheckUpdates; j["EnableTLSVerification"] = m_bEnableTLSVerification; j["DisableFormatting"] = m_bDisableFormatting; diff --git a/src/windows/Main.cpp b/src/windows/Main.cpp index c00967b..a1e2e2c 100644 --- a/src/windows/Main.cpp +++ b/src/windows/Main.cpp @@ -606,7 +606,7 @@ BOOL HandleCommand(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) break; } case ID_NOTIFICATION_SHOW: - SendMessage(g_Hwnd, WM_RESTORE, 0, 0); + SendMessage(g_Hwnd, WM_RESTOREAPP, 0, 0); break; case ID_NOTIFICATION_EXIT: SendMessage(g_Hwnd, WM_CLOSEBYPASSTRAY, 0, 0); @@ -1189,16 +1189,7 @@ LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) int height = HIWORD(lParam); // Save the new size GetLocalSettings()->SetWindowSize(UnscaleByDPI(width), UnscaleByDPI(height)); - - switch (wParam) - { - case SIZE_MAXIMIZED: - GetLocalSettings()->SetMaximized(true); - break; - case SIZE_RESTORED: - GetLocalSettings()->SetMaximized(false); - break; - } + GetLocalSettings()->SetMaximized(wParam == SIZE_MAXIMIZED); ProfilePopout::Dismiss(); ProperlySizeControls(hWnd); @@ -1501,7 +1492,7 @@ LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) GetShellNotification()->Callback(wParam, lParam); break; } - case WM_RESTORE: + case WM_RESTOREAPP: if (GetLocalSettings()->GetMaximized()) GetFrontend()->MaximizeWindow(); else @@ -1652,7 +1643,7 @@ static bool ForceSingleInstance(LPCWSTR pClassName) HWND hWnd = FindWindow(pClassName, NULL); if (hWnd) { - SendMessage(hWnd, WM_RESTORE, 0, 0); + SendMessage(hWnd, WM_RESTOREAPP, 0, 0); } return false; } diff --git a/src/windows/ShellNotification.cpp b/src/windows/ShellNotification.cpp index 9c21f86..16d9e50 100644 --- a/src/windows/ShellNotification.cpp +++ b/src/windows/ShellNotification.cpp @@ -241,7 +241,7 @@ void ShellNotification::Callback(WPARAM wParam, LPARAM lParam) } case WM_LBUTTONUP: - SendMessage(g_Hwnd, WM_RESTORE, 0, 0); + SendMessage(g_Hwnd, WM_RESTOREAPP, 0, 0); break; case WM_RBUTTONUP: diff --git a/src/windows/WindowMessages.hpp b/src/windows/WindowMessages.hpp index cd3aa35..dcaef10 100644 --- a/src/windows/WindowMessages.hpp +++ b/src/windows/WindowMessages.hpp @@ -68,5 +68,5 @@ enum eWmUserMsgs WM_CLOSEBYPASSTRAY, WM_UPDATETEXTSIZE = WM_APP, // used by the MessageEditor - WM_RESTORE, + WM_RESTOREAPP, }; From a88aabd3b25f63787391500c2455cf9d9999a1e9 Mon Sep 17 00:00:00 2001 From: KnockKnockP Date: Sun, 30 Jun 2024 19:41:48 +0900 Subject: [PATCH 11/12] Use std::string. --- src/windows/Main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/windows/Main.cpp b/src/windows/Main.cpp index a1e2e2c..234fee3 100644 --- a/src/windows/Main.cpp +++ b/src/windows/Main.cpp @@ -659,7 +659,7 @@ void AddOrRemoveAppFromStartup() TCHAR tPath[MAX_PATH]; const DWORD length = GetModuleFileName(NULL, tPath, MAX_PATH); - const std::string sPath = "\"" + MakeStringFromTString(tPath) + "\"" + MakeStringFromTString(g_tStartupArg); + const std::string sPath = "\"" + MakeStringFromTString(tPath) + "\"" + std::string(g_StartupArg); const LPTSTR finalPath = ConvertCppStringToTString(sPath); RegSetValueEx(hkey, value, 0, REG_SZ, (BYTE *)finalPath, (wcslen(finalPath) + 1) * sizeof(TCHAR)); From 923e0112532d2598c389ab91f3886083f140337e Mon Sep 17 00:00:00 2001 From: iProgramInCpp Date: Fri, 5 Jul 2024 12:15:46 +0300 Subject: [PATCH 12/12] * Fix bad startup command being added to the run registry key. * Don't show the main window on startup. * Don't take focus to the main message box when the channel is switched if the window is not active. * Change `--startup` to `/startup`. --- src/windows/LoadingMessage.cpp | 2 +- src/windows/Main.cpp | 16 ++++++++++------ src/windows/ShellNotification.cpp | 4 ++++ src/windows/WinUtils.cpp | 5 +++++ src/windows/WinUtils.hpp | 1 + 5 files changed, 21 insertions(+), 7 deletions(-) diff --git a/src/windows/LoadingMessage.cpp b/src/windows/LoadingMessage.cpp index 4938f35..99091b2 100644 --- a/src/windows/LoadingMessage.cpp +++ b/src/windows/LoadingMessage.cpp @@ -46,7 +46,7 @@ void LoadingMessage::Show() if (!m_hwnd) { CreateWnd(); ShowWindow(m_hwnd, SW_SHOWNORMAL); - SetFocus(m_hwnd); + SetActiveWindow(m_hwnd); } } diff --git a/src/windows/Main.cpp b/src/windows/Main.cpp index 234fee3..980a821 100644 --- a/src/windows/Main.cpp +++ b/src/windows/Main.cpp @@ -637,8 +637,7 @@ void ResetTryAgainInTime() { g_tryAgainTimerElapse = 500; } -const TCHAR g_tStartupArg[] = TEXT(" --startup"); -const CHAR g_StartupArg[] = "--startup"; +const CHAR g_StartupArg[] = "/startup"; bool g_bFromStartup = false; @@ -659,7 +658,7 @@ void AddOrRemoveAppFromStartup() TCHAR tPath[MAX_PATH]; const DWORD length = GetModuleFileName(NULL, tPath, MAX_PATH); - const std::string sPath = "\"" + MakeStringFromTString(tPath) + "\"" + std::string(g_StartupArg); + const std::string sPath = "\"" + MakeStringFromTString(tPath) + "\" " + std::string(g_StartupArg); const LPTSTR finalPath = ConvertCppStringToTString(sPath); RegSetValueEx(hkey, value, 0, REG_SZ, (BYTE *)finalPath, (wcslen(finalPath) + 1) * sizeof(TCHAR)); @@ -791,7 +790,9 @@ LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) g_pMessageList->UpdateAllowDrop(); UpdateMainWindowTitle(hWnd); - SetFocus(g_pMessageEditor->m_edit_hwnd); + + if (IsWindowActive(g_Hwnd)) + SetFocus(g_pMessageEditor->m_edit_hwnd); if (!GetDiscordInstance()->GetCurrentChannel()) { @@ -1147,7 +1148,8 @@ LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) } break; case WM_CONNECTING: { - g_pLoadingMessage->Show(); + if (!g_bFromStartup || !GetLocalSettings()->GetStartMinimized()) + g_pLoadingMessage->Show(); break; } case WM_LOGINAGAIN: @@ -1745,7 +1747,9 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR pCmdLin TextToSpeech::Initialize(); // Run the message loop. - ShowWindow (g_Hwnd, startMaximized ? SW_SHOWMAXIMIZED : nShowCmd); + + if (!g_bFromStartup || !GetLocalSettings()->GetStartMinimized()) + ShowWindow (g_Hwnd, startMaximized ? SW_SHOWMAXIMIZED : nShowCmd); while (GetMessage(&msg, NULL, 0, 0) > 0) { diff --git a/src/windows/ShellNotification.cpp b/src/windows/ShellNotification.cpp index 16d9e50..aed7939 100644 --- a/src/windows/ShellNotification.cpp +++ b/src/windows/ShellNotification.cpp @@ -237,6 +237,10 @@ void ShellNotification::Callback(WPARAM wParam, LPARAM lParam) { // TODO: Don't know how to know which one we clicked DbgPrintW("Acknowledge Notification"); + + ShowWindow(g_Hwnd, SW_SHOW); + SetActiveWindow(g_Hwnd); + break; } diff --git a/src/windows/WinUtils.cpp b/src/windows/WinUtils.cpp index 0af3f1a..f4f169c 100644 --- a/src/windows/WinUtils.cpp +++ b/src/windows/WinUtils.cpp @@ -133,6 +133,11 @@ void WindowScrollXY(HWND hWnd, int diffLeftRight, int diffUpDown) UpdateWindow(hWnd); } +bool IsWindowActive(HWND hWnd) +{ + return IsWindowVisible(hWnd) && GetForegroundWindow() == hWnd; +} + bool FileExists(const std::string& path) { #ifdef OLD_WINDOWS diff --git a/src/windows/WinUtils.hpp b/src/windows/WinUtils.hpp index 08dd552..9995ed4 100644 --- a/src/windows/WinUtils.hpp +++ b/src/windows/WinUtils.hpp @@ -49,6 +49,7 @@ std::string GetStringFromHResult(HRESULT hr); LPTSTR GetTStringFromHResult(HRESULT hr); // Window utils +bool IsWindowActive(HWND hWnd); void WindowScroll(HWND hWnd, int diffUpDown); void WindowScrollXY(HWND hWnd, int diffLeftRight, int diffUpDown); void DrawBitmap(HDC hdc, HBITMAP bitmap, int x, int y, LPRECT clip = NULL, COLORREF transparent = CLR_NONE, int scaleToWidth = 0, int scaleToHeight = 0, bool hasAlpha = false);