main.cpp 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. #include <flutter/dart_project.h>
  2. #include <flutter/flutter_view_controller.h>
  3. #include <windows.h>
  4. #include <VersionHelpers.h>
  5. #include "flutter_window.h"
  6. #include "utils.h"
  7. #include "dump.h"
  8. #define APP_MUTEX_NAME L"nomo_win.mutex"
  9. #define APP_WINDOW_NAME L"NOMO"
  10. UINT (*MyGetDpiForWindow) (HWND) = [] (HWND) { return 96u; };
  11. int (*MyGetSystemMetricsForDpi) (int, UINT) = [] (int nIndex, UINT) { return GetSystemMetrics(nIndex); };
  12. void runAsAdmin()
  13. {
  14. WCHAR czFileName[1024] = {0};
  15. GetModuleFileName(NULL, czFileName, _countof(czFileName) - 1);
  16. SHELLEXECUTEINFO EI;
  17. memset(&EI, 0, sizeof(EI));
  18. EI.cbSize = sizeof(SHELLEXECUTEINFO);
  19. EI.lpVerb = TEXT("runas");
  20. EI.fMask = 0x00000040;
  21. EI.lpFile = czFileName;
  22. EI.nShow = SW_SHOW;
  23. ShellExecuteEx(&EI);
  24. }
  25. BOOL isRunAsAdmin()
  26. {
  27. BOOL isRunAsAdmin = FALSE;
  28. HANDLE hToken = NULL;
  29. if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken)) {
  30. return FALSE;
  31. }
  32. TOKEN_ELEVATION tokenEle;
  33. DWORD dwRetLen = 0;
  34. if (GetTokenInformation(hToken, TokenElevation, &tokenEle, sizeof(tokenEle), &dwRetLen)) {
  35. if (dwRetLen == sizeof(tokenEle)) {
  36. isRunAsAdmin = tokenEle.TokenIsElevated;
  37. }
  38. }
  39. CloseHandle(hToken);
  40. return isRunAsAdmin;
  41. }
  42. int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev,
  43. _In_ wchar_t *command_line, _In_ int show_command) {
  44. bool isDebugMode = false;
  45. char buffer[2];
  46. if (GetEnvironmentVariableA("DEBUG_MODE", buffer, sizeof(buffer)) > 0) {
  47. isDebugMode = true;
  48. }
  49. // 以管理员权限运行
  50. if (!isDebugMode && !isRunAsAdmin()) {
  51. runAsAdmin();
  52. exit(0);
  53. }
  54. // 捕捉异常
  55. SetUnhandledExceptionFilter((LPTOP_LEVEL_EXCEPTION_FILTER)ApplicationCrashHandler);
  56. // Attach to console when present (e.g., 'flutter run') or create a
  57. // new console when running with a debugger.
  58. if (!::AttachConsole(ATTACH_PARENT_PROCESS) && ::IsDebuggerPresent()) {
  59. CreateAndAttachConsole();
  60. }
  61. // Initialize COM, so that it is available for use in the library and/or
  62. // plugins.
  63. ::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED);
  64. flutter::DartProject project(L"data");
  65. std::vector<std::string> command_line_arguments =
  66. GetCommandLineArguments();
  67. project.set_dart_entrypoint_arguments(std::move(command_line_arguments));
  68. FlutterWindow window(project);
  69. UINT scrWidth, scrHeight, xShaft, yShaft;
  70. double scale_factor_x = 1.0;
  71. double scale_factor_y = 1.0;
  72. // 计算屏幕逻辑尺寸
  73. if (IsWindows10OrGreater()) {
  74. UINT dpiX, dpiY;
  75. HDC screen = GetDC(NULL);
  76. dpiX = GetDeviceCaps(screen, LOGPIXELSX);
  77. dpiY = GetDeviceCaps(screen, LOGPIXELSY);
  78. ReleaseDC(NULL, screen);
  79. scale_factor_x = dpiX / 96.0;
  80. scale_factor_y = dpiY / 96.0;
  81. if (auto user32 = LoadLibraryA("User32.dll")) {
  82. if (auto fn = GetProcAddress(user32, "GetDpiForWindow")) {
  83. MyGetDpiForWindow = (decltype(MyGetDpiForWindow)) fn;
  84. MyGetSystemMetricsForDpi = (decltype(MyGetSystemMetricsForDpi)) GetProcAddress(user32, "GetSystemMetricsForDpi");
  85. }
  86. scrWidth = static_cast<UINT>(round(MyGetSystemMetricsForDpi(SM_CXFULLSCREEN, dpiX) / scale_factor_x));
  87. scrHeight = static_cast<UINT>(round(MyGetSystemMetricsForDpi(SM_CYFULLSCREEN, dpiY) / scale_factor_y));
  88. } else {
  89. scrWidth = GetSystemMetrics(SM_CXSCREEN);
  90. scrHeight = GetSystemMetrics(SM_CYSCREEN);
  91. }
  92. } else {
  93. scrWidth = GetSystemMetrics(SM_CXSCREEN);
  94. scrHeight = GetSystemMetrics(SM_CYSCREEN);
  95. }
  96. // 程序窗口大小
  97. UINT windowWidth = 340, windowHeight = 640;
  98. Win32Window::Size size(windowWidth, windowHeight);
  99. // 计算程序显示坐标原点(屏幕中间)
  100. xShaft = (scrWidth - windowWidth) / 2;
  101. yShaft = (scrHeight - windowHeight) / 2;
  102. Win32Window::Point origin(xShaft, yShaft);
  103. if (!window.Create(APP_WINDOW_NAME, origin, size)) {
  104. return EXIT_FAILURE;
  105. }
  106. window.SetQuitOnClose(true);
  107. // int minWidth = static_cast<int>(360 * scale_factor_x);
  108. // int minHeight = static_cast<int>(640 * scale_factor_y);
  109. // window.SetMinimumSize({minWidth, minHeight});
  110. window.SetMinimumSize(SIZE{ 340, 640 });
  111. // 设置窗口不可最大化以及不可缩放
  112. HWND hWnd = window.GetHandle();
  113. DWORD gwlStyle = GetWindowLong(hWnd, GWL_STYLE);
  114. gwlStyle &= ~WS_THICKFRAME;
  115. gwlStyle &= ~WS_MAXIMIZEBOX;
  116. SetWindowLong(hWnd, GWL_STYLE, gwlStyle);
  117. ::MSG msg;
  118. while (::GetMessage(&msg, nullptr, 0, 0)) {
  119. ::TranslateMessage(&msg);
  120. ::DispatchMessage(&msg);
  121. }
  122. ::CoUninitialize();
  123. return EXIT_SUCCESS;
  124. }