#include #include #include #include #include "flutter_window.h" #include "utils.h" #include "dump.h" #define APP_MUTEX_NAME L"nomo_win.mutex" #define APP_WINDOW_NAME L"Nomo VPN" UINT (*MyGetDpiForWindow) (HWND) = [] (HWND) { return 96u; }; int (*MyGetSystemMetricsForDpi) (int, UINT) = [] (int nIndex, UINT) { return GetSystemMetrics(nIndex); }; void runAsAdmin() { WCHAR czFileName[1024] = {0}; GetModuleFileName(NULL, czFileName, _countof(czFileName) - 1); SHELLEXECUTEINFO EI; memset(&EI, 0, sizeof(EI)); EI.cbSize = sizeof(SHELLEXECUTEINFO); EI.lpVerb = TEXT("runas"); EI.fMask = 0x00000040; EI.lpFile = czFileName; EI.nShow = SW_SHOW; ShellExecuteEx(&EI); } BOOL isRunAsAdmin() { BOOL isRunAsAdmin = FALSE; HANDLE hToken = NULL; if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken)) { return FALSE; } TOKEN_ELEVATION tokenEle; DWORD dwRetLen = 0; if (GetTokenInformation(hToken, TokenElevation, &tokenEle, sizeof(tokenEle), &dwRetLen)) { if (dwRetLen == sizeof(tokenEle)) { isRunAsAdmin = tokenEle.TokenIsElevated; } } CloseHandle(hToken); return isRunAsAdmin; } int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev, _In_ wchar_t *command_line, _In_ int show_command) { bool isDebugMode = false; char buffer[2]; if (GetEnvironmentVariableA("DEBUG_MODE", buffer, sizeof(buffer)) > 0) { isDebugMode = true; } // 以管理员权限运行 if (!isDebugMode && !isRunAsAdmin()) { runAsAdmin(); exit(0); } // 捕捉异常 //SetUnhandledExceptionFilter((LPTOP_LEVEL_EXCEPTION_FILTER)ApplicationCrashHandler); // Attach to console when present (e.g., 'flutter run') or create a // new console when running with a debugger. if (!::AttachConsole(ATTACH_PARENT_PROCESS) && ::IsDebuggerPresent()) { CreateAndAttachConsole(); } // Initialize COM, so that it is available for use in the library and/or // plugins. ::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); flutter::DartProject project(L"data"); std::vector command_line_arguments = GetCommandLineArguments(); project.set_dart_entrypoint_arguments(std::move(command_line_arguments)); FlutterWindow window(project); UINT scrWidth, scrHeight, xShaft, yShaft; double scale_factor_x = 1.0; double scale_factor_y = 1.0; // 计算屏幕逻辑尺寸 if (IsWindows10OrGreater()) { UINT dpiX, dpiY; HDC screen = GetDC(NULL); dpiX = GetDeviceCaps(screen, LOGPIXELSX); dpiY = GetDeviceCaps(screen, LOGPIXELSY); ReleaseDC(NULL, screen); scale_factor_x = dpiX / 96.0; scale_factor_y = dpiY / 96.0; if (auto user32 = LoadLibraryA("User32.dll")) { if (auto fn = GetProcAddress(user32, "GetDpiForWindow")) { MyGetDpiForWindow = (decltype(MyGetDpiForWindow)) fn; MyGetSystemMetricsForDpi = (decltype(MyGetSystemMetricsForDpi)) GetProcAddress(user32, "GetSystemMetricsForDpi"); } scrWidth = static_cast(round(MyGetSystemMetricsForDpi(SM_CXFULLSCREEN, dpiX) / scale_factor_x)); scrHeight = static_cast(round(MyGetSystemMetricsForDpi(SM_CYFULLSCREEN, dpiY) / scale_factor_y)); } else { scrWidth = GetSystemMetrics(SM_CXSCREEN); scrHeight = GetSystemMetrics(SM_CYSCREEN); } } else { scrWidth = GetSystemMetrics(SM_CXSCREEN); scrHeight = GetSystemMetrics(SM_CYSCREEN); } // 程序窗口大小 UINT windowWidth = 340, windowHeight = 640; Win32Window::Size size(windowWidth, windowHeight); // 计算程序显示坐标原点(屏幕中间) xShaft = (scrWidth - windowWidth) / 2; yShaft = (scrHeight - windowHeight) / 2; Win32Window::Point origin(xShaft, yShaft); if (!window.Create(APP_WINDOW_NAME, origin, size)) { return EXIT_FAILURE; } window.SetQuitOnClose(true); // int minWidth = static_cast(360 * scale_factor_x); // int minHeight = static_cast(640 * scale_factor_y); // window.SetMinimumSize({minWidth, minHeight}); window.SetMinimumSize(SIZE{ 340, 640 }); // 设置窗口不可最大化以及不可缩放 HWND hWnd = window.GetHandle(); DWORD gwlStyle = GetWindowLong(hWnd, GWL_STYLE); gwlStyle &= ~WS_THICKFRAME; gwlStyle &= ~WS_MAXIMIZEBOX; SetWindowLong(hWnd, GWL_STYLE, gwlStyle); ::MSG msg; while (::GetMessage(&msg, nullptr, 0, 0)) { ::TranslateMessage(&msg); ::DispatchMessage(&msg); } ::CoUninitialize(); return EXIT_SUCCESS; }