Path: blob/master/src/updater/win32_progress_callback.cpp
4243 views
// SPDX-FileCopyrightText: 2019-2024 Connor McLaughlin <[email protected]>1// SPDX-License-Identifier: CC-BY-NC-ND-4.023#include "win32_progress_callback.h"45#include "common/log.h"6#include "common/string_util.h"78#include <CommCtrl.h>910LOG_CHANNEL(Host);1112Win32ProgressCallback::Win32ProgressCallback() : ProgressCallback()13{14Create();15}1617void Win32ProgressCallback::PushState()18{19ProgressCallback::PushState();20}2122void Win32ProgressCallback::PopState()23{24ProgressCallback::PopState();25Redraw(true);26}2728void Win32ProgressCallback::SetCancellable(bool cancellable)29{30ProgressCallback::SetCancellable(cancellable);31Redraw(true);32}3334void Win32ProgressCallback::SetTitle(const std::string_view title)35{36SetWindowTextW(m_window_hwnd, StringUtil::UTF8StringToWideString(title).c_str());37}3839void Win32ProgressCallback::SetStatusText(const std::string_view text)40{41ProgressCallback::SetStatusText(text);42Redraw(true);43}4445void Win32ProgressCallback::SetProgressRange(u32 range)46{47ProgressCallback::SetProgressRange(range);48Redraw(false);49}5051void Win32ProgressCallback::SetProgressValue(u32 value)52{53ProgressCallback::SetProgressValue(value);54Redraw(false);55}5657bool Win32ProgressCallback::Create()58{59static const char* CLASS_NAME = "DSWin32ProgressCallbackWindow";60static bool class_registered = false;6162if (!class_registered)63{64InitCommonControls();6566WNDCLASSEX wc = {};67wc.cbSize = sizeof(WNDCLASSEX);68wc.lpfnWndProc = WndProcThunk;69wc.hInstance = GetModuleHandle(nullptr);70// wc.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICON));71// wc.hIconSm = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICON));72wc.hCursor = LoadCursor(NULL, IDC_WAIT);73wc.hbrBackground = (HBRUSH)COLOR_WINDOW;74wc.lpszClassName = CLASS_NAME;75if (!RegisterClassExA(&wc))76{77ERROR_LOG("Failed to register window class");78return false;79}8081class_registered = true;82}8384m_window_hwnd =85CreateWindowExA(WS_EX_CLIENTEDGE, CLASS_NAME, "Win32ProgressCallback", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT,86CW_USEDEFAULT, WINDOW_WIDTH, WINDOW_HEIGHT, nullptr, nullptr, GetModuleHandle(nullptr), this);87if (!m_window_hwnd)88{89ERROR_LOG("Failed to create window");90return false;91}9293SetWindowLongPtr(m_window_hwnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(this));94ShowWindow(m_window_hwnd, SW_SHOW);95PumpMessages();96return true;97}9899void Win32ProgressCallback::Destroy()100{101if (!m_window_hwnd)102return;103104DestroyWindow(m_window_hwnd);105m_window_hwnd = {};106m_text_hwnd = {};107m_progress_hwnd = {};108}109110void Win32ProgressCallback::PumpMessages()111{112MSG msg;113while (PeekMessageA(&msg, m_window_hwnd, 0, 0, PM_REMOVE))114{115TranslateMessage(&msg);116DispatchMessageA(&msg);117}118}119120void Win32ProgressCallback::Redraw(bool force)121{122const int percent =123static_cast<int>((static_cast<float>(m_progress_value) / static_cast<float>(m_progress_range)) * 100.0f);124if (percent == m_last_progress_percent && !force)125{126PumpMessages();127return;128}129130m_last_progress_percent = percent;131132SendMessageA(m_progress_hwnd, PBM_SETRANGE, 0, MAKELPARAM(0, m_progress_range));133SendMessageA(m_progress_hwnd, PBM_SETPOS, static_cast<WPARAM>(m_progress_value), 0);134SetWindowTextA(m_text_hwnd, m_status_text.c_str());135RedrawWindow(m_text_hwnd, nullptr, nullptr, RDW_INVALIDATE);136PumpMessages();137}138139LRESULT CALLBACK Win32ProgressCallback::WndProcThunk(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)140{141Win32ProgressCallback* cb;142if (msg == WM_CREATE)143{144const CREATESTRUCTA* cs = reinterpret_cast<CREATESTRUCTA*>(lparam);145cb = static_cast<Win32ProgressCallback*>(cs->lpCreateParams);146}147else148{149cb = reinterpret_cast<Win32ProgressCallback*>(GetWindowLongPtrA(hwnd, GWLP_USERDATA));150}151152return cb->WndProc(hwnd, msg, wparam, lparam);153}154155LRESULT CALLBACK Win32ProgressCallback::WndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)156{157switch (msg)158{159case WM_CREATE:160{161const CREATESTRUCTA* cs = reinterpret_cast<CREATESTRUCTA*>(lparam);162HFONT default_font = reinterpret_cast<HFONT>(GetStockObject(ANSI_VAR_FONT));163SendMessageA(hwnd, WM_SETFONT, WPARAM(default_font), TRUE);164165int y = WINDOW_MARGIN;166167m_text_hwnd = CreateWindowExA(0, "Static", nullptr, WS_VISIBLE | WS_CHILD, WINDOW_MARGIN, y, SUBWINDOW_WIDTH, 16,168hwnd, nullptr, cs->hInstance, nullptr);169SendMessageA(m_text_hwnd, WM_SETFONT, WPARAM(default_font), TRUE);170y += 16 + WINDOW_MARGIN;171172m_progress_hwnd = CreateWindowExA(0, PROGRESS_CLASSA, nullptr, WS_VISIBLE | WS_CHILD, WINDOW_MARGIN, y,173SUBWINDOW_WIDTH, 32, hwnd, nullptr, cs->hInstance, nullptr);174y += 32 + WINDOW_MARGIN;175176m_list_box_hwnd =177CreateWindowExA(0, "LISTBOX", nullptr, WS_VISIBLE | WS_CHILD | WS_VSCROLL | WS_HSCROLL | WS_BORDER | LBS_NOSEL,178WINDOW_MARGIN, y, SUBWINDOW_WIDTH, 170, hwnd, nullptr, cs->hInstance, nullptr);179SendMessageA(m_list_box_hwnd, WM_SETFONT, WPARAM(default_font), TRUE);180y += 170;181}182break;183184default:185return DefWindowProcA(hwnd, msg, wparam, lparam);186}187188return 0;189}190191void Win32ProgressCallback::DisplayError(const std::string_view message)192{193ERROR_LOG(message);194SendMessageW(m_list_box_hwnd, LB_ADDSTRING, 0,195reinterpret_cast<LPARAM>(StringUtil::UTF8StringToWideString(message).c_str()));196SendMessageW(m_list_box_hwnd, WM_VSCROLL, SB_BOTTOM, 0);197PumpMessages();198}199200void Win32ProgressCallback::DisplayWarning(const std::string_view message)201{202WARNING_LOG(message);203SendMessageW(m_list_box_hwnd, LB_ADDSTRING, 0,204reinterpret_cast<LPARAM>(StringUtil::UTF8StringToWideString(message).c_str()));205SendMessageW(m_list_box_hwnd, WM_VSCROLL, SB_BOTTOM, 0);206PumpMessages();207}208209void Win32ProgressCallback::DisplayInformation(const std::string_view message)210{211INFO_LOG(message);212SendMessageW(m_list_box_hwnd, LB_ADDSTRING, 0,213reinterpret_cast<LPARAM>(StringUtil::UTF8StringToWideString(message).c_str()));214SendMessageW(m_list_box_hwnd, WM_VSCROLL, SB_BOTTOM, 0);215PumpMessages();216}217218void Win32ProgressCallback::DisplayDebugMessage(const std::string_view message)219{220DEV_LOG(message);221}222223void Win32ProgressCallback::ModalError(const std::string_view message)224{225PumpMessages();226MessageBoxW(m_window_hwnd, StringUtil::UTF8StringToWideString(message).c_str(), L"Error", MB_ICONERROR | MB_OK);227PumpMessages();228}229230bool Win32ProgressCallback::ModalConfirmation(const std::string_view message)231{232PumpMessages();233bool result = MessageBoxW(m_window_hwnd, StringUtil::UTF8StringToWideString(message).c_str(), L"Confirmation",234MB_ICONQUESTION | MB_YESNO) == IDYES;235PumpMessages();236return result;237}238239void Win32ProgressCallback::ModalInformation(const std::string_view message)240{241MessageBoxW(m_window_hwnd, StringUtil::UTF8StringToWideString(message).c_str(), L"Information",242MB_ICONINFORMATION | MB_OK);243}244245246