diff --git a/deps/mwas b/deps/mwas index 1663c311..0a12a0d6 160000 --- a/deps/mwas +++ b/deps/mwas @@ -1 +1 @@ -Subproject commit 1663c311589a3391a7b33d7cd776eb752a10a971 +Subproject commit 0a12a0d619af90854e52109bb08d0c41e94c57cb diff --git a/res/icons/icon_channel_dark.ico b/res/icons/icon_channel_dark.ico new file mode 100644 index 00000000..e844ce1a Binary files /dev/null and b/res/icons/icon_channel_dark.ico differ diff --git a/res/icons/icon_channel_dark_2k.ico b/res/icons/icon_channel_dark_2k.ico new file mode 100644 index 00000000..da730369 Binary files /dev/null and b/res/icons/icon_channel_dark_2k.ico differ diff --git a/res/icons/icon_channel_mentioned_dark.ico b/res/icons/icon_channel_mentioned_dark.ico new file mode 100644 index 00000000..1f63c88d Binary files /dev/null and b/res/icons/icon_channel_mentioned_dark.ico differ diff --git a/res/icons/icon_channel_mentioned_dark_2k.ico b/res/icons/icon_channel_mentioned_dark_2k.ico new file mode 100644 index 00000000..f8e72386 Binary files /dev/null and b/res/icons/icon_channel_mentioned_dark_2k.ico differ diff --git a/res/icons/icon_channel_unread_dark.ico b/res/icons/icon_channel_unread_dark.ico new file mode 100644 index 00000000..051eed52 Binary files /dev/null and b/res/icons/icon_channel_unread_dark.ico differ diff --git a/res/icons/icon_channel_unread_dark_2k.ico b/res/icons/icon_channel_unread_dark_2k.ico new file mode 100644 index 00000000..902ce14d Binary files /dev/null and b/res/icons/icon_channel_unread_dark_2k.ico differ diff --git a/res/icons/icon_dm_dark.ico b/res/icons/icon_dm_dark.ico new file mode 100644 index 00000000..3f20a78d Binary files /dev/null and b/res/icons/icon_dm_dark.ico differ diff --git a/res/icons/icon_dm_dark_2k.ico b/res/icons/icon_dm_dark_2k.ico new file mode 100644 index 00000000..a265576d Binary files /dev/null and b/res/icons/icon_dm_dark_2k.ico differ diff --git a/res/icons/icon_groupdm_dark.ico b/res/icons/icon_groupdm_dark.ico new file mode 100644 index 00000000..118ed8f3 Binary files /dev/null and b/res/icons/icon_groupdm_dark.ico differ diff --git a/res/icons/icon_groupdm_dark_2k.ico b/res/icons/icon_groupdm_dark_2k.ico new file mode 100644 index 00000000..3f863748 Binary files /dev/null and b/res/icons/icon_groupdm_dark_2k.ico differ diff --git a/res/icons/icon_voice_dark.ico b/res/icons/icon_voice_dark.ico new file mode 100644 index 00000000..ae7d1f0c Binary files /dev/null and b/res/icons/icon_voice_dark.ico differ diff --git a/res/icons/icon_voice_dark_2k.ico b/res/icons/icon_voice_dark_2k.ico new file mode 100644 index 00000000..331be883 Binary files /dev/null and b/res/icons/icon_voice_dark_2k.ico differ diff --git a/src/core/config/LocalSettings.cpp b/src/core/config/LocalSettings.cpp index 095d6885..1b261e99 100644 --- a/src/core/config/LocalSettings.cpp +++ b/src/core/config/LocalSettings.cpp @@ -163,6 +163,10 @@ bool LocalSettings::Load() if (j.contains("AddExtraHeaders")) m_bAddExtraHeaders = j["AddExtraHeaders"]; + + if (j.contains("EnableDarkMode")) + m_bEnableDarkMode = j["EnableDarkMode"]; + return true; } @@ -203,6 +207,7 @@ bool LocalSettings::Save() j["Use12HourTime"] = m_bUse12HourTime; j["ShowBlockedMessages"] = m_bShowBlockedMessages; j["UseDoubleBuffering"] = m_bUseDoubleBuffering; + j["EnableDarkMode"] = m_bEnableDarkMode; if (m_bSaveWindowSize) { j["WindowWidth"] = m_width; diff --git a/src/core/config/LocalSettings.hpp b/src/core/config/LocalSettings.hpp index cd4364ea..d4e18be1 100644 --- a/src/core/config/LocalSettings.hpp +++ b/src/core/config/LocalSettings.hpp @@ -226,6 +226,12 @@ class LocalSettings void SetUseDoubleBuffering(bool b) { m_bUseDoubleBuffering = b; } + bool EnableDarkMode() const { + return m_bEnableDarkMode; + } + void SetEnableDarkMode(bool b) { + m_bEnableDarkMode = b; + } private: std::string m_token; @@ -258,6 +264,7 @@ class LocalSettings bool m_bUse12HourTime = false; bool m_bShowBlockedMessages = false; bool m_bUseDoubleBuffering = false; + bool m_bEnableDarkMode = false; time_t m_remindUpdatesOn = 0; int m_width = 1000; int m_height = 700; diff --git a/src/resource.h b/src/resource.h index 1e54e0dc..fbd473d0 100644 --- a/src/resource.h +++ b/src/resource.h @@ -105,6 +105,18 @@ #define IDR_LINK_CONTEXT 104 #define IDI_PROFILE_BORDER_UNREAD_2K 105 #define IDR_IMAGE_CONTEXT 105 +#define IDI_CHANNEL_DARK 106 +#define IDI_DM_DARK 107 +#define IDI_GROUPDM_DARK 108 +#define IDI_VOICE_DARK 109 +#define IDI_CHANNEL_MENTIONED_DARK 110 +#define IDI_CHANNEL_UNREAD_DARK 111 +#define IDI_CHANNEL_DARK_2K 112 +#define IDI_DM_DARK_2K 113 +#define IDI_GROUPDM_DARK_2K 114 +#define IDI_VOICE_DARK_2K 115 +#define IDI_CHANNEL_MENTIONED_DARK_2K 116 +#define IDI_CHANNEL_UNREAD_DARK_2K 117 #define IDB_TARGET 200 #define IDB_CHANNEL 201 #define IDB_CATEGORY 202 @@ -338,6 +350,9 @@ #define IDS_CONFIRM_UNPIN 776 #define IDS_CONFIRM_UNPIN_TITLE 777 #define IDS_ETA_STRING_DOWNLOADED 778 +#define IDS_FAILED_TO_LOAD_CONFIG_1 779 +#define IDS_FAILED_TO_LOAD_CONFIG_2 780 +#define IDS_FAILED_TO_LOAD_CONFIG_RECOVERED_TOKEN 781 #define IDC_OPTIONS_TABS 801 #define IDC_MY_ACCOUNT_BOX 802 #define IDC_MY_ACCOUNT_NAME 803 @@ -436,6 +451,7 @@ #define IDC_USE_12HR_TIME 897 #define IDC_ENABLE_BALLOON_NOTIFS 898 #define IDC_SHOW_BLOCKED_MESSAGES 898 +#define IDC_DARK_MODE 898 #define IDC_FLASH_TASKBAR 899 #define IDC_USE_DISCORD_SOUND 900 #define IDC_MUTE_NOTIFICATIONS 901 diff --git a/src/resource.rc b/src/resource.rc index 61d13933..79f2e1ee 100644 --- a/src/resource.rc +++ b/src/resource.rc @@ -458,6 +458,30 @@ IDI_PROFILE_BORDER_UNREAD ICON "../res/icons/icon_profile_bor IDI_PROFILE_BORDER_UNREAD_2K ICON "../res/icons/icon_profile_border_unread_2k.ico" +IDI_CHANNEL_DARK ICON "../res/icons/icon_channel_dark.ico" + +IDI_DM_DARK ICON "../res/icons/icon_dm_dark.ico" + +IDI_GROUPDM_DARK ICON "../res/icons/icon_groupdm_dark.ico" + +IDI_VOICE_DARK ICON "../res/icons/icon_voice_dark.ico" + +IDI_CHANNEL_MENTIONED_DARK ICON "../res/icons/icon_channel_mentioned_dark.ico" + +IDI_CHANNEL_UNREAD_DARK ICON "../res/icons/icon_channel_unread_dark.ico" + +IDI_CHANNEL_DARK_2K ICON "../res/icons/icon_channel_dark_2k.ico" + +IDI_DM_DARK_2K ICON "../res/icons/icon_dm_dark_2k.ico" + +IDI_GROUPDM_DARK_2K ICON "../res/icons/icon_groupdm_dark_2k.ico" + +IDI_VOICE_DARK_2K ICON "../res/icons/icon_voice_dark_2k.ico" + +IDI_CHANNEL_MENTIONED_DARK_2K ICON "../res/icons/icon_channel_mentioned_dark_2k.ico" + +IDI_CHANNEL_UNREAD_DARK_2K ICON "../res/icons/icon_channel_unread_dark_2k.ico" + ///////////////////////////////////////////////////////////////////////////// // @@ -519,21 +543,22 @@ BEGIN "Button",BS_AUTORADIOBUTTON | WS_GROUP,12,18,236,10 CONTROL "Compact: Fit more messages on screen at one time. #IRC",IDC_APPEARANCE_COMPACT, "Button",BS_AUTORADIOBUTTON,12,30,236,10 - GROUPBOX "Message List Style",IDC_MSTYLE_BOX,6,105,248,29 - LTEXT "Message theme:",IDC_STATIC,12,116,53,13,SS_CENTERIMAGE - PUSHBUTTON "Change...",IDC_ACTIVE_IMAGE_BROWSE,198,146,50,14 - EDITTEXT IDC_ACTIVE_IMAGE_EDIT,53,146,135,14,ES_AUTOHSCROLL | ES_READONLY - LTEXT "Image:",IDC_STATIC,12,146,41,14,SS_CENTERIMAGE - COMBOBOX IDC_MESSAGE_STYLE,73,116,175,128,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + GROUPBOX "Message List Style",IDC_MSTYLE_BOX,6,120,248,29 + LTEXT "Message theme:",IDC_STATIC,12,131,53,13,SS_CENTERIMAGE + PUSHBUTTON "Change...",IDC_ACTIVE_IMAGE_BROWSE,198,161,50,14 + EDITTEXT IDC_ACTIVE_IMAGE_EDIT,53,161,135,14,ES_AUTOHSCROLL | ES_READONLY + LTEXT "Image:",IDC_STATIC,12,161,41,14,SS_CENTERIMAGE + COMBOBOX IDC_MESSAGE_STYLE,73,131,175,128,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP CONTROL "Compact member list",IDC_COMPACT_MEMBER_LIST,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,60,236,10 - COMBOBOX IDC_COMBO_ALIGNMENT,53,164,195,78,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - LTEXT "Aligned to:",IDC_STATIC,12,164,41,12,SS_CENTERIMAGE - GROUPBOX "Message List Watermark",IDC_STATIC,6,135,248,48 - GROUPBOX "User Interface",IDC_STATIC,6,48,248,56 - LTEXT "Size of UI elements:",IDC_STATIC,12,86,68,12,SS_CENTERIMAGE - COMBOBOX IDC_COMBO_GUI_SCALE,80,86,168,159,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + COMBOBOX IDC_COMBO_ALIGNMENT,53,179,195,78,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + LTEXT "Aligned to:",IDC_STATIC,12,179,41,12,SS_CENTERIMAGE + GROUPBOX "Message List Watermark",IDC_STATIC,6,150,248,48 + GROUPBOX "User Interface",IDC_STATIC,6,48,248,69 + LTEXT "Size of UI elements:",IDC_STATIC,12,100,68,12,SS_CENTERIMAGE + COMBOBOX IDC_COMBO_GUI_SCALE,80,100,168,159,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP CONTROL "Double-buffer drawing (reduces flicker but uses more memory)",IDC_DOUBLE_BUFFERING, "Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,74,236,10 + CONTROL "Enable dark mode",IDC_DARK_MODE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,88,236,10 END IDD_DIALOG_PROFILE_POPOUT DIALOGEX 0, 0, 126, 134 @@ -869,19 +894,19 @@ BEGIN LISTBOX IDC_GUILD_LIST,7,19,271,158,LBS_SORT | LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP END -IDD_DIALOG_PREFERENCES_ND DIALOG 0, 0, 231, 308 +IDD_DIALOG_PREFERENCES_ND DIALOG 0, 0, 269, 294 STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "Preferences" FONT 8, "MS Shell Dlg" BEGIN - PUSHBUTTON "Done",IDOK,174,287,50,14 - GROUPBOX "My Account",IDC_STATIC,7,7,218,36 - GROUPBOX "Appearance",IDC_STATIC,7,45,218,77 + PUSHBUTTON "Done",IDOK,212,273,50,14 + GROUPBOX "My Account",IDC_STATIC,7,7,255,36 + GROUPBOX "Appearance",IDC_STATIC,7,46,255,87 LTEXT "Static",IDC_MY_ACCOUNT_NAME,52,17,135,8 LTEXT "Username:",IDC_STATIC,12,17,36,8 LTEXT "*****@*****.***",IDC_EMAIL_DISPLAY,52,29,114,8 LTEXT "Email:",IDC_STATIC,12,29,20,8 - PUSHBUTTON "Reveal",IDC_REVEALEMAIL,169,26,50,14 + PUSHBUTTON "Reveal",IDC_REVEALEMAIL,208,26,50,14 CONTROL "Cozy",IDC_APPEARANCE_COZY,"Button",BS_AUTORADIOBUTTON,80,56,32,10 CONTROL "Compact",IDC_APPEARANCE_COMPACT,"Button",BS_AUTORADIOBUTTON,114,56,44,10 COMBOBOX IDC_MESSAGE_STYLE,80,70,137,30,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP @@ -892,24 +917,25 @@ BEGIN PUSHBUTTON "Change...",IDC_ACTIVE_IMAGE_BROWSE,169,86,50,14 LTEXT "Aligned to:",IDC_STATIC,12,105,65,8 COMBOBOX IDC_COMBO_ALIGNMENT,80,104,137,30,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP - GROUPBOX "Chat",IDC_STATIC,7,123,218,76 + GROUPBOX "Chat",IDC_STATIC,7,134,255,52 CONTROL "Disable markdown formatting",IDC_DISABLE_FORMATTING, - "Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,134,205,10 + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,147,107,10 CONTROL "Display images when uploaded directly to Discord",IDC_IMAGES_WHEN_UPLOADED, - "Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,147,205,10 + "Button",BS_AUTOCHECKBOX | BS_MULTILINE | WS_TABSTOP,151,147,104,17 CONTROL "Display images when posted as links in chat",IDC_IMAGES_WHEN_EMBEDDED, - "Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,160,205,10 + "Button",BS_AUTOCHECKBOX | BS_MULTILINE | WS_TABSTOP,151,165,104,19 CONTROL "Show embeds and preview links in chat",IDC_SHOW_EMBEDS, - "Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,173,205,10 - GROUPBOX "Window",IDC_STATIC,7,200,218,38 - CONTROL "Save window size",IDC_SAVE_WINDOW_SIZE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,211,203,10 - CONTROL "Start maximized",IDC_START_MAXIMIZED,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,224,203,10 - GROUPBOX "Check for updates",IDC_STATIC,7,240,218,44 + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,160,137,10 + GROUPBOX "Window",IDC_STATIC,7,186,255,38 + CONTROL "Save window size",IDC_SAVE_WINDOW_SIZE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,197,203,10 + CONTROL "Start maximized",IDC_START_MAXIMIZED,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,210,203,10 + GROUPBOX "Check for updates",IDC_STATIC,7,226,255,44 CONTROL "Check for updates using the GitHub API",IDC_CHECK_UPDATES, - "Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,251,203,10 - LTEXT "iProgramInCpp cannot see your IP address through the update service.",IDC_STATIC,12,263,204,17 - LTEXT "Changes apply automatically.",IDC_STATIC,7,289,163,8 - CONTROL "Use 12-hour time",IDC_USE_12HR_TIME,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,186,205,10 + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,237,203,10 + LTEXT "iProgramInCpp cannot see your IP address through the update service.",IDC_STATIC,12,249,204,17 + LTEXT "Changes apply automatically.",IDC_STATIC,7,275,163,8 + CONTROL "Use 12-hour time",IDC_USE_12HR_TIME,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,173,136,10 + CONTROL "Enable dark mode",IDC_DARK_MODE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,119,136,10 END @@ -1148,9 +1174,9 @@ BEGIN IDD_DIALOG_PREFERENCES_ND, DIALOG BEGIN LEFTMARGIN, 7 - RIGHTMARGIN, 224 + RIGHTMARGIN, 262 TOPMARGIN, 7 - BOTTOMMARGIN, 301 + BOTTOMMARGIN, 287 END END #endif // APSTUDIO_INVOKED @@ -1717,6 +1743,12 @@ BEGIN IDS_CONFIRM_UNPIN "You sure you want to remove this pinned message?\n\n%s (%s)\n\n%s" IDS_CONFIRM_UNPIN_TITLE "Discord Messenger - Unpin Message" IDS_ETA_STRING_DOWNLOADED "(%s (%s downloaded)" + IDS_FAILED_TO_LOAD_CONFIG_1 + "Discord Messenger failed to load your configuration. You will need to re-insert your Discord token.\n\nTechnical details:\n" + IDS_FAILED_TO_LOAD_CONFIG_2 + "\n\nThe corrupted settings file is located at:\n" + IDS_FAILED_TO_LOAD_CONFIG_RECOVERED_TOKEN + "Discord Messenger failed to load your configuration. A Discord token was successfully recovered from the corrupted config file, and will be used to attempt to log in, but it might be wrong.\n\nTechnical details:\n" END #endif // English (United States) resources diff --git a/src/windows/AutoComplete.cpp b/src/windows/AutoComplete.cpp index 8afc2034..74561e37 100644 --- a/src/windows/AutoComplete.cpp +++ b/src/windows/AutoComplete.cpp @@ -331,7 +331,7 @@ bool AutoComplete::InitializeClass() WNDCLASS wc; ZeroMemory(&wc, sizeof wc); wc.lpszClassName = T_AUTOCOMPLETE_CLASS; - wc.hbrBackground = ri::GetSysColorBrush(COLOR_3DFACE); + wc.hbrBackground = GetSysColorBrushV2(COLOR_3DFACE); wc.style = 0; wc.hCursor = LoadCursor (0, IDC_ARROW); wc.lpfnWndProc = AutoComplete::WndProc; @@ -506,16 +506,16 @@ LRESULT AutoComplete::HandleCustomDraw(HWND hWnd, NMLVCUSTOMDRAW* pInfo) int sta = ListView_GetItemState(hList, idx, LVIS_SELECTED); if (sta & LVIS_SELECTED) { - pInfo->clrTextBk = GetSysColor(COLOR_HIGHLIGHT); - pInfo->clrText = GetSysColor(COLOR_HIGHLIGHTTEXT); + pInfo->clrTextBk = GetSysColorV2(COLOR_HIGHLIGHT); + pInfo->clrText = GetSysColorV2(COLOR_HIGHLIGHTTEXT); } else if (pInfo->iSubItem == COL_SUBNAME) { - pInfo->clrTextBk = GetSysColor(COLOR_WINDOW); - pInfo->clrText = GetSysColor(COLOR_GRAYTEXT); + pInfo->clrTextBk = GetSysColorV2(COLOR_WINDOW); + pInfo->clrText = GetSysColorV2(COLOR_GRAYTEXT); } else { - pInfo->clrTextBk = GetSysColor(COLOR_WINDOW); - pInfo->clrText = GetSysColor(COLOR_MENUTEXT); + pInfo->clrTextBk = GetSysColorV2(COLOR_WINDOW); + pInfo->clrText = GetSysColorV2(COLOR_MENUTEXT); } return CDRF_NEWFONT; diff --git a/src/windows/ChannelView.cpp b/src/windows/ChannelView.cpp index 46bb249b..06023692 100644 --- a/src/windows/ChannelView.cpp +++ b/src/windows/ChannelView.cpp @@ -63,13 +63,13 @@ bool ChannelView::InitTreeView() // Add the open file, closed file, and document bitmaps. m_nCategoryExpandIcon = ri::ImageList_AddIcon(himl, LoadIcon(g_hInstance, MAKEINTRESOURCE(DMIC(IDI_CATEGORY_EXPAND)))); m_nCategoryCollapseIcon = ri::ImageList_AddIcon(himl, LoadIcon(g_hInstance, MAKEINTRESOURCE(DMIC(IDI_CATEGORY_COLLAPSE)))); - m_nChannelIcon = ri::ImageList_AddIcon(himl, LoadIcon(g_hInstance, MAKEINTRESOURCE(DMIC(IDI_CHANNEL)))); - m_nForumIcon = ri::ImageList_AddIcon(himl, LoadIcon(g_hInstance, MAKEINTRESOURCE(DMIC(IDI_GROUPDM)))); - m_nVoiceIcon = ri::ImageList_AddIcon(himl, LoadIcon(g_hInstance, MAKEINTRESOURCE(DMIC(IDI_VOICE)))); - m_nDmIcon = ri::ImageList_AddIcon(himl, LoadIcon(g_hInstance, MAKEINTRESOURCE(DMIC(IDI_DM)))); - m_nGroupDmIcon = ri::ImageList_AddIcon(himl, LoadIcon(g_hInstance, MAKEINTRESOURCE(DMIC(IDI_GROUPDM)))); - m_nChannelDotIcon = ri::ImageList_AddIcon(himl, LoadIcon(g_hInstance, MAKEINTRESOURCE(DMIC(IDI_CHANNEL_UNREAD)))); - m_nChannelRedIcon = ri::ImageList_AddIcon(himl, LoadIcon(g_hInstance, MAKEINTRESOURCE(DMIC(IDI_CHANNEL_MENTIONED)))); + m_nChannelIcon = ri::ImageList_AddIcon(himl, LoadIcon(g_hInstance, MAKEINTRESOURCE(DMIC(DMV(IDI_CHANNEL))))); + m_nForumIcon = ri::ImageList_AddIcon(himl, LoadIcon(g_hInstance, MAKEINTRESOURCE(DMIC(DMV(IDI_GROUPDM))))); + m_nVoiceIcon = ri::ImageList_AddIcon(himl, LoadIcon(g_hInstance, MAKEINTRESOURCE(DMIC(DMV(IDI_VOICE))))); + m_nDmIcon = ri::ImageList_AddIcon(himl, LoadIcon(g_hInstance, MAKEINTRESOURCE(DMIC(DMV(IDI_DM))))); + m_nGroupDmIcon = ri::ImageList_AddIcon(himl, LoadIcon(g_hInstance, MAKEINTRESOURCE(DMIC(DMV(IDI_GROUPDM))))); + m_nChannelDotIcon = ri::ImageList_AddIcon(himl, LoadIcon(g_hInstance, MAKEINTRESOURCE(DMIC(DMV(IDI_CHANNEL_UNREAD))))); + m_nChannelRedIcon = ri::ImageList_AddIcon(himl, LoadIcon(g_hInstance, MAKEINTRESOURCE(DMIC(DMV(IDI_CHANNEL_MENTIONED))))); // Fail if not all of the images were added. int ic = ri::ImageList_GetImageCount(himl); @@ -85,6 +85,11 @@ bool ChannelView::InitTreeView() SetWindowFont(hwndTV, g_MessageTextFont, TRUE); + if (IsDarkModeEnabled()) { + TreeView_SetBkColor(m_treeHwnd, GetSysColorV2(COLOR_WINDOW)); + TreeView_SetTextColor(m_treeHwnd, GetSysColorV2(COLOR_WINDOWTEXT)); + } + return TRUE; } @@ -109,6 +114,11 @@ bool ChannelView::InitListView() SetWindowFont(m_listHwnd, g_MessageTextFont, TRUE); + if (IsDarkModeEnabled()) { + TreeView_SetBkColor(m_listHwnd, GetSysColorV2(COLOR_WINDOW)); + TreeView_SetTextColor(m_listHwnd, GetSysColorV2(COLOR_WINDOWTEXT)); + } + return TRUE; } @@ -494,6 +504,8 @@ ChannelView* ChannelView::Create(HWND hwnd, LPRECT rect) view = NULL; } + view->SetMode(false); + return view; } @@ -509,7 +521,7 @@ void ChannelView::InitializeClass() WNDCLASS& wc = g_ChannelViewClass; wc.lpszClassName = T_CHANNEL_VIEW_CONTAINER_CLASS; - wc.hbrBackground = ri::GetSysColorBrush(COLOR_3DFACE); + wc.hbrBackground = GetSysColorBrushV2(COLOR_3DFACE); wc.style = 0; wc.hCursor = LoadCursor(0, IDC_ARROW); wc.lpfnWndProc = &ChannelView::WndProc; @@ -691,27 +703,27 @@ LRESULT ChannelView::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) ChannelMember* pMember = &pView->m_channels[lpdis->itemID]; Channel* pChan = GetDiscordInstance()->GetChannel(pMember->m_snowflake); - COLORREF nameTextColor = GetSysColor(COLOR_WINDOWTEXT); - COLORREF statusTextColor = GetSysColor(COLOR_GRAYTEXT); - COLORREF backgdColor = GetSysColor(COLOR_WINDOW); + COLORREF nameTextColor = GetSysColorV2(COLOR_WINDOWTEXT); + COLORREF statusTextColor = GetSysColorV2(COLOR_GRAYTEXT); + COLORREF backgdColor = GetSysColorV2(COLOR_WINDOW); if (pView->m_hotItem == lpdis->itemID) { - FillRect(lpdis->hDC, &lpdis->rcItem, ri::GetSysColorBrush(COLOR_MENUBAR)); - backgdColor = GetSysColor(COLOR_MENUBAR); + FillRect(lpdis->hDC, &lpdis->rcItem, GetSysColorBrushV2(COLOR_MENUBAR)); + backgdColor = GetSysColorV2(COLOR_MENUBAR); } else { // Windows 2000 doesn't do automatic clearing - FillRect(lpdis->hDC, &lpdis->rcItem, ri::GetSysColorBrush(COLOR_WINDOW)); + FillRect(lpdis->hDC, &lpdis->rcItem, GetSysColorBrushV2(COLOR_WINDOW)); } if (lpdis->itemState & ODS_SELECTED) { - FillRect(lpdis->hDC, &lpdis->rcItem, ri::GetSysColorBrush(COLOR_HIGHLIGHT)); - backgdColor = GetSysColor(COLOR_HIGHLIGHT); - nameTextColor = GetSysColor(COLOR_HIGHLIGHTTEXT); - statusTextColor = GetSysColor(COLOR_HIGHLIGHTTEXT); + FillRect(lpdis->hDC, &lpdis->rcItem, GetSysColorBrushV2(COLOR_HIGHLIGHT)); + backgdColor = GetSysColorV2(COLOR_HIGHLIGHT); + nameTextColor = GetSysColorV2(COLOR_HIGHLIGHTTEXT); + statusTextColor = GetSysColorV2(COLOR_HIGHLIGHTTEXT); } // draw profile picture frame @@ -806,20 +818,20 @@ LRESULT ChannelView::ListWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPa switch (uMsg) { - case WM_DESTROY: - { - SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR)NULL); - SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)pView->m_origListWndProc); - pView->m_listHwnd = NULL; - break; - } - case WM_MOUSELEAVE: - { - int oldItem = pView->m_hotItem; - pView->m_hotItem = -1; - ListView_RedrawItems(hWnd, oldItem, oldItem); - break; - } + case WM_DESTROY: + { + SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR)NULL); + SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)pView->m_origListWndProc); + pView->m_listHwnd = NULL; + break; + } + case WM_MOUSELEAVE: + { + int oldItem = pView->m_hotItem; + pView->m_hotItem = -1; + ListView_RedrawItems(hWnd, oldItem, oldItem); + break; + } } return CallWindowProc(pView->m_origListWndProc, hWnd, uMsg, wParam, lParam); diff --git a/src/windows/ChannelViewOld.cpp b/src/windows/ChannelViewOld.cpp index a64c97f8..22225061 100644 --- a/src/windows/ChannelViewOld.cpp +++ b/src/windows/ChannelViewOld.cpp @@ -58,7 +58,7 @@ void ChannelViewOld::InitializeClass() WNDCLASS& wc = g_ChannelViewLegacyClass; wc.lpszClassName = T_CHANNEL_VIEW_CONTAINER_CLASS2; - wc.hbrBackground = ri::GetSysColorBrush(COLOR_3DFACE); + wc.hbrBackground = GetSysColorBrushV2(COLOR_3DFACE); wc.style = 0; wc.hCursor = LoadCursor(0, IDC_ARROW); wc.lpfnWndProc = &ChannelViewOld::WndProc; @@ -251,6 +251,16 @@ LRESULT ChannelViewOld::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPar GetDiscordInstance()->OnSelectChannel(sf); break; } + + case WM_CTLCOLORLISTBOX: + { + HDC hdc = (HDC)wParam; + + SetBkColor(hdc, GetSysColorV2(COLOR_WINDOW)); + SetTextColor(hdc, GetSysColorV2(COLOR_WINDOWTEXT)); + + return (LRESULT) GetSysColorBrushV2(COLOR_WINDOW); + } } return DefWindowProc( hWnd, uMsg, wParam, lParam ); diff --git a/src/windows/Frontend_Win32.cpp b/src/windows/Frontend_Win32.cpp index 11545d21..0fac1bd5 100644 --- a/src/windows/Frontend_Win32.cpp +++ b/src/windows/Frontend_Win32.cpp @@ -603,61 +603,6 @@ bool Frontend_Win32::UseGradientByDefault() return LOWORD(GetVersion()) >= 5; } -static std::string LoadEntireFile(const std::string& fileNameUTF8) -{ - LPTSTR fileNameUTF16 = ConvertCppStringToTString(fileNameUTF8); - HANDLE handle = CreateFile(fileNameUTF16, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); - free(fileNameUTF16); - - if (!handle) { - DbgPrintW("Failed to open %s: %d", fileNameUTF8.c_str(), GetLastError()); - return ""; - } - - DWORD fileSize = GetFileSize(handle, NULL); - if (fileSize > 10000000) { - DbgPrintW("Uh oh, file is too big!"); - CloseHandle(handle); - return ""; - } - - DWORD bytesRead = 0; - std::string data; - data.resize(fileSize); - ReadFile(handle, (void*) data.data(), fileSize, &bytesRead, NULL); - CloseHandle(handle); - - if (bytesRead != fileSize) { - DbgPrintW("We only read %zu bytes, out of %zu!", (size_t) bytesRead, (size_t) fileSize); - return ""; - } - - return data; -} - -static bool SaveEntireFile(const std::string& fileNameUTF8, const std::string& data) -{ - LPTSTR fileNameUTF16 = ConvertCppStringToTString(fileNameUTF8); - HANDLE handle = CreateFile(fileNameUTF16, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); - free(fileNameUTF16); - - if (!handle) { - DbgPrintW("Failed to save %s: %d", fileNameUTF8.c_str(), GetLastError()); - return false; - } - - DWORD bytesWritten = 0; - WriteFile(handle, (const void*)data.data(), (DWORD) data.size(), &bytesWritten, NULL); - CloseHandle(handle); - - if (bytesWritten != (DWORD) data.size()) { - DbgPrintW("We only wrote %zu bytes, out of %zu! Data may have been corrupted!", (size_t) bytesWritten, data.size()); - return false; - } - - return true; -} - std::string Frontend_Win32::LoadConfig() { std::string data = LoadEntireTextFile(GetBasePath() + "/settings.json"); diff --git a/src/windows/GuildHeader.cpp b/src/windows/GuildHeader.cpp index 627e97cb..6b037149 100644 --- a/src/windows/GuildHeader.cpp +++ b/src/windows/GuildHeader.cpp @@ -182,8 +182,8 @@ void GuildHeader::DrawButton(HDC hdc, Button& button) MoveToEx(hdc, 0, 0, &oldPt); const int clr = GUILD_HEADER_COLOR_2; - COLORREF clrA = LerpColor(RGB(255, 255, 255), GetSysColor(clr), 1, 2); - COLORREF clrB = LerpColor(RGB(0, 0, 0), GetSysColor(clr), 1, 2); + COLORREF clrA = LerpColor(RGB(255, 255, 255), GetSysColorV2(clr), 1, 2); + COLORREF clrB = LerpColor(RGB(0, 0, 0), GetSysColorV2(clr), 1, 2); RECT exp = { iconX - 4, iconY - 4, iconX + 4 + iconSize, iconY + 4 + iconSize }; exp.left = std::max(exp.left, button.m_rect.left); @@ -199,7 +199,7 @@ void GuildHeader::DrawButton(HDC hdc, Button& button) DeleteRgn(rgn); } else { - FillRect(hdc, &exp, ri::GetSysColorBrush(clr)); + FillRect(hdc, &exp, GetSysColorBrushV2(clr)); } if (button.m_held) { @@ -418,8 +418,8 @@ LRESULT CALLBACK GuildHeader::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA HDC hdc = BeginPaint(hWnd, &ps); - COLORREF old = SetBkColor(hdc, GetSysColor(GUILD_HEADER_COLOR)); - COLORREF oldText = SetTextColor(hdc, GetSysColor(COLOR_CAPTIONTEXT)); + COLORREF old = SetBkColor(hdc, GetSysColorV2(GUILD_HEADER_COLOR)); + COLORREF oldText = SetTextColor(hdc, GetSysColorV2(COLOR_CAPTIONTEXT)); pThis->Layout(); @@ -427,9 +427,9 @@ LRESULT CALLBACK GuildHeader::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA #if (WINVER>=0x0500) FillGradient(hdc, &pThis->m_rectLeftFull, GUILD_HEADER_COLOR, GUILD_HEADER_COLOR_2, false); FillGradient(hdc, &pThis->m_rectRightFull, GUILD_HEADER_COLOR_2, GUILD_HEADER_COLOR, false); - FillRect(hdc, &pThis->m_rectMidFull, ri::GetSysColorBrush(GUILD_HEADER_COLOR_2)); + FillRect(hdc, &pThis->m_rectMidFull, GetSysColorBrushV2(GUILD_HEADER_COLOR_2)); #else - FillRect(hdc, &pThis->m_rectFull, ri::GetSysColorBrush(GUILD_HEADER_COLOR)); + FillRect(hdc, &pThis->m_rectFull, GetSysColorBrushV2(GUILD_HEADER_COLOR)); #endif int old_mode = SetBkMode(hdc, TRANSPARENT); diff --git a/src/windows/GuildLister.cpp b/src/windows/GuildLister.cpp index 2c8d57e5..25eec5cb 100644 --- a/src/windows/GuildLister.cpp +++ b/src/windows/GuildLister.cpp @@ -523,7 +523,7 @@ void GuildLister::DrawServerIcon(HDC hdc, HBITMAP hicon, int& y, RECT& rect, Sno int pfpBorderSize2 = GetProfileBorderRenderSize(); - FillRect(hdc, &rcProfile, ri::GetSysColorBrush(GUILD_LISTER_COLOR)); + FillRect(hdc, &rcProfile, GetSysColorBrushV2(GUILD_LISTER_COLOR)); if (currentFolder) { HRGN hrgn = DoubleBufferingHelper::CreateRectRgn(hdc, rcProfile); @@ -535,8 +535,8 @@ void GuildLister::DrawServerIcon(HDC hdc, HBITMAP hicon, int& y, RECT& rect, Sno } HGDIOBJ oldBrush, oldPen; - oldBrush = SelectObject(hdc, ri::GetSysColorBrush(COLOR_BTNSHADOW)); - oldPen = SelectObject(hdc, GetStockObject(BLACK_PEN)); + oldBrush = SelectObject(hdc, GetSysColorBrushV2(COLOR_BTNSHADOW)); + oldPen = SelectObject(hdc, IsDarkModeEnabled() ? GetStockObject(WHITE_PEN) : GetStockObject(BLACK_PEN)); if (currentFolder == (id & ~BIT_FOLDER)) { RoundRect(hdc, rcProfile.left + 1, rcProfile.top + 1, rcProfile.right - 1, rcProfile.top - 1 + pfpBorderSize + amount, 10, 10); @@ -701,8 +701,8 @@ void GuildLister::Paint(HWND hWnd, HDC hdc, RECT& rcPaint) RECT rc = rect; rc.top += y; rc.bottom = rc.top + C_GUILD_GAP_HEIGHT; - FillRect(hdc, &rc, ri::GetSysColorBrush(GUILD_LISTER_COLOR)); - COLORREF oldPenColor = ri::SetDCPenColor(hdc, GetSysColor(COLOR_WINDOWTEXT)); + FillRect(hdc, &rc, GetSysColorBrushV2(GUILD_LISTER_COLOR)); + COLORREF oldPenColor = ri::SetDCPenColor(hdc, GetSysColorV2(COLOR_WINDOWTEXT)); HGDIOBJ oldobj = SelectObject(hdc, ri::GetDCPen()); POINT pt2; MoveToEx(hdc, rc.left + BORDER_SIZE, rc.top + BORDER_SIZE, &pt2); @@ -782,9 +782,9 @@ void GuildLister::Paint(HWND hWnd, HDC hdc, RECT& rcPaint) finalRect.top = y; //if (initialRect.top < initialRect.bottom) - // FillRect(hdc, &initialRect, ri::GetSysColorBrush(GUILD_LISTER_COLOR)); + // FillRect(hdc, &initialRect, GetSysColorBrushV2(GUILD_LISTER_COLOR)); //if (finalRect.top < finalRect.bottom) - // FillRect(hdc, &finalRect, ri::GetSysColorBrush(GUILD_LISTER_COLOR)); + // FillRect(hdc, &finalRect, GetSysColorBrushV2(GUILD_LISTER_COLOR)); MoveToEx(hdc, pt.x, pt.y, NULL); } @@ -1185,7 +1185,7 @@ LRESULT CALLBACK GuildLister::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA if (ShouldUseDoubleBuffering()) { DoubleBufferingHelper helper(hdc, paintRect); - FillRect(helper.HdcMem(), &paintRect, ri::GetSysColorBrush(GUILD_LISTER_COLOR)); + FillRect(helper.HdcMem(), &paintRect, GetSysColorBrushV2(GUILD_LISTER_COLOR)); pThis->Paint(hWnd, helper.HdcMem(), paintRect); } else @@ -1382,7 +1382,7 @@ void GuildLister::InitializeClass() WNDCLASS& wc = g_GuildListerClass; wc.lpszClassName = T_GUILD_LISTER_CLASS; - wc.hbrBackground = ri::GetSysColorBrush(GUILD_LISTER_COLOR); + wc.hbrBackground = GetSysColorBrushV2(GUILD_LISTER_COLOR); wc.style = 0; wc.hCursor = LoadCursor(0, IDC_ARROW); wc.lpfnWndProc = GuildLister::WndProc; @@ -1451,6 +1451,11 @@ GuildLister* GuildLister::Create(HWND hwnd, LPRECT pRect) } SetWindowPos(newThis->m_tooltip_hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); + + if (IsDarkModeEnabled()) { + ri::SetWindowTheme(newThis->m_more_btn_hwnd, L" ", L" "); + ri::SetWindowTheme(newThis->m_bar_btn_hwnd, L" ", L" "); + } return newThis; } diff --git a/src/windows/ImageViewer.cpp b/src/windows/ImageViewer.cpp index 8a3f396f..cb6b9f4d 100644 --- a/src/windows/ImageViewer.cpp +++ b/src/windows/ImageViewer.cpp @@ -287,7 +287,7 @@ LRESULT CALLBACK ImageViewerChildWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LP HImage* him = GetBitmap(); if (!him) { - COLORREF oldBk = SetBkColor(hdc, GetSysColor (COLOR_3DDKSHADOW)); + COLORREF oldBk = SetBkColor(hdc, GetSysColorV2 (COLOR_3DDKSHADOW)); COLORREF oldText = SetTextColor(hdc, RGB(255, 255, 255)); HGDIOBJ oldObject = SelectObject(hdc, g_MessageTextFont); @@ -491,7 +491,7 @@ bool RegisterImageViewerClass() wc.lpfnWndProc = ImageViewerWndProc; wc.hInstance = g_hInstance; wc.lpszClassName = DM_IMAGE_VIEWER_CLASS; - wc.hbrBackground = ri::GetSysColorBrush(COLOR_3DFACE); + wc.hbrBackground = GetSysColorBrushV2(COLOR_3DFACE); wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hIcon = g_Icon = LoadIcon(g_hInstance, MAKEINTRESOURCE(IDI_ICON)); @@ -501,7 +501,7 @@ bool RegisterImageViewerClass() wc2.lpfnWndProc = ImageViewerChildWndProc; wc2.hInstance = g_hInstance; wc2.lpszClassName = DM_IMAGE_VIEWER_CHILD_CLASS; - wc2.hbrBackground = ri::GetSysColorBrush(COLOR_3DDKSHADOW); + wc2.hbrBackground = GetSysColorBrushV2(COLOR_3DDKSHADOW); wc2.hCursor = LoadCursor(NULL, IDC_ARROW); wc2.hIcon = g_Icon = LoadIcon(g_hInstance, MAKEINTRESOURCE(IDI_ICON)); diff --git a/src/windows/LoadingMessage.cpp b/src/windows/LoadingMessage.cpp index d8c01428..7d796d2a 100644 --- a/src/windows/LoadingMessage.cpp +++ b/src/windows/LoadingMessage.cpp @@ -130,8 +130,8 @@ LRESULT CALLBACK LoadingMessage::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LP RECT textRect = rect; textRect.top += MulDiv(textRect.bottom - textRect.top, 3, 4); HGDIOBJ old = SelectObject(hdc, g_AuthorTextFont); - COLORREF oldClr = SetBkColor(hdc, GetSysColor(COLOR_3DFACE)); - COLORREF oldTClr = SetTextColor(hdc, GetSysColor(COLOR_WINDOWTEXT)); + COLORREF oldClr = SetBkColor(hdc, GetSysColorV2(COLOR_3DFACE)); + COLORREF oldTClr = SetTextColor(hdc, GetSysColorV2(COLOR_WINDOWTEXT)); DrawText(hdc, TEXT("Please wait, connecting to Discord..."), -1, &textRect, DT_CENTER); @@ -161,7 +161,7 @@ void LoadingMessage::InitializeClass() return; wc.lpszClassName = T_LOADING_MESSAGE_CLASS; - wc.hbrBackground = ri::GetSysColorBrush(COLOR_3DFACE); + wc.hbrBackground = GetSysColorBrushV2(COLOR_3DFACE); wc.style = CS_HREDRAW; wc.hCursor = LoadCursor(0, IDC_WAIT); wc.lpfnWndProc = LoadingMessage::WndProc; diff --git a/src/windows/Main.cpp b/src/windows/Main.cpp index f69fd4bd..4e07cdf4 100644 --- a/src/windows/Main.cpp +++ b/src/windows/Main.cpp @@ -1943,6 +1943,95 @@ static bool ForceSingleInstance(LPCTSTR pClassName) return false; } +static bool IsMaybeValidDiscordToken(const std::string& token) +{ + if (token.size() < 70) + return false; + + if (token.size() > 75) + return false; + + int periodCount = 0; + for (auto ch : token) + { + if (ch == '.') { + periodCount++; + } + + if (!((ch >= '0' && ch <= '9') || (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z') || ch == '_' || ch == '\'' || ch == '.')) { + return false; + } + } + + return periodCount == 2; +} + +static std::string PerformSettingsRecoveryOperations(bool& recoveredToken) +{ + recoveredToken = false; + + std::string settingsData = GetFrontend()->LoadConfig(); + + auto pos = settingsData.find("\"Token\":\""); + if (pos != std::string::npos) { + // Find the ending part + auto pos2 = settingsData.find("\"", pos + 9); + if (pos2 == std::string::npos) { + pos2 = settingsData.size(); + } + + std::string tokenExtracted = settingsData.substr(pos + 9, pos2 - pos - 9); + if (IsMaybeValidDiscordToken(tokenExtracted)) { + GetLocalSettings()->SetToken(tokenExtracted); + recoveredToken = true; + } + } + + std::string fn = GetBasePath() + "/bad_settings_" + std::to_string(time(NULL)) + ".json"; + if (SaveEntireFile(fn, settingsData)) + return fn; + + fn = GetBasePath() + "bs" + std::to_string(time(NULL) % 1000000) + ".jso"; + if (SaveEntireFile(fn, settingsData)) + return fn; + + return ""; +} + +static void LoadSettingsIfPossible() +{ + std::string technicalDetails; + + try + { + GetLocalSettings()->Load(); + return; + } + catch (nlohmann::json::exception ex) + { + technicalDetails = "JSON exception: " + std::string(ex.what()); + } + catch (std::exception ex) + { + technicalDetails = "Unknown exception: " + std::string(ex.what()); + } + + bool recoveredToken = false; + std::string oldPath = PerformSettingsRecoveryOperations(recoveredToken); + + std::string message = TmGetString(recoveredToken ? IDS_FAILED_TO_LOAD_CONFIG_RECOVERED_TOKEN : IDS_FAILED_TO_LOAD_CONFIG_1); + message += technicalDetails; + + if (!oldPath.empty()) { + message += TmGetString(IDS_FAILED_TO_LOAD_CONFIG_2); + message += oldPath; + } + + LPTSTR tstr = ConvertToTStringAddCR(message); + MessageBox(NULL, tstr, TmGetTString(IDS_PROGRAM_NAME), MB_ICONERROR | MB_OK); + free(tstr); +} + // Blackwingcat's Extended Kernel workaround: Apparently, the custom user32.dll it uses tries // to write to the class name, which previously was part of .rodata, which is of course read-only. TCHAR g_className[64]; @@ -1977,9 +2066,6 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR pCmdLin g_pFrontEnd = new Frontend_Win32; g_pHTTPClient = new NetworkerThreadManager; - // Create a background brush. - g_backgroundBrush = ri::GetSysColorBrush(COLOR_3DFACE); - SetupCachePathIfNeeded(); LocalSettings* pSettings = GetLocalSettings(); @@ -1987,7 +2073,7 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR pCmdLin // Load the settings, and fix up some settings that are // actually bad to leave on on NT 3.x or NT 4 - pSettings->Load(); + LoadSettingsIfPossible(); if (LOBYTE(version) < 5 && pSettings->GetMessageStyle() == MS_GRADIENT) { @@ -2012,8 +2098,17 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR pCmdLin pSettings->SetUseDoubleBuffering(false); } + if (IsDarkModeEnabled()) + { + // disable theming, as classic controls are easier to theme + //ri::SetThemeAppProperties(ri_STAP_ALLOW_NONCLIENT); + } + SetUserScale(GetLocalSettings()->GetUserScale()); + // Create a background brush. + g_backgroundBrush = GetSysColorBrushV2(COLOR_3DFACE); + int wndWidth = 0, wndHeight = 0; bool startMaximized = false; GetLocalSettings()->GetWindowSize(wndWidth, wndHeight); diff --git a/src/windows/MemberList.cpp b/src/windows/MemberList.cpp index c734a483..4d39f251 100644 --- a/src/windows/MemberList.cpp +++ b/src/windows/MemberList.cpp @@ -270,6 +270,11 @@ void MemberList::Initialize() ListView_InsertColumn(m_listHwnd, 0, &col); SetWindowFont(m_listHwnd, g_MessageTextFont, TRUE); + + if (IsDarkModeEnabled()) { + ListView_SetBkColor(m_listHwnd, GetSysColorV2(COLOR_WINDOW)); + ListView_SetTextColor(m_listHwnd, GetSysColorV2(COLOR_WINDOWTEXT)); + } } LRESULT MemberList::ListWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) @@ -365,30 +370,30 @@ LRESULT MemberList::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) Profile* pf = GetProfileCache()->LookupProfile(user, "", "", "", false); COLORREF nameTextColor = 0; - COLORREF statusTextColor = GetSysColor(COLOR_GRAYTEXT); - COLORREF backgdColor = GetSysColor(COLOR_WINDOW); + COLORREF statusTextColor = GetSysColorV2(COLOR_GRAYTEXT); + COLORREF backgdColor = GetSysColorV2(COLOR_WINDOW); nameTextColor = GetNameColor(pf, pList->m_guild); if (nameTextColor == CLR_NONE) - nameTextColor = GetSysColor(COLOR_WINDOWTEXT); + nameTextColor = GetSysColorV2(COLOR_WINDOWTEXT); if (pList->m_hotItem == lpdis->itemID) { - FillRect(lpdis->hDC, &lpdis->rcItem, ri::GetSysColorBrush(COLOR_MENUBAR)); - backgdColor = GetSysColor(COLOR_MENUBAR); + FillRect(lpdis->hDC, &lpdis->rcItem, GetSysColorBrushV2(COLOR_MENUBAR)); + backgdColor = GetSysColorV2(COLOR_MENUBAR); } else { // Windows 2000 doesn't do automatic clearing - FillRect(lpdis->hDC, &lpdis->rcItem, ri::GetSysColorBrush(COLOR_WINDOW)); + FillRect(lpdis->hDC, &lpdis->rcItem, GetSysColorBrushV2(COLOR_WINDOW)); } if (lpdis->itemState & ODS_SELECTED) { - FillRect(lpdis->hDC, &lpdis->rcItem, ri::GetSysColorBrush(COLOR_HIGHLIGHT)); - backgdColor = GetSysColor(COLOR_HIGHLIGHT); - nameTextColor = GetSysColor(COLOR_HIGHLIGHTTEXT); - statusTextColor = GetSysColor(COLOR_HIGHLIGHTTEXT); + FillRect(lpdis->hDC, &lpdis->rcItem, GetSysColorBrushV2(COLOR_HIGHLIGHT)); + backgdColor = GetSysColorV2(COLOR_HIGHLIGHT); + nameTextColor = GetSysColorV2(COLOR_HIGHLIGHTTEXT); + statusTextColor = GetSysColorV2(COLOR_HIGHLIGHTTEXT); } int textOffset = 0; @@ -541,7 +546,7 @@ void MemberList::InitializeClass() WNDCLASS& wc = g_MemberListClass; wc.lpszClassName = T_MEMBER_LIST_CLASS; - wc.hbrBackground = ri::GetSysColorBrush(COLOR_3DFACE); + wc.hbrBackground = GetSysColorBrushV2(COLOR_3DFACE); wc.style = 0; wc.hCursor = LoadCursor(0, IDC_ARROW); wc.lpfnWndProc = &MemberList::WndProc; diff --git a/src/windows/MemberListOld.cpp b/src/windows/MemberListOld.cpp index 88e6ae06..2f39e502 100644 --- a/src/windows/MemberListOld.cpp +++ b/src/windows/MemberListOld.cpp @@ -59,7 +59,7 @@ void MemberListOld::InitializeClass() WNDCLASS& wc = g_memberListOldClass; wc.lpszClassName = T_MEMBER_LIST_CLASS_OLD; - wc.hbrBackground = ri::GetSysColorBrush(COLOR_3DFACE); + wc.hbrBackground = GetSysColorBrushV2(COLOR_3DFACE); wc.style = 0; wc.hCursor = LoadCursor(0, IDC_ARROW); wc.lpfnWndProc = &MemberListOld::WndProc; @@ -198,6 +198,15 @@ LRESULT MemberListOld::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPara MoveWindow(pList->m_listHwnd, 0, 0, wWidth, wHeight, TRUE); break; } + + case WM_CTLCOLORLISTBOX: { + HDC hdc = (HDC)wParam; + + SetBkColor(hdc, GetSysColorV2(COLOR_WINDOW)); + SetTextColor(hdc, GetSysColorV2(COLOR_WINDOWTEXT)); + + return (LRESULT)GetSysColorBrushV2(COLOR_WINDOW); + } } return DefWindowProc(hWnd, uMsg, wParam, lParam); diff --git a/src/windows/MessageEditor.cpp b/src/windows/MessageEditor.cpp index 7a7e9b0b..2ac66a07 100644 --- a/src/windows/MessageEditor.cpp +++ b/src/windows/MessageEditor.cpp @@ -289,7 +289,7 @@ void MessageEditor::StartReply(Snowflake messageID, Snowflake authorID) } if (clr == CLR_NONE) - clr = GetSysColor(COLOR_WINDOWTEXT); + clr = GetSysColorV2(COLOR_WINDOWTEXT); m_userNameColor = clr; } @@ -870,9 +870,20 @@ LRESULT MessageEditor::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPara { if ((HWND) lParam == pThis->m_mentionName_hwnd) SetTextColor((HDC) wParam, pThis->m_userNameColor); + else + SetTextColor((HDC) wParam, GetSysColorV2(COLOR_WINDOWTEXT)); - SetBkColor((HDC) wParam, GetSysColor(COLOR_3DFACE)); - return (LRESULT)ri::GetSysColorBrush(COLOR_3DFACE); + SetBkColor((HDC) wParam, GetSysColorV2(COLOR_3DFACE)); + return (LRESULT)GetSysColorBrushV2(COLOR_3DFACE); + } + case WM_CTLCOLOREDIT: + { + HDC hdc = (HDC)wParam; + + SetTextColor(hdc, GetSysColorV2(COLOR_WINDOWTEXT)); + SetBkColor(hdc, GetSysColorV2(COLOR_WINDOW)); + + return (LRESULT) GetSysColorBrushV2(COLOR_WINDOW); } } @@ -884,7 +895,7 @@ void MessageEditor::InitializeClass() WNDCLASS wc; ZeroMemory(&wc, sizeof wc); wc.lpszClassName = T_MESSAGE_EDITOR_CLASS; - wc.hbrBackground = ri::GetSysColorBrush(COLOR_3DFACE); + wc.hbrBackground = GetSysColorBrushV2(COLOR_3DFACE); wc.style = 0; wc.hCursor = LoadCursor (0, IDC_ARROW); wc.lpfnWndProc = MessageEditor::WndProc; @@ -1028,5 +1039,12 @@ MessageEditor* MessageEditor::Create(HWND hwnd, LPRECT pRect) newThis->m_autoComplete.SetLookup(&_AutoCompleteLookup); newThis->m_autoComplete.SetLookupContext(newThis); + if (IsDarkModeEnabled()) { + ri::SetWindowTheme(newThis->m_send_hwnd, L" ", L" "); + ri::SetWindowTheme(newThis->m_btnUpload_hwnd, L" ", L" "); + ri::SetWindowTheme(newThis->m_mentionJump_hwnd, L" ", L" "); + ri::SetWindowTheme(newThis->m_mentionCancel_hwnd, L" ", L" "); + } + return newThis; } diff --git a/src/windows/MessageList.cpp b/src/windows/MessageList.cpp index 5158be4a..b68e76c7 100644 --- a/src/windows/MessageList.cpp +++ b/src/windows/MessageList.cpp @@ -59,7 +59,7 @@ static const int g_WelcomeTextCount = _countof(g_WelcomeTextIds); MessageList::MessageList() { - m_defaultBackgroundBrush = ri::GetSysColorBrush(COLOR_WINDOW); + m_defaultBackgroundBrush = GetSysColorBrushV2(COLOR_WINDOW); // This ugly hack allows me to calculate the offset between GMT and // local time. This is used when calculating date gaps. @@ -277,7 +277,7 @@ void RichEmbedItem::Draw(HDC hdc, RECT& messageRect, MessageList* pList) rcGradient.left += ScaleByDPI(4); COLORREF oldColor = SetBkColor(hdc, pList->GetDarkerBackgroundColor()); if (GetLocalSettings()->GetMessageStyle() == MS_GRADIENT) { - FillGradientColors(hdc, &rcGradient, GetSysColor(COLOR_WINDOWFRAME), CLR_NONE, true); + FillGradientColors(hdc, &rcGradient, GetSysColorV2(COLOR_WINDOWFRAME), CLR_NONE, true); } else { COLORREF oldClr = ri::SetDCBrushColor(hdc, pList->GetDarkerBackgroundColor()); @@ -299,7 +299,7 @@ void RichEmbedItem::Draw(HDC hdc, RECT& messageRect, MessageList* pList) rc.right -= borderSize; rc.bottom -= borderSize; HGDIOBJ oldObj = SelectObject(hdc, GetStockFont(ANSI_VAR_FONT)); - COLORREF windowTextColor = pList->InvertIfNeeded(GetSysColor(COLOR_WINDOWTEXT)); + COLORREF windowTextColor = pList->InvertIfNeeded(GetSysColorV2(COLOR_WINDOWTEXT)); if (m_providerSize.cy) { SelectObject(hdc, g_ReplyTextFont); @@ -1537,7 +1537,7 @@ void MessageList::DrawDefaultAttachment(HDC hdc, RECT& paintRect, AttachmentItem if (attachItem.m_bHighlighted && inView) old = SetTextColor(hdc, RGB(0, 0, 255)); else - old = SetTextColor(hdc, GetSysColor(COLOR_WINDOWTEXT)); + old = SetTextColor(hdc, GetSysColorV2(COLOR_WINDOWTEXT)); LPCTSTR name = attachItem.m_nameText; RECT rcMeasure; @@ -1558,7 +1558,7 @@ void MessageList::DrawDefaultAttachment(HDC hdc, RECT& paintRect, AttachmentItem if (inView) { - ri::DrawEdge(hdc, &childAttachRect, BDR_RAISEDINNER | BDR_RAISEDOUTER, BF_RECT | BF_MIDDLE); + DrawEdgeV2(hdc, &childAttachRect, BDR_RAISEDINNER | BDR_RAISEDOUTER, BF_RECT | BF_MIDDLE); DrawText(hdc, name, -1, &textRect, DT_NOPREFIX | DT_NOCLIP); ri::DrawIconEx( hdc, @@ -1575,7 +1575,7 @@ void MessageList::DrawDefaultAttachment(HDC hdc, RECT& paintRect, AttachmentItem attachItem.m_textRect = textRect; - uint32_t oc = SetTextColor(hdc, GetSysColor(COLOR_WINDOWTEXT)); + uint32_t oc = SetTextColor(hdc, GetSysColorV2(COLOR_WINDOWTEXT)); if (old == CLR_NONE) old = oc; @@ -1991,7 +1991,7 @@ void MessageList::DrawReplyPieceIcon(HDC hdc, int leftX, int topY) return; } - HPEN hpen = CreatePen(PS_SOLID, 3, InvertIfNeeded(GetSysColor(COLOR_WINDOWTEXT))); + HPEN hpen = CreatePen(PS_SOLID, 3, InvertIfNeeded(GetSysColorV2(COLOR_WINDOWTEXT))); HGDIOBJ old = SelectObject(hdc, hpen); POINT ptold = {}; @@ -2092,7 +2092,7 @@ int MessageList::DrawMessageReply(HDC hdc, MessageItem& item, RECT& rc) } if (nameClr == CLR_NONE) - nameClr = InvertIfNeeded(GetSysColor(COLOR_WINDOWTEXT)); + nameClr = InvertIfNeeded(GetSysColorV2(COLOR_WINDOWTEXT)); LPCTSTR strPart1 = TEXT(""); LPCTSTR strPart2 = NULL; @@ -2133,7 +2133,7 @@ int MessageList::DrawMessageReply(HDC hdc, MessageItem& item, RECT& rc) } // Draw the text - COLORREF old = SetTextColor(hdc, GetSysColor(COLOR_GRAYTEXT)); + COLORREF old = SetTextColor(hdc, GetSysColorV2(COLOR_GRAYTEXT)); SelectObject(hdc, g_ReplyTextFont); RECT rcMeasure{}; @@ -2155,7 +2155,7 @@ int MessageList::DrawMessageReply(HDC hdc, MessageItem& item, RECT& rc) if (!isActionMessage) rcReply.left += ScaleByDPI(5); - SetTextColor(hdc, GetSysColor(COLOR_GRAYTEXT)); + SetTextColor(hdc, GetSysColorV2(COLOR_GRAYTEXT)); if (STRAVAILABLE(strPart2)) { @@ -2230,9 +2230,9 @@ void MessageList::DrawMessage(HDC hdc, MessageItem& item, RECT& msgRect, RECT& c bool isFlashed = (m_emphasizedMessage == item.m_msg->m_snowflake) && (m_flash_counter % 2 != 0); - COLORREF chosenTextColor = GetSysColor(COLOR_WINDOWTEXT); + COLORREF chosenTextColor = GetSysColorV2(COLOR_WINDOWTEXT); if (item.m_msg->m_bRead) - chosenTextColor = GetSysColor(COLOR_3DSHADOW); + chosenTextColor = GetSysColorV2(COLOR_3DSHADOW); COLORREF textColor = InvertIfNeeded(chosenTextColor), bkgdColor = CLR_NONE; @@ -2260,7 +2260,7 @@ void MessageList::DrawMessage(HDC hdc, MessageItem& item, RECT& msgRect, RECT& c LPTSTR strDateGap = ConvertCppStringToTString(" " + item.m_msg->m_dateOnly + " "); - COLORREF clrText = InvertIfNeeded(bDrawNewMarker ? NEW_MARKER_COLOR : GetSysColor(COLOR_GRAYTEXT)); + COLORREF clrText = InvertIfNeeded(bDrawNewMarker ? NEW_MARKER_COLOR : GetSysColorV2(COLOR_GRAYTEXT)); COLORREF oldTextClr = SetTextColor(hdc, clrText); COLORREF oldPenClr = ri::SetDCPenColor(hdc, clrText); @@ -2270,13 +2270,13 @@ void MessageList::DrawMessage(HDC hdc, MessageItem& item, RECT& msgRect, RECT& c if (mStyle == MS_FLATBR) clr = COLOR_WINDOW; else if (mStyle == MS_GRADIENT) { COLORREF c1, c2; - c1 = GetSysColor(COLOR_WINDOW); // high - c2 = GetSysColor(COLOR_3DFACE); // low + c1 = GetSysColorV2(COLOR_WINDOW); // high + c2 = GetSysColorV2(COLOR_3DFACE); // low if (c1 < c2) clr = COLOR_3DFACE; else clr = COLOR_WINDOW; } - FillRect(hdc, &dgRect, ri::GetSysColorBrush(clr)); + FillRect(hdc, &dgRect, GetSysColorBrushV2(clr)); } else { @@ -2339,27 +2339,27 @@ void MessageList::DrawMessage(HDC hdc, MessageItem& item, RECT& msgRect, RECT& c else rect2.top -= 4; if (!isFlashed) - bkgdColor = GetSysColor(COLOR_3DFACE); + bkgdColor = GetSysColorV2(COLOR_3DFACE); if (item.m_msg->m_type != MessageType::CHANNEL_HEADER) { - ri::DrawEdge(hdc, &rect2, BDR_RAISED, edgeFlags); + DrawEdgeV2(hdc, &rect2, BDR_RAISED, edgeFlags); } else if (edgeFlags & BF_MIDDLE) { - FillRect(hdc, &rect2, ri::GetSysColorBrush(COLOR_3DFACE)); + FillRect(hdc, &rect2, GetSysColorBrushV2(COLOR_3DFACE)); } break; } case MS_FLAT: { if (!isFlashed) { - bkgdColor = GetSysColor(COLOR_3DFACE); - FillRect(hdc, &msgRect, ri::GetSysColorBrush(COLOR_3DFACE)); + bkgdColor = GetSysColorV2(COLOR_3DFACE); + FillRect(hdc, &msgRect, GetSysColorBrushV2(COLOR_3DFACE)); } break; } case MS_FLATBR: { if (!isFlashed) { - bkgdColor = GetSysColor(COLOR_WINDOW); - FillRect(hdc, &msgRect, ri::GetSysColorBrush(COLOR_WINDOW)); + bkgdColor = GetSysColorV2(COLOR_WINDOW); + FillRect(hdc, &msgRect, GetSysColorBrushV2(COLOR_WINDOW)); } break; } @@ -2369,8 +2369,8 @@ void MessageList::DrawMessage(HDC hdc, MessageItem& item, RECT& msgRect, RECT& c break; COLORREF c1, c2; - c1 = GetSysColor(COLOR_WINDOW); // high - c2 = GetSysColor(COLOR_3DFACE); // low + c1 = GetSysColorV2(COLOR_WINDOW); // high + c2 = GetSysColorV2(COLOR_3DFACE); // low bool swapped = false; if (c1 < c2) { @@ -2392,7 +2392,7 @@ void MessageList::DrawMessage(HDC hdc, MessageItem& item, RECT& msgRect, RECT& c if (isChainCont) { // Just render a flat background using the bottom color - FillRect(hdc, &msgRect, ri::GetSysColorBrush(swapped ? COLOR_WINDOW : COLOR_3DFACE)); + FillRect(hdc, &msgRect, GetSysColorBrushV2(swapped ? COLOR_WINDOW : COLOR_3DFACE)); break; } @@ -2779,7 +2779,7 @@ void MessageList::DrawMessage(HDC hdc, MessageItem& item, RECT& msgRect, RECT& c if (item.m_msg->m_type == MessageType::UNSENT_MESSAGE) oldTextColor = SetTextColor(hdc, RGB(255, 0, 0)); else if (item.m_msg->m_type == MessageType::SENDING_MESSAGE) - oldTextColor = SetTextColor(hdc, GetSysColor(COLOR_GRAYTEXT)); + oldTextColor = SetTextColor(hdc, GetSysColorV2(COLOR_GRAYTEXT)); item.m_message.Draw(&mddc, offsetY); @@ -2788,7 +2788,7 @@ void MessageList::DrawMessage(HDC hdc, MessageItem& item, RECT& msgRect, RECT& c if (oldTextColor != CLR_NONE) SetTextColor(hdc, oldTextColor); - COLORREF windowTextColor = InvertIfNeeded(GetSysColor(COLOR_WINDOWTEXT)); + COLORREF windowTextColor = InvertIfNeeded(GetSysColorV2(COLOR_WINDOWTEXT)); for (size_t i = 0; i < item.m_interactableData.size(); i++) { InteractableItem& iitem = item.m_interactableData[i]; @@ -3132,11 +3132,11 @@ void MessageList::Paint(HDC hdc, RECT& paintRect) case MS_GRADIENT: { oldBkMode = SetBkMode(hdc, TRANSPARENT); oldBkModeSet = true; - chosenBkColor = GetSysColor(COLOR_3DFACE); + chosenBkColor = GetSysColorV2(COLOR_3DFACE); break; } case MS_FLATBR: { - chosenBkColor = GetSysColor(COLOR_WINDOW); + chosenBkColor = GetSysColorV2(COLOR_WINDOW); oldBkColor = SetBkColor(hdc, chosenBkColor); break; } @@ -3147,7 +3147,7 @@ void MessageList::Paint(HDC hdc, RECT& paintRect) break; } default: { - chosenBkColor = GetSysColor(COLOR_3DFACE); + chosenBkColor = GetSysColorV2(COLOR_3DFACE); oldBkColor = SetBkColor(hdc, chosenBkColor); break; } @@ -3155,7 +3155,7 @@ void MessageList::Paint(HDC hdc, RECT& paintRect) DrawingContext mddc(hdc); mddc.SetBackgroundColor(chosenBkColor); - mddc.SetInvertTextColor(InvertIfNeeded(GetSysColor(COLOR_WINDOWTEXT))); + mddc.SetInvertTextColor(InvertIfNeeded(GetSysColorV2(COLOR_WINDOWTEXT))); Snowflake lastDrawnMessage = 0; Snowflake lastKnownMessage = 0; @@ -4140,7 +4140,7 @@ void MessageList::InitializeClass() WNDCLASS& wc = g_MsgListClass; wc.lpszClassName = T_MESSAGE_LIST_CLASS; - wc.hbrBackground = ri::GetSysColorBrush(COLOR_3DFACE); + wc.hbrBackground = GetSysColorBrushV2(COLOR_3DFACE); wc.style = 0; wc.lpfnWndProc = MessageList::WndProc; wc.hCursor = LoadCursor(0, IDC_ARROW); @@ -4164,7 +4164,7 @@ void MessageList::UpdateBackgroundBrush() if (mode == MS_IMAGE) SetClassLongPtr(m_hwnd, GCLP_HBRBACKGROUND, (LONG_PTR) m_backgroundBrush); else - SetClassLongPtr(m_hwnd, GCLP_HBRBACKGROUND, (LONG_PTR) ri::GetSysColorBrush(bru)); + SetClassLongPtr(m_hwnd, GCLP_HBRBACKGROUND, (LONG_PTR) GetSysColorBrushV2(bru)); } bool MessageList::SendToMessage(Snowflake sf, bool requestIfNeeded, bool forceInvalidate) @@ -4457,8 +4457,8 @@ void MessageList::ReloadBackground() if (m_bBackgroundHasAlpha) { - m_backgroundColor = GetSysColor(COLOR_WINDOW); - m_backgroundBrush = ri::GetSysColorBrush(COLOR_WINDOW); + m_backgroundColor = GetSysColorV2(COLOR_WINDOW); + m_backgroundBrush = GetSysColorBrushV2(COLOR_WINDOW); m_bDontDeleteBackgroundBrush = true; } else @@ -4486,7 +4486,7 @@ void MessageList::ReloadBackground() m_bDontDeleteBackgroundBrush = false; } - m_bInvertTextColors = IsColorDark(m_backgroundColor) ^ (!IsColorDark(GetSysColor(COLOR_WINDOWTEXT))); + m_bInvertTextColors = IsColorDark(m_backgroundColor) ^ (!IsColorDark(GetSysColorV2(COLOR_WINDOWTEXT))); } void MessageList::UnloadBackground() @@ -4554,9 +4554,9 @@ COLORREF MessageList::GetDarkerBackgroundColor() const if (style == MS_IMAGE) bgColor = m_backgroundColor; else if (style == MS_FLATBR) - bgColor = GetSysColor(COLOR_WINDOW); + bgColor = GetSysColorV2(COLOR_WINDOW); else - bgColor = GetSysColor(COLOR_3DFACE); + bgColor = GetSysColorV2(COLOR_3DFACE); COLORREF hint = IsColorDark(bgColor) ? 0xFFFFFF : 0x000000; @@ -5372,7 +5372,7 @@ void MessagePollData::Draw(HDC hdc, RECT& messageRect, MessageList* pList) rcPoll.right = rcPoll.left + m_width; rcPoll.bottom = rcPoll.top + m_height; rcPoll2 = rcPoll; - ri::DrawEdge(hdc, &rcPoll2, EDGE_RAISED, BF_RECT); + DrawEdgeV2(hdc, &rcPoll2, EDGE_RAISED, BF_RECT); rcPoll.left += borderSize; rcPoll.top += borderSize; diff --git a/src/windows/OptionsDialog.cpp b/src/windows/OptionsDialog.cpp index 16556e2a..b5f83069 100644 --- a/src/windows/OptionsDialog.cpp +++ b/src/windows/OptionsDialog.cpp @@ -160,6 +160,7 @@ void OptionsInitPage(HWND hwndDlg, int pageNum) GetSettingsManager()->GetMessageCompact() ? IDC_APPEARANCE_COMPACT : IDC_APPEARANCE_COZY ); + CheckDlgButton(hwndDlg, IDC_DARK_MODE, GetLocalSettings()->EnableDarkMode() ? BST_CHECKED : BST_UNCHECKED); CheckDlgButton(hwndDlg, IDC_DOUBLE_BUFFERING, GetLocalSettings()->UseDoubleBuffering() ? BST_CHECKED : BST_UNCHECKED); if (ShouldBlockDoubleBuffering()) { @@ -493,6 +494,10 @@ INT_PTR OptionsHandleCommand(HWND hwndParent, HWND hWnd, int pageNum, UINT uMsg, case IDC_DOUBLE_BUFFERING: GetLocalSettings()->SetUseDoubleBuffering(IsDlgButtonChecked(hWnd, IDC_DOUBLE_BUFFERING)); break; + case IDC_DARK_MODE: + GetLocalSettings()->SetEnableDarkMode(IsDlgButtonChecked(hWnd, IDC_DARK_MODE)); + SendMessage(g_Hwnd, WM_FORCERESTART, 0, 0); + break; } break; } diff --git a/src/windows/ProfilePopout.cpp b/src/windows/ProfilePopout.cpp index 76d61bf0..a65f53c8 100644 --- a/src/windows/ProfilePopout.cpp +++ b/src/windows/ProfilePopout.cpp @@ -329,7 +329,7 @@ bool ProfilePopout::Layout(HWND hWnd, SIZE& fullSize) HBITMAP hnewbm = ResizeWithBackgroundColor( hdc, hbm, - ri::GetSysColorBrush(COLOR_3DFACE), + GetSysColorBrushV2(COLOR_3DFACE), hasAlpha, joinedAtIconSize, joinedAtIconSize, @@ -464,8 +464,7 @@ void ProfilePopout::Paint(HWND hWnd, HDC hdc) { RECT rect = {}; GetClientRect(hWnd, &rect); - - ri::DrawEdge(hdc, &rect, EDGE_RAISED, BF_RECT | BF_MIDDLE); + DrawEdgeV2(hdc, &rect, EDGE_RAISED, BF_RECT | BF_MIDDLE); } void ProfilePopout::FlushNote() @@ -513,6 +512,14 @@ INT_PTR CALLBACK ProfilePopout::Proc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM case WM_INITDIALOG: case WM_UPDATEPROFILEPOPOUT: { + if (IsDarkModeEnabled()) { + ri::SetWindowTheme(GetDlgItem(hWnd, IDC_MEMBERSINCEGROUP), L" ", L" "); + ri::SetWindowTheme(GetDlgItem(hWnd, IDC_ROLE_GROUP), L" ", L" "); + ri::SetWindowTheme(GetDlgItem(hWnd, IDC_NOTE_GROUP), L" ", L" "); + ri::SetWindowTheme(GetDlgItem(hWnd, IDC_MESSAGE_GROUP), L" ", L" "); + ri::SetWindowTheme(GetDlgItem(hWnd, IDC_ABOUTME_GROUP), L" ", L" "); + } + m_size = {}; BOOL res = Layout(hWnd, m_size); if (!res) { @@ -547,8 +554,14 @@ INT_PTR CALLBACK ProfilePopout::Proc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM case WM_CTLCOLOREDIT: // Windows NT 3.1 seems to send this intead of WM_CTLCOLORSTATIC for my disabled text boxes // If the window is disabled, set the background color below - if (IsWindowEnabled((HWND)lParam)) + if (IsWindowEnabled((HWND)lParam)) { + if (IsDarkModeEnabled()) { + SetTextColor((HDC)wParam, GetSysColorV2(COLOR_WINDOWTEXT)); + SetBkColor((HDC)wParam, GetSysColorV2(COLOR_WINDOW)); + return (INT_PTR)GetSysColorBrushV2(COLOR_WINDOW); + } break; + } // fall through case WM_CTLCOLOR: @@ -556,8 +569,9 @@ INT_PTR CALLBACK ProfilePopout::Proc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM case WM_CTLCOLORSTATIC: case WM_CTLCOLORBTN: // Windows NT 3.1 seems to send this instead of WM_CTLCOLORSTATIC for my group boxes { - SetBkColor((HDC) wParam, GetSysColor(COLOR_3DFACE)); - return (INT_PTR)ri::GetSysColorBrush(COLOR_3DFACE); + SetTextColor((HDC) wParam, GetSysColorV2(COLOR_WINDOWTEXT)); + SetBkColor((HDC) wParam, GetSysColorV2(COLOR_3DFACE)); + return (INT_PTR)GetSysColorBrushV2(COLOR_3DFACE); } } diff --git a/src/windows/ProfileView.cpp b/src/windows/ProfileView.cpp index e0e443c4..1693e72f 100644 --- a/src/windows/ProfileView.cpp +++ b/src/windows/ProfileView.cpp @@ -107,7 +107,7 @@ void ProfileView::Paint(HDC hdc) RECT rcProfile = rect; rcProfile.right = pfpX + pfpBorderSize - ScaleByDPI(6); - FillRect(hdc, &rcProfile, ri::GetSysColorBrush(PROFILE_VIEW_COLOR)); + FillRect(hdc, &rcProfile, GetSysColorBrushV2(PROFILE_VIEW_COLOR)); if (!NT31SimplifiedInterface()) ri::DrawIconEx(hdc, pfpX - ScaleByDPI(6), pfpY - ScaleByDPI(4), g_ProfileBorderIcon, pfpBorderSizeDrawn, pfpBorderSizeDrawn, 0, NULL, DI_NORMAL | DI_COMPAT); @@ -116,8 +116,8 @@ void ProfileView::Paint(HDC hdc) DrawActivityStatus(hdc, pfpX, pfpY, activeStatus); - COLORREF clrOld = SetBkColor(hdc, GetSysColor(PROFILE_VIEW_COLOR)); - COLORREF cltOld = SetTextColor(hdc, GetSysColor(COLOR_MENUTEXT)); + COLORREF clrOld = SetBkColor(hdc, GetSysColorV2(PROFILE_VIEW_COLOR)); + COLORREF cltOld = SetTextColor(hdc, GetSysColorV2(COLOR_MENUTEXT)); HGDIOBJ objOld = SelectObject(hdc, g_AccountInfoFont); RECT rcText = rect; @@ -192,7 +192,7 @@ void ProfileView::InitializeClass() WNDCLASS& wc = g_ProfileViewClass; wc.lpszClassName = T_PROFILE_VIEW_CLASS; - wc.hbrBackground = ri::GetSysColorBrush(PROFILE_VIEW_COLOR); + wc.hbrBackground = GetSysColorBrushV2(PROFILE_VIEW_COLOR); wc.style = 0; wc.hCursor = LoadCursor(0, IDC_ARROW); wc.lpfnWndProc = ProfileView::WndProc; diff --git a/src/windows/QuickSwitcher.cpp b/src/windows/QuickSwitcher.cpp index 97b2c012..a89777a7 100644 --- a/src/windows/QuickSwitcher.cpp +++ b/src/windows/QuickSwitcher.cpp @@ -297,16 +297,16 @@ LRESULT QuickSwitcher::HandleCustomDraw(HWND hWnd, NMLVCUSTOMDRAW* pInfo) int sta = ListView_GetItemState(hList, idx, LVIS_SELECTED); if (sta & LVIS_SELECTED) { - pInfo->clrTextBk = GetSysColor(COLOR_HIGHLIGHT); - pInfo->clrText = GetSysColor(COLOR_HIGHLIGHTTEXT); + pInfo->clrTextBk = GetSysColorV2(COLOR_HIGHLIGHT); + pInfo->clrText = GetSysColorV2(COLOR_HIGHLIGHTTEXT); } else if (pInfo->iSubItem == COL_CATEGORY_NAME) { - pInfo->clrTextBk = GetSysColor(COLOR_WINDOW); - pInfo->clrText = GetSysColor(COLOR_GRAYTEXT); + pInfo->clrTextBk = GetSysColorV2(COLOR_WINDOW); + pInfo->clrText = GetSysColorV2(COLOR_GRAYTEXT); } else { - pInfo->clrTextBk = GetSysColor(COLOR_WINDOW); - pInfo->clrText = GetSysColor(COLOR_MENUTEXT); + pInfo->clrTextBk = GetSysColorV2(COLOR_WINDOW); + pInfo->clrText = GetSysColorV2(COLOR_MENUTEXT); } return CDRF_NEWFONT; diff --git a/src/windows/RoleList.cpp b/src/windows/RoleList.cpp index 3b5f6c9f..d7b9fc6a 100644 --- a/src/windows/RoleList.cpp +++ b/src/windows/RoleList.cpp @@ -119,13 +119,13 @@ void RoleList::DrawRole(HDC hdc, RoleItem* role) COLORREF oldBkColor = CLR_NONE; switch (style) { case MS_3DFACE: - ri::DrawEdge(hdc, &rect, BDR_RAISEDINNER, BF_RECT | BF_MIDDLE | BF_ADJUST); + DrawEdgeV2(hdc, &rect, BDR_RAISEDINNER, BF_RECT | BF_MIDDLE | BF_ADJUST); case MS_FLAT: case MS_IMAGE: - oldBkColor = SetBkColor(hdc, GetSysColor(COLOR_3DFACE)); + oldBkColor = SetBkColor(hdc, GetSysColorV2(COLOR_3DFACE)); break; case MS_FLATBR: - oldBkColor = SetBkColor(hdc, GetSysColor(COLOR_WINDOW)); + oldBkColor = SetBkColor(hdc, GetSysColorV2(COLOR_WINDOW)); break; case MS_GRADIENT: oldBkMode = SetBkMode(hdc, TRANSPARENT); @@ -150,7 +150,7 @@ void RoleList::DrawRole(HDC hdc, RoleItem* role) DrawShinyRoleColor(hdc, &rcColor, cref); - COLORREF col2 = SetTextColor(hdc, GetSysColor(COLOR_WINDOWTEXT)); + COLORREF col2 = SetTextColor(hdc, GetSysColorV2(COLOR_WINDOWTEXT)); DrawText(hdc, role->GetText(), -1, &rcText, DT_NOPREFIX | DT_VCENTER | DT_SINGLELINE | DT_CENTER); SetTextColor(hdc, col2); SelectObject(hdc, obj); @@ -235,10 +235,10 @@ LRESULT CALLBACK RoleList::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM l eMessageStyle style = GetLocalSettings()->GetMessageStyle(); switch (style) { default: - SetClassLongPtr(hWnd, GCLP_HBRBACKGROUND, (LONG_PTR)ri::GetSysColorBrush(COLOR_3DFACE)); + SetClassLongPtr(hWnd, GCLP_HBRBACKGROUND, (LONG_PTR)GetSysColorBrushV2(COLOR_3DFACE)); break; case MS_FLATBR: - SetClassLongPtr(hWnd, GCLP_HBRBACKGROUND, (LONG_PTR)ri::GetSysColorBrush(COLOR_WINDOW)); + SetClassLongPtr(hWnd, GCLP_HBRBACKGROUND, (LONG_PTR)GetSysColorBrushV2(COLOR_WINDOW)); break; } break; @@ -378,7 +378,7 @@ void RoleList::InitializeClass() return; wc.lpszClassName = T_ROLE_LIST_CLASS; - wc.hbrBackground = ri::GetSysColorBrush(COLOR_3DFACE); + wc.hbrBackground = GetSysColorBrushV2(COLOR_3DFACE); wc.style = 0; wc.hCursor = LoadCursor(0, IDC_ARROW); wc.lpfnWndProc = RoleList::WndProc; diff --git a/src/windows/StatusBar.cpp b/src/windows/StatusBar.cpp index 514a49ab..cf5f8916 100644 --- a/src/windows/StatusBar.cpp +++ b/src/windows/StatusBar.cpp @@ -41,6 +41,12 @@ StatusBar* StatusBar::Create(HWND hParent) SetWindowFont(pBar->m_hwnd, g_MessageTextFont, TRUE); SetWindowLongPtr(pBar->m_hwnd, GWLP_USERDATA, (LONG_PTR) pBar); + + if (IsDarkModeEnabled()) { + ri::SetWindowTheme(pBar->m_hwnd, L" ", L" "); + SendMessage(pBar->m_hwnd, SB_SETBKCOLOR, 0, (LPARAM) GetSysColorV2(COLOR_3DFACE)); + } + return pBar; } @@ -188,6 +194,21 @@ void StatusBar::OnAnimationTick() void StatusBar::UpdateCharacterCounter(int nChars, int nCharsMax) { + if (IsDarkModeEnabled()) { + if (!nChars) { + if (m_charCountStr) + free(m_charCountStr); + m_charCountStr = NULL; + } + else { + std::string text = std::to_string(nChars) + "/" + std::to_string(nCharsMax); + LPTSTR tstr = ConvertCppStringToTString(text); + m_charCountStr = tstr; + } + SendMessage(m_hwnd, SB_SETTEXT, IDP_CHRCNT | SBT_OWNERDRAW, 0); + return; + } + if (!nChars) { SendMessage(m_hwnd, SB_SETTEXT, IDP_CHRCNT, (LPARAM) TEXT("")); return; @@ -200,6 +221,33 @@ void StatusBar::UpdateCharacterCounter(int nChars, int nCharsMax) } void StatusBar::DrawItem(LPDRAWITEMSTRUCT lpDIS) +{ + switch (lpDIS->itemID) { + case IDP_TYPING: + DrawTypingItem(lpDIS); + break; + case IDP_CHRCNT: + DrawCharCountItem(lpDIS); + break; + } +} + +void StatusBar::DrawCharCountItem(LPDRAWITEMSTRUCT lpDIS) +{ + HDC hdc = lpDIS->hDC; + RECT rc = lpDIS->rcItem; + int mode = SetBkMode(hdc, TRANSPARENT); + COLORREF textOld = SetTextColor(hdc, GetSysColorV2(COLOR_WINDOWTEXT)); + + if (m_charCountStr) { + DrawText(hdc, m_charCountStr, -1, &rc, DT_NOPREFIX | DT_SINGLELINE | DT_VCENTER); + } + + SetTextColor(hdc, textOld); + SetBkMode(hdc, mode); +} + +void StatusBar::DrawTypingItem(LPDRAWITEMSTRUCT lpDIS) { // this is the only owner drawn item assert(lpDIS->itemID == IDP_TYPING); @@ -221,7 +269,7 @@ void StatusBar::DrawItem(LPDRAWITEMSTRUCT lpDIS) int mode = SetBkMode(hdc, TRANSPARENT); HGDIOBJ gdiObjOld = SelectObject(hdc, g_TypingBoldFont); - COLORREF textOld = SetTextColor(hdc, GetSysColor(COLOR_WINDOWTEXT)); + COLORREF textOld = SetTextColor(hdc, GetSysColorV2(COLOR_WINDOWTEXT)); m_typing_status_rect = rc; diff --git a/src/windows/StatusBar.hpp b/src/windows/StatusBar.hpp index 671e08ea..aaa41a5b 100644 --- a/src/windows/StatusBar.hpp +++ b/src/windows/StatusBar.hpp @@ -36,6 +36,8 @@ class StatusBar int GetNextExpiryTime(); void OnExpiryTick(); void OnAnimationTick(); + void DrawTypingItem(LPDRAWITEMSTRUCT lpDIS); + void DrawCharCountItem(LPDRAWITEMSTRUCT lpDIS); public: // should only be called by Main.cpp @@ -57,4 +59,5 @@ class StatusBar int m_anim_frame_number = 0; RECT m_typing_status_rect; RECT m_typing_animation_rect; + LPTSTR m_charCountStr = NULL; }; diff --git a/src/windows/TextInterface_Win32.cpp b/src/windows/TextInterface_Win32.cpp index ff7072a3..c0fa392d 100644 --- a/src/windows/TextInterface_Win32.cpp +++ b/src/windows/TextInterface_Win32.cpp @@ -239,7 +239,7 @@ void MdDrawString(DrawingContext* context, const Rect& rect, const String& str, setColorBG = true; } if (styleFlags & (WORD_CODE | WORD_MLCODE)) { - oldColorBG = SetBkColor(context->m_hdc, context->InvertIfNeeded(GetSysColor(COLOR_WINDOW))); + oldColorBG = SetBkColor(context->m_hdc, context->InvertIfNeeded(GetSysColorV2(COLOR_WINDOW))); setColorBG = true; flags |= DT_WORDBREAK | DT_EDITCONTROL; } @@ -254,7 +254,7 @@ void MdDrawString(DrawingContext* context, const Rect& rect, const String& str, RECT rc2 = rc; rc2.left -= ScaleByDPI(SIZE_QUOTE_INDENT); rc2.right = rc2.left + ScaleByDPI(3); - FillRect(hdc, &rc2, ri::GetSysColorBrush(COLOR_SCROLLBAR)); + FillRect(hdc, &rc2, GetSysColorBrushV2(COLOR_SCROLLBAR)); } // prevent italics that overflow the rect from being clipped @@ -285,15 +285,15 @@ void MdDrawCodeBackground(DrawingContext* context, const Rect& rect) RECT rc = RectToNative(rect); if (context->m_bInvertTextColor) { - COLORREF old = ri::SetDCBrushColor(context->m_hdc, context->InvertIfNeeded(GetSysColor(COLOR_WINDOW))); + COLORREF old = ri::SetDCBrushColor(context->m_hdc, context->InvertIfNeeded(GetSysColorV2(COLOR_WINDOW))); FillRect(context->m_hdc, &rc, ri::GetDCBrush()); ri::SetDCBrushColor(context->m_hdc, old); } else { - FillRect(context->m_hdc, &rc, ri::GetSysColorBrush(COLOR_WINDOW)); + FillRect(context->m_hdc, &rc, GetSysColorBrushV2(COLOR_WINDOW)); } - ri::DrawEdge(context->m_hdc, &rc, BDR_SUNKEN, BF_RECT); + DrawEdgeV2(context->m_hdc, &rc, BDR_SUNKEN, BF_RECT); } void MdDrawForwardBackground(DrawingContext* context, const Rect& rect) @@ -304,12 +304,12 @@ void MdDrawForwardBackground(DrawingContext* context, const Rect& rect) rc.left = rc.right - ScaleByDPI(3); if (context->m_bInvertTextColor) { - COLORREF old = ri::SetDCBrushColor(context->m_hdc, context->InvertIfNeeded(GetSysColor(COLOR_GRAYTEXT))); + COLORREF old = ri::SetDCBrushColor(context->m_hdc, context->InvertIfNeeded(GetSysColorV2(COLOR_GRAYTEXT))); FillRect(context->m_hdc, &rc, ri::GetDCBrush()); ri::SetDCBrushColor(context->m_hdc, old); } else { - FillRect(context->m_hdc, &rc, ri::GetSysColorBrush(COLOR_GRAYTEXT)); + FillRect(context->m_hdc, &rc, GetSysColorBrushV2(COLOR_GRAYTEXT)); } } diff --git a/src/windows/WinUtils.cpp b/src/windows/WinUtils.cpp index ed39d10b..ace6d4af 100644 --- a/src/windows/WinUtils.cpp +++ b/src/windows/WinUtils.cpp @@ -20,6 +20,7 @@ #include "TextManager.hpp" #include "ProgressDialog.hpp" #include "DoubleBufferingHelper.hpp" +#include "config/LocalSettings.hpp" #ifndef OLD_WINDOWS #include @@ -604,12 +605,12 @@ void FillGradient(HDC hdc, const LPRECT lpRect, int sci1, int sci2, bool vertica sci1 = COLOR_INACTIVECAPTION; } if (ri::HaveMsImg()) { - COLORREF c1 = GetSysColor(sci1); - COLORREF c2 = GetSysColor(sci2); + COLORREF c1 = GetSysColorV2(sci1); + COLORREF c2 = GetSysColorV2(sci2); FillGradientColors(hdc, lpRect, c1, c2, vertical); } else { - HBRUSH hbr = ri::GetSysColorBrush(sci1); + HBRUSH hbr = GetSysColorBrushV2(sci1); FillRect(hdc, lpRect, hbr); } } @@ -1165,7 +1166,9 @@ int MapIconToOldIfNeeded(int iconID) switch (iconID) { + case IDI_CHANNEL_MENTIONED_DARK: return IDI_CHANNEL_MENTIONED_DARK_2K; case IDI_PROFILE_BORDER_UNREAD: return IDI_PROFILE_BORDER_UNREAD_2K; + case IDI_CHANNEL_UNREAD_DARK: return IDI_CHANNEL_UNREAD_DARK_2K; case IDI_PROFILE_BORDER_GOLD: return IDI_PROFILE_BORDER_GOLD_2K; case IDI_CHANNEL_MENTIONED: return IDI_CHANNEL_MENTIONED_2K; case IDI_CHANNEL_UNREAD: return IDI_CHANNEL_UNREAD_2K; @@ -1173,15 +1176,19 @@ int MapIconToOldIfNeeded(int iconID) case IDI_TYPING_FRAME1: return IDI_TYPING_FRAME1_2K; case IDI_TYPING_FRAME2: return IDI_TYPING_FRAME2_2K; case IDI_TYPING_FRAME3: return IDI_TYPING_FRAME3_2K; + case IDI_CHANNEL_DARK: return IDI_CHANNEL_DARK_2K; + case IDI_GROUPDM_DARK: return IDI_GROUPDM_DARK_2K; case IDI_NOTIFICATION: return IDI_NOTIFICATION_2K; case IDI_REPLY_PIECE: return IDI_REPLY_PIECE_2K; case IDI_SHIFT_RIGHT: return IDI_SHIFT_RIGHT_2K; case IDI_NEW_INLINE: return IDI_NEW_INLINE_2K; case IDI_SHIFT_LEFT: return IDI_SHIFT_LEFT_2K; + case IDI_VOICE_DARK: return IDI_VOICE_DARK_2K; case IDI_CATEGORY: return IDI_CATEGORY_2K; case IDI_CHANNEL: return IDI_CHANNEL_2K; case IDI_MEMBERS: return IDI_MEMBERS_2K; case IDI_GROUPDM: return IDI_GROUPDM_2K; + case IDI_DM_DARK: return IDI_DM_DARK_2K; case IDI_SERVER: return IDI_SERVER_2K; case IDI_BOOST: return IDI_BOOST_2K; case IDI_VOICE: return IDI_VOICE_2K; @@ -1199,6 +1206,42 @@ int MapIconToOldIfNeeded(int iconID) } } +int MapIconToDarkModeIfNeeded(int iconID) +{ + if (!IsDarkModeEnabled()) + return iconID; + + switch (iconID) + { + case IDI_CHANNEL: + return IDI_CHANNEL_DARK; + case IDI_VOICE: + return IDI_VOICE_DARK; + case IDI_DM: + return IDI_DM_DARK; + case IDI_GROUPDM: + return IDI_GROUPDM_DARK; + case IDI_CHANNEL_MENTIONED: + return IDI_CHANNEL_MENTIONED_DARK; + case IDI_CHANNEL_UNREAD: + return IDI_CHANNEL_UNREAD_DARK; + case IDI_CHANNEL_2K: + return IDI_CHANNEL_DARK_2K; + case IDI_VOICE_2K: + return IDI_VOICE_DARK_2K; + case IDI_DM_2K: + return IDI_DM_DARK_2K; + case IDI_GROUPDM_2K: + return IDI_GROUPDM_DARK_2K; + case IDI_CHANNEL_MENTIONED_2K: + return IDI_CHANNEL_MENTIONED_DARK_2K; + case IDI_CHANNEL_UNREAD_2K: + return IDI_CHANNEL_UNREAD_DARK_2K; + default: + return iconID; + } +} + int MapDialogToOldIfNeeded(int iid) { if (SupportsDialogEx()) @@ -1270,7 +1313,7 @@ void DrawActivityStatus(HDC hdc, int x, int y, eActiveStatus status) void DrawLoadingBox(HDC hdc, RECT rect) { - ri::DrawEdge(hdc, &rect, BDR_SUNKEN, BF_RECT); + DrawEdgeV2(hdc, &rect, BDR_SUNKEN, BF_RECT); HRGN rgn = DoubleBufferingHelper::CreateRectRgn(hdc, rect); SelectClipRgn(hdc, rgn); @@ -1286,7 +1329,7 @@ void DrawLoadingBox(HDC hdc, RECT rect) void DrawErrorBox(HDC hdc, RECT rect) { - ri::DrawEdge(hdc, &rect, BDR_SUNKEN, BF_RECT); + DrawEdgeV2(hdc, &rect, BDR_SUNKEN, BF_RECT); HRGN rgn = DoubleBufferingHelper::CreateRectRgn(hdc, rect); SelectClipRgn(hdc, rgn); @@ -1521,7 +1564,7 @@ bool IsColorDark(COLORREF cr) bool IsTextColorDark() { - return IsColorDark(GetSysColor(COLOR_CAPTIONTEXT)); + return IsColorDark(GetSysColorV2(COLOR_CAPTIONTEXT)); } std::map m_bMostlyBlack; @@ -1743,3 +1786,136 @@ std::string FilterToken(const std::string& ogToken) return newToken; } + +std::string LoadEntireFile(const std::string& fileNameUTF8) +{ + LPTSTR fileNameUTF16 = ConvertCppStringToTString(fileNameUTF8); + HANDLE handle = CreateFile(fileNameUTF16, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + free(fileNameUTF16); + + if (!handle) { + DbgPrintW("Failed to open %s: %d", fileNameUTF8.c_str(), GetLastError()); + return ""; + } + + DWORD fileSize = GetFileSize(handle, NULL); + if (fileSize > 10000000) { + DbgPrintW("Uh oh, file is too big!"); + CloseHandle(handle); + return ""; + } + + DWORD bytesRead = 0; + std::string data; + data.resize(fileSize); + ReadFile(handle, (void*) data.data(), fileSize, &bytesRead, NULL); + CloseHandle(handle); + + if (bytesRead != fileSize) { + DbgPrintW("We only read %zu bytes, out of %zu!", (size_t) bytesRead, (size_t) fileSize); + return ""; + } + + return data; +} + +bool SaveEntireFile(const std::string& fileNameUTF8, const std::string& data) +{ + LPTSTR fileNameUTF16 = ConvertCppStringToTString(fileNameUTF8); + HANDLE handle = CreateFile(fileNameUTF16, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + free(fileNameUTF16); + + if (!handle) { + DbgPrintW("Failed to save %s: %d", fileNameUTF8.c_str(), GetLastError()); + return false; + } + + DWORD bytesWritten = 0; + WriteFile(handle, (const void*)data.data(), (DWORD) data.size(), &bytesWritten, NULL); + CloseHandle(handle); + + if (bytesWritten != (DWORD) data.size()) { + DbgPrintW("We only wrote %zu bytes, out of %zu! Data may have been corrupted!", (size_t) bytesWritten, data.size()); + return false; + } + + return true; +} + +bool IsDarkModeEnabled() +{ + return GetLocalSettings()->EnableDarkMode(); +} + +const COLORREF s_DarkModeColors[] = { + RGB(20,20,20), // COLOR_SCROLLBAR + RGB(40,40,40), // COLOR_BACKGROUND + RGB(0,0,0), // COLOR_ACTIVECAPTION + RGB(0,0,0), // COLOR_INACTIVECAPTION + RGB(40,40,40), // COLOR_MENU + RGB(0,0,0), // COLOR_WINDOW + RGB(80,80,80), // COLOR_WINDOWFRAME + RGB(255,255,255), // COLOR_MENUTEXT + RGB(255,255,255), // COLOR_WINDOWTEXT + RGB(255,255,255), // COLOR_CAPTIONTEXT + RGB(255,255,255), // COLOR_ACTIVEBORDER + RGB(255,255,255), // COLOR_INACTIVEBORDER + RGB(40,40,40), // COLOR_APPWORKSPACE + RGB(40,40,128), // COLOR_HIGHLIGHT + RGB(255,255,255), // COLOR_HIGHLIGHTTEXT + RGB(60,60,60), // COLOR_BTNFACE + RGB(20,20,20), // COLOR_BTNSHADOW + RGB(96,96,96), // COLOR_GRAYTEXT + RGB(255,255,255), // COLOR_BTNTEXT + RGB(128,128,128), // COLOR_INACTIVECAPTIONTEXT + RGB(80,80,80), // COLOR_BTNHIGHLIGHT + RGB(0,0,0), // COLOR_3DDKSHADOW + RGB(100,100,100), // COLOR_3DLIGHT + RGB(255,255,255), // COLOR_INFOTEXT + RGB(80,80,80), // COLOR_INFOBK + RGB(0,0,0), // missing #25 + RGB(255,0,255), // COLOR_HOTLIGHT + RGB(0,0,0), // COLOR_GRADIENTACTIVECAPTION + RGB(0,0,0), // COLOR_GRADIENTINACTIVECAPTION + RGB(40,40,128), // COLOR_MENUHILIGHT + RGB(30,30,30), // COLOR_MENUBAR +}; + +COLORREF GetSysColorV2(int nIndex) +{ + if (!IsDarkModeEnabled() || nIndex < 0 || nIndex >= 31) + return GetSysColor(nIndex); + + return s_DarkModeColors[nIndex]; +} + +HBRUSH GetSysColorBrushV2(int nIndex) +{ + if (!IsDarkModeEnabled()) + return ri::GetSysColorBrush(nIndex); + + if (nIndex < 0 || nIndex >= 31) { + // fallback, but this usage is WRONG! + DbgPrintW("bad index %d used in GetSysColorBrushV2", nIndex); + return ri::GetSysColorBrush(nIndex); + } + + static HBRUSH brushes[31]; + if (!brushes[nIndex]) + brushes[nIndex] = CreateSolidBrush(GetSysColorV2(nIndex)); + + return brushes[nIndex]; +} + +BOOL DrawEdgeV2(HDC hdc, LPRECT lprect, UINT style, UINT grfFlags) +{ + if (!IsDarkModeEnabled()) + return ri::DrawEdge(hdc, lprect, style, grfFlags); + + if (grfFlags & BF_MIDDLE) { + grfFlags &= ~BF_MIDDLE; + FillRect(hdc, lprect, GetSysColorBrushV2(COLOR_3DFACE)); + } + + return ri::DrawEdge(hdc, lprect, style, grfFlags); +} diff --git a/src/windows/WinUtils.hpp b/src/windows/WinUtils.hpp index fa70f273..057af2b2 100644 --- a/src/windows/WinUtils.hpp +++ b/src/windows/WinUtils.hpp @@ -20,9 +20,10 @@ #define DMCDF_WS2_32 0x0040 #define DMCDF_OLE32 0x0080 #define DMCDF_COMCTL32 0x0100 -#define DMCDF_ALL 0x01FF -#define DMCDF_NODLGEX 0x0200 -#define DMCDF_NODRIEX 0x0400 +#define DMCDF_UXTHEME 0x0200 +#define DMCDF_ALL 0x03FF +#define DMCDF_NODLGEX 0x0400 +#define DMCDF_NODRIEX 0x0800 #ifdef UNICODE #define WAsnprintf _snwprintf @@ -109,6 +110,7 @@ SIZE EnsureMaximumSize(int width, int height, int maxWidth, int maxHeight); bool Supports32BitIcons(); // Really, this checks if we are using Windows 2000 or older. bool SupportsDialogEx(); // Really, this checks if we are using Windows NT 3.51 or older. int MapIconToOldIfNeeded(int iconID); +int MapIconToDarkModeIfNeeded(int iconID); int MapDialogToOldIfNeeded(int dialogID); void InitializeStatusIcons(); void DrawMentionStatus(HDC hdc, int x, int y, int mentionCount); @@ -138,10 +140,13 @@ void DbgPrintW(const char* fmt, ...); // Convenience macro #define DMIC(iid) MapIconToOldIfNeeded((iid)) +#define DMV(iid) MapIconToDarkModeIfNeeded((iid)) #define DMDI(iid) MapDialogToOldIfNeeded((iid)) // File utils bool FileExists(const std::string& path); +std::string LoadEntireFile(const std::string& fileNameUTF8); +bool SaveEntireFile(const std::string& fileNameUTF8, const std::string& data); bool XSetProcessDPIAware(); @@ -150,6 +155,10 @@ COLORREF LerpColor(COLORREF a, COLORREF b, int progMul, int progDiv); bool IsColorDark(COLORREF cr); bool IsTextColorDark(); bool IsIconMostlyBlack(HICON hic); +bool IsDarkModeEnabled(); +COLORREF GetSysColorV2(int nIndex); +HBRUSH GetSysColorBrushV2(int nIndex); +BOOL DrawEdgeV2(HDC hdc, LPRECT lprect, UINT style, UINT grfFlags); #define IsColorLight(cr) (!IsColorDark(cr)) #define IsTextColorLight() (!IsTextColorDark()) diff --git a/vs/DiscordMessenger.vcxproj b/vs/DiscordMessenger.vcxproj index dc18896a..e44246db 100644 --- a/vs/DiscordMessenger.vcxproj +++ b/vs/DiscordMessenger.vcxproj @@ -483,21 +483,31 @@ + + + + + + + + + + @@ -563,6 +573,8 @@ + + diff --git a/vs/DiscordMessenger.vcxproj.filters b/vs/DiscordMessenger.vcxproj.filters index 5b534b2d..ee5cca25 100644 --- a/vs/DiscordMessenger.vcxproj.filters +++ b/vs/DiscordMessenger.vcxproj.filters @@ -498,6 +498,42 @@ Resource Files + + Resource Files + + + Resource Files + + + Resource Files + + + Resource Files + + + Resource Files + + + Resource Files + + + Resource Files + + + Resource Files + + + Resource Files + + + Resource Files + + + Resource Files + + + Resource Files +