diff options
| author | spycrab <spycrab@users.noreply.github.com> | 2019-04-10 10:46:49 +0200 |
|---|---|---|
| committer | spycrab <spycrab@users.noreply.github.com> | 2019-04-10 10:46:49 +0200 |
| commit | d73987e466b734a837253b50c5d650322ec02662 (patch) | |
| tree | 41e1681a11a311e59d2e033ac81ac55c7f6af734 /Source/Core/WinUpdater/WinUI.cpp | |
| parent | 1f6c67a6fb26c873a72c5d33367d9be14f7c028e (diff) | |
Move Updater to WinUpdater
Diffstat (limited to 'Source/Core/WinUpdater/WinUI.cpp')
| -rw-r--r-- | Source/Core/WinUpdater/WinUI.cpp | 271 |
1 files changed, 271 insertions, 0 deletions
diff --git a/Source/Core/WinUpdater/WinUI.cpp b/Source/Core/WinUpdater/WinUI.cpp new file mode 100644 index 0000000000..7f9a951bef --- /dev/null +++ b/Source/Core/WinUpdater/WinUI.cpp @@ -0,0 +1,271 @@ +// Copyright 2018 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#include "UpdaterCommon/UI.h" + +#include <string> +#include <thread> + +#include <Windows.h> +#include <CommCtrl.h> +#include <ShObjIdl.h> +#include <shellapi.h> + +#include "Common/Flag.h" +#include "Common/StringUtil.h" + +namespace +{ +HWND window_handle = nullptr; +HWND label_handle = nullptr; +HWND total_progressbar_handle = nullptr; +HWND current_progressbar_handle = nullptr; +ITaskbarList3* taskbar_list = nullptr; + +Common::Flag running; +Common::Flag request_stop; + +int GetWindowHeight(HWND hwnd) +{ + RECT rect; + GetWindowRect(hwnd, &rect); + + return rect.bottom - rect.top; +} +}; // namespace + +constexpr int PROGRESSBAR_FLAGS = WS_VISIBLE | WS_CHILD | PBS_SMOOTH | PBS_SMOOTHREVERSE; +constexpr int WINDOW_FLAGS = WS_VISIBLE | WS_CLIPCHILDREN; +constexpr int PADDING_HEIGHT = 5; + +namespace UI +{ +bool InitWindow() +{ + InitCommonControls(); + + WNDCLASS wndcl = {}; + wndcl.lpfnWndProc = DefWindowProcW; + wndcl.hbrBackground = GetSysColorBrush(COLOR_MENU); + wndcl.lpszClassName = L"UPDATER"; + + if (!RegisterClass(&wndcl)) + return false; + + window_handle = + CreateWindow(L"UPDATER", L"Dolphin Updater", WINDOW_FLAGS, CW_USEDEFAULT, CW_USEDEFAULT, 500, + 100, nullptr, nullptr, GetModuleHandle(nullptr), 0); + + if (!window_handle) + return false; + + if (FAILED(CoCreateInstance(CLSID_TaskbarList, NULL, CLSCTX_INPROC_SERVER, + IID_PPV_ARGS(&taskbar_list)))) + { + taskbar_list = nullptr; + } + if (taskbar_list && FAILED(taskbar_list->HrInit())) + { + taskbar_list->Release(); + taskbar_list = nullptr; + } + + int y = PADDING_HEIGHT; + + label_handle = CreateWindow(L"STATIC", NULL, WS_VISIBLE | WS_CHILD, 5, y, 500, 25, window_handle, + nullptr, nullptr, 0); + + if (!label_handle) + return false; + + // Get the default system font + NONCLIENTMETRICS metrics = {}; + metrics.cbSize = sizeof(NONCLIENTMETRICS); + + if (!SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(metrics), &metrics, 0)) + return false; + + SendMessage(label_handle, WM_SETFONT, + reinterpret_cast<WPARAM>(CreateFontIndirect(&metrics.lfMessageFont)), 0); + + y += GetWindowHeight(label_handle) + PADDING_HEIGHT; + + total_progressbar_handle = CreateWindow(PROGRESS_CLASS, NULL, PROGRESSBAR_FLAGS, 5, y, 470, 25, + window_handle, nullptr, nullptr, 0); + + y += GetWindowHeight(total_progressbar_handle) + PADDING_HEIGHT; + + if (!total_progressbar_handle) + return false; + + current_progressbar_handle = CreateWindow(PROGRESS_CLASS, NULL, PROGRESSBAR_FLAGS, 5, y, 470, 25, + window_handle, nullptr, nullptr, 0); + + y += GetWindowHeight(current_progressbar_handle) + PADDING_HEIGHT; + + if (!current_progressbar_handle) + return false; + + RECT rect; + GetWindowRect(window_handle, &rect); + + // Account for the title bar + y += GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CYCAPTION) + + GetSystemMetrics(SM_CXPADDEDBORDER); + // ...and window border + y += GetSystemMetrics(SM_CYBORDER); + + // Add some padding for good measure + y += PADDING_HEIGHT * 3; + + SetWindowPos(window_handle, HWND_TOPMOST, 0, 0, rect.right - rect.left, y, SWP_NOMOVE); + + return true; +} + +void Destroy() +{ + DestroyWindow(window_handle); + DestroyWindow(label_handle); + DestroyWindow(total_progressbar_handle); + DestroyWindow(current_progressbar_handle); +} + +void SetTotalMarquee(bool marquee) +{ + SetWindowLong(total_progressbar_handle, GWL_STYLE, + PROGRESSBAR_FLAGS | (marquee ? PBS_MARQUEE : 0)); + SendMessage(total_progressbar_handle, PBM_SETMARQUEE, marquee, 0); + if (taskbar_list) + { + taskbar_list->SetProgressState(window_handle, marquee ? TBPF_INDETERMINATE : TBPF_NORMAL); + } +} + +void ResetTotalProgress() +{ + SendMessage(total_progressbar_handle, PBM_SETPOS, 0, 0); + SetCurrentMarquee(true); +} + +void SetTotalProgress(int current, int total) +{ + SendMessage(total_progressbar_handle, PBM_SETRANGE32, 0, total); + SendMessage(total_progressbar_handle, PBM_SETPOS, current, 0); + if (taskbar_list) + { + taskbar_list->SetProgressValue(window_handle, current, total); + } +} + +void SetCurrentMarquee(bool marquee) +{ + SetWindowLong(current_progressbar_handle, GWL_STYLE, + PROGRESSBAR_FLAGS | (marquee ? PBS_MARQUEE : 0)); + SendMessage(current_progressbar_handle, PBM_SETMARQUEE, marquee, 0); +} + +void ResetCurrentProgress() +{ + SendMessage(current_progressbar_handle, PBM_SETPOS, 0, 0); + SetCurrentMarquee(true); +} + +void Error(const std::string& text) +{ + auto wide_text = UTF8ToUTF16(text); + + MessageBox(nullptr, + (L"A fatal error occured and the updater cannot continue:\n " + wide_text).c_str(), + L"Error", MB_ICONERROR); + + if (taskbar_list) + { + taskbar_list->SetProgressState(window_handle, TBPF_ERROR); + } +} + +void SetCurrentProgress(int current, int total) +{ + SendMessage(current_progressbar_handle, PBM_SETRANGE32, 0, total); + SendMessage(current_progressbar_handle, PBM_SETPOS, current, 0); +} + +void SetDescription(const std::string& text) +{ + SetWindowText(label_handle, UTF8ToUTF16(text).c_str()); +} + +void MessageLoop() +{ + request_stop.Clear(); + running.Set(); + + if (!InitWindow()) + { + running.Clear(); + MessageBox(nullptr, L"Window init failed!", L"", MB_ICONERROR); + } + + SetTotalMarquee(true); + SetCurrentMarquee(true); + + while (!request_stop.IsSet()) + { + MSG msg; + while (PeekMessage(&msg, window_handle, 0, 0, PM_REMOVE)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + + running.Clear(); + + Destroy(); +} + +void Init() +{ + std::thread thread(MessageLoop); + thread.detach(); +} + +void Stop() +{ + if (!running.IsSet()) + return; + + request_stop.Set(); + + while (running.IsSet()) + { + } +} + +void LaunchApplication(std::string path) +{ + // Hack: Launching the updater over the explorer ensures that admin priviliges are dropped. Why? + // Ask Microsoft. + ShellExecuteW(nullptr, nullptr, L"explorer.exe", UTF8ToUTF16(path).c_str(), nullptr, SW_SHOW); +} + +void Sleep(int sleep) +{ + ::Sleep(sleep * 1000); +} + +void WaitForPID(u32 pid) +{ + HANDLE parent_handle = OpenProcess(SYNCHRONIZE, FALSE, static_cast<DWORD>(pid)); + WaitForSingleObject(parent_handle, INFINITE); + CloseHandle(parent_handle); +} + +void SetVisible(bool visible) +{ + ShowWindow(window_handle, visible ? SW_SHOW : SW_HIDE); +} + +}; // namespace UI |
