diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index c15b41f49..26fbc8abd 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -24,7 +24,7 @@ jobs: submodules: true - name: Set up MSBuild - uses: microsoft/setup-msbuild@v1 + uses: microsoft/setup-msbuild@v1.1 - name: Cache dependencies uses: actions/cache@v2 diff --git a/CHANGELOG.md b/CHANGELOG.md index 9c0b1a40b..f68ebb697 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,28 +13,30 @@ [#437](https://github.com/reupen/columns_ui/pull/437), [#438](https://github.com/reupen/columns_ui/pull/438), [#439](https://github.com/reupen/columns_ui/pull/439), [#440](https://github.com/reupen/columns_ui/pull/440), [#442](https://github.com/reupen/columns_ui/pull/442), [#444](https://github.com/reupen/columns_ui/pull/444), -[#445](https://github.com/reupen/columns_ui/pull/445)] +[#445](https://github.com/reupen/columns_ui/pull/445), [#451](https://github.com/reupen/columns_ui/pull/451)] -* The Filter search toolbar is now integrated with the Colours and fonts preferences page, and its font, foreground colour and background colour are now configurable. [[#424](https://github.com/reupen/columns_ui/pull/424)] - - (Note that selection colours are not supported.) +* The status bar can now show the number of selected tracks. [[#450](https://github.com/reupen/columns_ui/pull/450)] * Improvements were made to the status bar layout logic (including better DPI scaling). [[#432](https://github.com/reupen/columns_ui/pull/432)] +* The status bar playlist lock icon was replaced with the 🔒 character. [[#432](https://github.com/reupen/columns_ui/pull/432)] + * The default playback button icons were tweaked. This includes the removal of subtle glow effects. [[#435](https://github.com/reupen/columns_ui/pull/435)] +* The Filter search toolbar is now integrated with the Colours and fonts preferences page, and its font, foreground colour and background colour are now configurable. [[#424](https://github.com/reupen/columns_ui/pull/424)] + + (Note that selection colours are not supported.) + * The filter search button icons were updated. [[#438](https://github.com/reupen/columns_ui/pull/438)] * The default no-cover artwork image was updated. [[#437](https://github.com/reupen/columns_ui/pull/437)] -* The status bar playlist lock icon was replaced with the 🔒 character. [[#432](https://github.com/reupen/columns_ui/pull/432)] +* Flickering when resizing the Playlist tabs and Tab stack panels was eliminated. [[#451](https://github.com/reupen/columns_ui/pull/451)] * The 'View/Show toolbars' menu item is now only shown if the shift key is held down when opening the View menu. [[#410](https://github.com/reupen/columns_ui/pull/410)] * A warning was added under the 'Show toolbars' option in preferences. [[#410](https://github.com/reupen/columns_ui/pull/410)] -* The status bar can now show the number of selected tracks. [[#450](https://github.com/reupen/columns_ui/pull/450)] - ### Bug fixes * A problem where the playlist tabs panel had an incorrect maximum width or height was fixed. [[#449](https://github.com/reupen/columns_ui/pull/449)] diff --git a/foo_ui_columns/dark_mode_tabs.cpp b/foo_ui_columns/dark_mode_tabs.cpp index bfd920482..c72fe2db9 100644 --- a/foo_ui_columns/dark_mode_tabs.cpp +++ b/foo_ui_columns/dark_mode_tabs.cpp @@ -70,18 +70,16 @@ void handle_tab_control_paint(HWND wnd) const auto active_item_brush = get_colour_brush_lazy(ColourID::TabControlActiveItemBackground, is_dark); PAINTSTRUCT ps{}; - const auto dc = wil::BeginPaint(wnd, &ps); - const auto _select_font = wil::SelectObject(dc.get(), GetWindowFont(wnd)); - const auto _select_pen = wil::SelectObject(dc.get(), border_pen.get()); + const auto paint_dc = wil::BeginPaint(wnd, &ps); + const auto buffered_dc = uih::BufferedDC(paint_dc.get(), ps.rcPaint); + const auto _select_font = wil::SelectObject(buffered_dc.get(), GetWindowFont(wnd)); + const auto _select_pen = wil::SelectObject(buffered_dc.get(), border_pen.get()); - SetTextColor(dc.get(), get_colour(ColourID::TabControlItemText, is_dark)); - SetBkMode(dc.get(), TRANSPARENT); - - RECT client_rect{}; - GetClientRect(wnd, &client_rect); + SetTextColor(buffered_dc.get(), get_colour(ColourID::TabControlItemText, is_dark)); + SetBkMode(buffered_dc.get(), TRANSPARENT); if (ps.fErase) - FillRect(dc.get(), &client_rect, *get_colour_brush_lazy(ColourID::TabControlBackground, is_dark)); + FillRect(buffered_dc.get(), &ps.rcPaint, *get_colour_brush_lazy(ColourID::TabControlBackground, is_dark)); for (auto&& [index, item] : ranges::views::enumerate(items)) { const auto is_new_line = index == 0 || items[index - 1].rc.top != item.rc.top; @@ -110,23 +108,23 @@ void handle_tab_control_paint(HWND wnd) return *default_item_brush; }(); - FillRect(dc.get(), &item_rect, item_back_brush); + FillRect(buffered_dc.get(), &item_rect, item_back_brush); - MoveToEx(dc.get(), item_rect.right, item_rect.bottom, nullptr); - LineTo(dc.get(), item_rect.right, item_rect.top); - LineTo(dc.get(), item_rect.left, item_rect.top); + MoveToEx(buffered_dc.get(), item_rect.right, item_rect.bottom, nullptr); + LineTo(buffered_dc.get(), item_rect.right, item_rect.top); + LineTo(buffered_dc.get(), item_rect.left, item_rect.top); if (is_new_line || item.is_active) { - LineTo(dc.get(), item_rect.left, item_rect.bottom); + LineTo(buffered_dc.get(), item_rect.left, item_rect.bottom); } SIZE sz{}; - GetTextExtentPoint32(dc.get(), item.text.data(), gsl::narrow(item.text.length()), &sz); + GetTextExtentPoint32(buffered_dc.get(), item.text.data(), gsl::narrow(item.text.length()), &sz); // Position using original rect, but shift up 1px if it's the active tab const auto x = item.rc.left + (RECT_CX(item.rc) - sz.cx) / 2; const auto y = item.rc.top + (RECT_CY(item.rc) - sz.cy) / 2 - (item.is_active ? 1_spx : 0); - ExtTextOut(dc.get(), x, y, ETO_CLIPPED, &item_rect, item.text.data(), item.text.length(), nullptr); + ExtTextOut(buffered_dc.get(), x, y, ETO_CLIPPED, &item_rect, item.text.data(), item.text.length(), nullptr); } } diff --git a/foo_ui_columns/playlist_tabs.cpp b/foo_ui_columns/playlist_tabs.cpp index afb6fc1b0..97e8a65f5 100644 --- a/foo_ui_columns/playlist_tabs.cpp +++ b/foo_ui_columns/playlist_tabs.cpp @@ -259,17 +259,13 @@ LRESULT WINAPI PlaylistTabs::hook(HWND wnd, UINT msg, WPARAM wp, LPARAM lp) { switch (msg) { case WM_ERASEBKGND: - if (!colours::is_dark_mode_active()) - break; - return FALSE; - case WM_PAINT: { - if (!colours::is_dark_mode_active()) - break; - - dark::handle_tab_control_paint(wnd); + case WM_PAINT: + if (colours::is_dark_mode_active()) + dark::handle_tab_control_paint(wnd); + else + uih::paint_subclassed_window_with_buffering(wnd, tabproc); return 0; - } case WM_GETDLGCODE: return DLGC_WANTALLKEYS; case WM_KEYDOWN: { diff --git a/foo_ui_columns/playlist_tabs_wndproc.cpp b/foo_ui_columns/playlist_tabs_wndproc.cpp index 1d385322c..7b21bf46b 100644 --- a/foo_ui_columns/playlist_tabs_wndproc.cpp +++ b/foo_ui_columns/playlist_tabs_wndproc.cpp @@ -1,6 +1,7 @@ #include "stdafx.h" #include "common.h" +#include "dark_mode.h" #include "playlist_tabs.h" #include "playlist_manager_utils.h" @@ -52,7 +53,9 @@ LRESULT PlaylistTabs::on_message(HWND wnd, UINT msg, WPARAM wp, LPARAM lp) static_api_ptr_t()->register_callback(this, flag_all); break; } - + case WM_ERASEBKGND: + dark::draw_layout_background(wnd, reinterpret_cast(wp)); + return TRUE; case WM_SHOWWINDOW: { if (wp == TRUE && lp == NULL && !IsWindowVisible(m_child_wnd)) { ShowWindow(m_child_wnd, SW_SHOWNORMAL); diff --git a/foo_ui_columns/splitter_tabs.cpp b/foo_ui_columns/splitter_tabs.cpp index 9169d9726..07a4fc544 100644 --- a/foo_ui_columns/splitter_tabs.cpp +++ b/foo_ui_columns/splitter_tabs.cpp @@ -1,6 +1,7 @@ #include "stdafx.h" #include "splitter_tabs.h" +#include "dark_mode.h" #include "dark_mode_tabs.h" namespace cui::panels::tab_stack { @@ -511,6 +512,9 @@ LRESULT TabStackPanel::on_message(HWND wnd, UINT msg, WPARAM wp, LPARAM lp) m_dark_mode_notifier = std::make_unique( [wnd_tabs = m_wnd_tabs] { RedrawWindow(wnd_tabs, nullptr, nullptr, RDW_ERASE | RDW_INVALIDATE); }); } break; + case WM_ERASEBKGND: + dark::draw_layout_background(wnd, reinterpret_cast(wp)); + return TRUE; case WM_KEYDOWN: { if (wp != VK_LEFT && wp != VK_RIGHT && get_host()->get_keyboard_shortcuts_enabled() && g_process_keydown_keyboard_shortcuts(wp)) @@ -915,17 +919,13 @@ LRESULT WINAPI TabStackPanel::on_hooked_message(HWND wnd, UINT msg, WPARAM wp, L { switch (msg) { case WM_ERASEBKGND: - if (!colours::is_dark_mode_active()) - break; - return FALSE; - case WM_PAINT: { - if (!colours::is_dark_mode_active()) - break; - - dark::handle_tab_control_paint(wnd); + case WM_PAINT: + if (colours::is_dark_mode_active()) + dark::handle_tab_control_paint(wnd); + else + uih::paint_subclassed_window_with_buffering(wnd, m_tab_proc); return 0; - } case WM_GETDLGCODE: return DLGC_WANTALLKEYS; case WM_KEYDOWN: { diff --git a/foo_ui_columns/status_pane_msgproc.cpp b/foo_ui_columns/status_pane_msgproc.cpp index 402cb608f..8906b68f5 100644 --- a/foo_ui_columns/status_pane_msgproc.cpp +++ b/foo_ui_columns/status_pane_msgproc.cpp @@ -85,8 +85,9 @@ LRESULT StatusPane::on_message(HWND wnd, UINT msg, WPARAM wp, LPARAM lp) } } break; case WM_PAINT: { - uih::PaintScope ps(wnd); - uih::MemoryDC dc(ps); + PAINTSTRUCT ps{}; + const auto paint_dc = wil::BeginPaint(wnd, &ps); + uih::BufferedDC dc(paint_dc.get(), ps.rcPaint); const auto font_height = uGetFontHeight(m_font.get()); const auto line_height = font_height + uih::scale_dpi_value(3); @@ -97,7 +98,7 @@ LRESULT StatusPane::on_message(HWND wnd, UINT msg, WPARAM wp, LPARAM lp) RECT rc_volume{}; GetRelativeRect(m_volume_control.get_wnd(), wnd, &rc_volume); - render_background(dc, rc_client); + render_background(dc.get(), rc_client); RECT rc_text{rc_client}; rc_text.right = rc_volume.left - uih::scale_dpi_value(20); @@ -110,11 +111,12 @@ LRESULT StatusPane::on_message(HWND wnd, UINT msg, WPARAM wp, LPARAM lp) rc_line_2.top = rc_line_1.bottom; rc_line_2.bottom = rc_line_2.top + line_height; - HFONT fnt_old = SelectFont(dc, m_font.get()); + const auto _ = wil::SelectObject(dc.get(), m_font.get()); const char* placeholder = "999999999 items selected"; const auto default_text_colour = dark::get_system_colour(COLOR_BTNTEXT, colours::is_dark_mode_active()); - int placeholder_len = get_text_width(dc, placeholder, strlen(placeholder)) + uih::scale_dpi_value(20); + int placeholder_len + = uih::get_text_width(dc.get(), placeholder, strlen(placeholder)) + uih::scale_dpi_value(20); pfc::string8 items_text; items_text << m_item_count << " item"; @@ -123,47 +125,45 @@ LRESULT StatusPane::on_message(HWND wnd, UINT msg, WPARAM wp, LPARAM lp) if (m_selection) items_text << " selected"; - text_out_colours_tab(dc, items_text, -1, uih::scale_dpi_value(1), uih::scale_dpi_value(3), &rc_line_1, false, - default_text_colour, false, false, uih::ALIGN_LEFT); + text_out_colours_tab(dc.get(), items_text, -1, uih::scale_dpi_value(1), uih::scale_dpi_value(3), &rc_line_1, + false, default_text_colour, false, false, uih::ALIGN_LEFT); if (m_item_count) { pfc::string_formatter formatter; - text_out_colours_tab(dc, formatter << "Length: " << m_length_text, -1, uih::scale_dpi_value(1), + text_out_colours_tab(dc.get(), formatter << "Length: " << m_length_text, -1, uih::scale_dpi_value(1), uih::scale_dpi_value(3), &rc_line_2, false, default_text_colour, false, false, uih::ALIGN_LEFT); } if (m_menu_active) { { RECT rc_item = rc_line_1; - text_out_colours_tab(dc, m_menu_text, -1, uih::scale_dpi_value(1) + placeholder_len, + text_out_colours_tab(dc.get(), m_menu_text, -1, uih::scale_dpi_value(1) + placeholder_len, uih::scale_dpi_value(3), &rc_item, false, default_text_colour, false, false, uih::ALIGN_LEFT, nullptr, true, true, nullptr); } } else { placeholder = "Playing: "; - t_size placeholder2_len = get_text_width(dc, placeholder, strlen(placeholder)); + t_size placeholder2_len = uih::get_text_width(dc.get(), placeholder, strlen(placeholder)); t_size now_playing_x_end = uih::scale_dpi_value(4) + placeholder_len + placeholder2_len; { RECT rc_item = rc_line_1; // rc_item.right = 4 + placeholder_len + placeholder2_len; - text_out_colours_tab(dc, m_track_label, -1, uih::scale_dpi_value(4) + placeholder_len, 0, &rc_item, - false, default_text_colour, false, false, uih::ALIGN_LEFT, nullptr, true, true, nullptr); + text_out_colours_tab(dc.get(), m_track_label, -1, uih::scale_dpi_value(4) + placeholder_len, 0, + &rc_item, false, default_text_colour, false, false, uih::ALIGN_LEFT, nullptr, true, true, nullptr); } if (playing1.get_length()) { pfc::string_list_impl playingstrings; g_split_string_by_crlf(playing1.get_ptr(), playingstrings); t_size lines = playingstrings.get_count(); if (lines) - text_out_colours_tab(dc, playingstrings[0], pfc_infinite, now_playing_x_end, 0, &rc_line_1, false, - default_text_colour, true, false, uih::ALIGN_LEFT); + text_out_colours_tab(dc.get(), playingstrings[0], pfc_infinite, now_playing_x_end, 0, &rc_line_1, + false, default_text_colour, true, false, uih::ALIGN_LEFT); if (lines > 1) - text_out_colours_tab(dc, playingstrings[1], pfc_infinite, now_playing_x_end, 0, &rc_line_2, false, - default_text_colour, true, false, uih::ALIGN_LEFT); + text_out_colours_tab(dc.get(), playingstrings[1], pfc_infinite, now_playing_x_end, 0, &rc_line_2, + false, default_text_colour, true, false, uih::ALIGN_LEFT); } } - SelectFont(dc, fnt_old); - return 0; } } diff --git a/ui_helpers b/ui_helpers index 3aacdac66..c41b3107d 160000 --- a/ui_helpers +++ b/ui_helpers @@ -1 +1 @@ -Subproject commit 3aacdac6640793b7452bc3363f4c3d5dd904c010 +Subproject commit c41b3107dd02b97a804a779f880c8d1cc25c991f diff --git a/vc17/columns_ui-public.sln b/vc17/columns_ui-public.sln index edac772b9..718008c1b 100644 --- a/vc17/columns_ui-public.sln +++ b/vc17/columns_ui-public.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.29215.179 +# Visual Studio Version 17 +VisualStudioVersion = 17.1.32210.238 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Components", "Components", "{5CE500DE-1CE0-4222-9433-DCE0A3364124}" EndProject @@ -31,6 +31,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution ..\.gitattributes = ..\.gitattributes ..\.gitignore = ..\.gitignore ..\.gitmodules = ..\.gitmodules + ..\.github\workflows\build.yml = ..\.github\workflows\build.yml ..\CHANGELOG.md = ..\CHANGELOG.md ..\CONTRIBUTING.md = ..\CONTRIBUTING.md ..\COPYING = ..\COPYING @@ -41,10 +42,11 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fbh", "..\fbh\fbh.vcxproj", "{84D30275-D3D7-4867-82D2-8031A53DCE20}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Azure", "Azure", "{4800C6BC-4666-4EBD-882B-B50A759132F0}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".github", ".github", "{9697868F-BFF6-40A6-8818-F351DD370422}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "workflows", "workflows", "{9A1841D3-5B7E-4831-A6B7-8B3899D66EF2}" ProjectSection(SolutionItems) = preProject - ..\azure\job-build.yml = ..\azure\job-build.yml - ..\azure\pipeline.yml = ..\azure\pipeline.yml + ..\.github\workflows\build.yml = ..\.github\workflows\build.yml EndProjectSection EndProject Global @@ -147,7 +149,8 @@ Global {EBFFFB4E-261D-44D3-B89C-957B31A0BF9C} = {B9D1251F-E5BC-412F-950B-BE588408EA59} {743CBAAD-BE8E-430A-918B-2BB68008A616} = {5CE500DE-1CE0-4222-9433-DCE0A3364124} {93EC0EDE-01CD-4FB0-B8E8-4F2A027E026E} = {3A85ACE2-E7C5-4F1F-A253-9C60B8076BE8} - {4800C6BC-4666-4EBD-882B-B50A759132F0} = {0FF158B9-F515-4DCF-B879-3D38EEC6DA2C} + {9697868F-BFF6-40A6-8818-F351DD370422} = {0FF158B9-F515-4DCF-B879-3D38EEC6DA2C} + {9A1841D3-5B7E-4831-A6B7-8B3899D66EF2} = {9697868F-BFF6-40A6-8818-F351DD370422} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {69B91470-DA3C-4CE2-B984-1659F90BD386}