From f75352dcb03b23f56eecd6eec74050a828b740a8 Mon Sep 17 00:00:00 2001 From: Xu <34770031+Blinue@users.noreply.github.com> Date: Wed, 10 Apr 2024 22:25:10 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E4=BC=98=E5=8C=96=E8=8E=B7=E5=8F=96?= =?UTF-8?q?=E7=A8=8B=E5=BA=8F=E8=B7=AF=E5=BE=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Magpie.App/AboutViewModel.cpp | 6 ++---- src/Magpie.App/AutoStartHelper.cpp | 9 +++------ src/Magpie.App/TitlebarControl.cpp | 7 +++---- src/Magpie/NotifyIconService.cpp | 17 +++++++++++------ src/Magpie/main.cpp | 24 ++++++++++-------------- src/Shared/Win32Utils.cpp | 24 ++++++++++++++++++++++++ src/Shared/Win32Utils.h | 2 ++ 7 files changed, 55 insertions(+), 34 deletions(-) diff --git a/src/Magpie.App/AboutViewModel.cpp b/src/Magpie.App/AboutViewModel.cpp index 8a2f53645..bf444bc04 100644 --- a/src/Magpie.App/AboutViewModel.cpp +++ b/src/Magpie.App/AboutViewModel.cpp @@ -40,12 +40,10 @@ AboutViewModel::AboutViewModel() { // 异步加载 Logo ([](AboutViewModel* that)->fire_and_forget { - wchar_t exePath[MAX_PATH]; - GetModuleFileName(NULL, exePath, MAX_PATH); - auto weakThis = that->get_weak(); SoftwareBitmapSource bitmap; - co_await bitmap.SetBitmapAsync(IconHelper::ExtractIconFromExe(exePath, 256, USER_DEFAULT_SCREEN_DPI)); + co_await bitmap.SetBitmapAsync(IconHelper::ExtractIconFromExe( + Win32Utils::GetExePath().c_str(), 256, USER_DEFAULT_SCREEN_DPI)); if (!weakThis.get()) { co_return; diff --git a/src/Magpie.App/AutoStartHelper.cpp b/src/Magpie.App/AutoStartHelper.cpp index 231ce6d6c..a8277a476 100644 --- a/src/Magpie.App/AutoStartHelper.cpp +++ b/src/Magpie.App/AutoStartHelper.cpp @@ -210,9 +210,8 @@ static bool CreateAutoStartTask(bool runElevated, const wchar_t* arguments) { } // Set the path of the executable to Magpie (passed as CustomActionData). - WCHAR executablePath[MAX_PATH]; - GetModuleFileName(NULL, executablePath, MAX_PATH); - hr = execAction->put_Path(wil::make_bstr_nothrow(executablePath).get()); + const std::wstring& exePath = Win32Utils::GetExePath(); + hr = execAction->put_Path(wil::make_bstr_nothrow(exePath.c_str()).get()); if (FAILED(hr)) { Logger::Get().ComError("设置可执行文件路径失败", hr); return false; @@ -407,9 +406,7 @@ static bool CreateAutoStartShortcut(const wchar_t* arguments) { return false; } - WCHAR executablePath[MAX_PATH]; - GetModuleFileName(NULL, executablePath, MAX_PATH); - shellLink->SetPath(executablePath); + shellLink->SetPath(Win32Utils::GetExePath().c_str()); if (arguments) { shellLink->SetArguments(arguments); diff --git a/src/Magpie.App/TitlebarControl.cpp b/src/Magpie.App/TitlebarControl.cpp index 31bf57baa..b1f91bf82 100644 --- a/src/Magpie.App/TitlebarControl.cpp +++ b/src/Magpie.App/TitlebarControl.cpp @@ -4,6 +4,7 @@ #include "TitleBarControl.g.cpp" #endif #include "IconHelper.h" +#include "Win32Utils.h" using namespace winrt; using namespace Windows::UI::Xaml::Media::Imaging; @@ -13,13 +14,11 @@ namespace winrt::Magpie::App::implementation { TitleBarControl::TitleBarControl() { // 异步加载 Logo [](TitleBarControl* that)->fire_and_forget { - wchar_t exePath[MAX_PATH]; - GetModuleFileName(NULL, exePath, MAX_PATH); - auto weakThis = that->get_weak(); SoftwareBitmapSource bitmap; - co_await bitmap.SetBitmapAsync(IconHelper::ExtractIconFromExe(exePath, 40, USER_DEFAULT_SCREEN_DPI)); + co_await bitmap.SetBitmapAsync(IconHelper::ExtractIconFromExe( + Win32Utils::GetExePath().c_str(), 40, USER_DEFAULT_SCREEN_DPI)); if (!weakThis.get()) { co_return; diff --git a/src/Magpie/NotifyIconService.cpp b/src/Magpie/NotifyIconService.cpp index 439ca78bb..67586e3f7 100644 --- a/src/Magpie/NotifyIconService.cpp +++ b/src/Magpie/NotifyIconService.cpp @@ -102,9 +102,9 @@ LRESULT NotifyIconService::_NotifyIconWndProc(HWND hWnd, UINT message, WPARAM wP winrt::hstring mainWindowText = resourceLoader.GetString(L"NotifyIcon_MainWindow"); winrt::hstring exitText = resourceLoader.GetString(L"NotifyIcon_Exit"); - HMENU hMenu = CreatePopupMenu(); - AppendMenu(hMenu, MF_STRING, 1, mainWindowText.c_str()); - AppendMenu(hMenu, MF_STRING, 2, exitText.c_str()); + wil::unique_hmenu hMenu(CreatePopupMenu()); + AppendMenu(hMenu.get(), MF_STRING, 1, mainWindowText.c_str()); + AppendMenu(hMenu.get(), MF_STRING, 2, exitText.c_str()); // hWnd 必须为前台窗口才能正确展示弹出菜单 // 即使 hWnd 是隐藏的 @@ -112,9 +112,14 @@ LRESULT NotifyIconService::_NotifyIconWndProc(HWND hWnd, UINT message, WPARAM wP POINT cursorPos; GetCursorPos(&cursorPos); - BOOL selectedMenuId = TrackPopupMenuEx(hMenu, TPM_LEFTALIGN | TPM_NONOTIFY | TPM_RETURNCMD, cursorPos.x, cursorPos.y, hWnd, nullptr); - - DestroyMenu(hMenu); + BOOL selectedMenuId = TrackPopupMenuEx( + hMenu.get(), + TPM_LEFTALIGN | TPM_NONOTIFY | TPM_RETURNCMD, + cursorPos.x, + cursorPos.y, + hWnd, + nullptr + ); switch (selectedMenuId) { case 1: diff --git a/src/Magpie/main.cpp b/src/Magpie/main.cpp index 3ddcbf85b..756ca7df1 100644 --- a/src/Magpie/main.cpp +++ b/src/Magpie/main.cpp @@ -16,22 +16,18 @@ #include "pch.h" #include "XamlApp.h" -#include "StrUtils.h" +#include "Win32Utils.h" // 将当前目录设为程序所在目录 -static void SetCurDir() noexcept { - wchar_t curDir[MAX_PATH] = { 0 }; - GetModuleFileName(NULL, curDir, MAX_PATH); +static void SetWorkingDir() noexcept { + std::wstring exePath = Win32Utils::GetExePath(); - for (int i = (int)StrUtils::StrLen(curDir) - 1; i >= 0; --i) { - if (curDir[i] == L'\\' || curDir[i] == L'/') { - break; - } else { - curDir[i] = L'\0'; - } - } + FAIL_FAST_IF_FAILED(PathCchRemoveFileSpec( + exePath.data(), + exePath.size() + 1 + )); - SetCurrentDirectory(curDir); + FAIL_FAST_IF_WIN32_BOOL_FALSE(SetCurrentDirectory(exePath.c_str())); } static void IncreaseTimerResolution() noexcept { @@ -72,11 +68,11 @@ int APIENTRY wWinMain( // 见 https://kennykerr.ca/2018/03/24/cppwinrt-hosting-the-windows-runtime/ winrt::init_apartment(winrt::apartment_type::single_threaded); - SetCurDir(); + SetWorkingDir(); auto& app = Magpie::XamlApp::Get(); if (!app.Initialize(hInstance, lpCmdLine)) { - return -1; + return 0; } return app.Run(); diff --git a/src/Shared/Win32Utils.cpp b/src/Shared/Win32Utils.cpp index ce1a189ea..ea101126a 100644 --- a/src/Shared/Win32Utils.cpp +++ b/src/Shared/Win32Utils.cpp @@ -696,3 +696,27 @@ bool Win32Utils::OpenFolderAndSelectFile(const wchar_t* fileName) noexcept { return true; } + +const std::wstring& Win32Utils::GetExePath() noexcept { + // 会在日志初始化前调用 + static std::wstring result = []() -> std::wstring { + std::wstring exePath; + FAIL_FAST_IF_FAILED(wil::GetModuleFileNameW(NULL, exePath)); + + if (!wil::is_extended_length_path(exePath.c_str())) { + return exePath; + } + + // 去除 \\?\ 前缀 + wil::unique_hlocal_string canonicalPath; + FAIL_FAST_IF_FAILED(PathAllocCanonicalize( + exePath.c_str(), + PATHCCH_ALLOW_LONG_PATHS, + canonicalPath.put() + )); + + return canonicalPath.get(); + }(); + + return result; +} diff --git a/src/Shared/Win32Utils.h b/src/Shared/Win32Utils.h index d223b64f3..cf9278810 100644 --- a/src/Shared/Win32Utils.h +++ b/src/Shared/Win32Utils.h @@ -142,6 +142,8 @@ struct Win32Utils { static bool ShellOpen(const wchar_t* path, const wchar_t* parameters = nullptr, bool nonElevated = true) noexcept; // 不应在主线程调用 static bool OpenFolderAndSelectFile(const wchar_t* fileName) noexcept; + + static const std::wstring& GetExePath() noexcept; }; constexpr bool operator==(const SIZE& l, const SIZE& r) noexcept {