已经使用flutter创建了工程, flutter run -d windows 即可启动桌面应用,
但是我们的应用相当于是从手机APP移植过来的, 为了减少适配问题, 不希望用户能改变窗口大小, 还有窗口的标题也需要修改, 这些在flutter工程中是做不到的, 那么应该怎么处理呢?
在项目的 windows 目录下是windows项目容器(壳)相关内容, 里面有一个runner 和 flutter 文件夹
runner: 工程的主要配置flutter: 这里面主要是注册插件相关的内容
首页根目录下包括上面两个目录下都有 CMakeLists.txt 这个文件, 这是做什么用的呢?
CMake通过CMakeLists.txt配置项目的构建系统,配合使用cmake命令行工具生成构建系统并执行编译、测试,相比于手动编写构建系统(如Makefile)要高效许多。对于C/C++项目开发,非常值得学习掌握。
看到runner下面有个 win32_window.h 就去看了一眼, 里面找到了这个方法
// Creates a win32 window with |title| that is positioned and sized using
// |origin| and |size|. New windows are created on the default monitor. Window
// sizes are specified to the OS in physical pixels, hence to ensure a
// consistent size this function will scale the inputted width and height as
// as appropriate for the default monitor. The window is invisible until
// |Show| is called. Returns true if the window was created successfully.
bool Create(const std::wstring& title, const Point& origin, const Size& size);
看注释好像完全是符合我们的目标的, 然后查找下引用,
插一句, 写到这里有点受不了憨憨的visual studio了, 什么宇宙最强IDE, 然后去换了CLion
CLion直接无法正常解析项目...
尴尬至极, 然后我们去main.cpp里看下调用吧,
FlutterWindow window(project);
Win32Window::Point origin(10, 10);
Win32Window::Size size(1280, 720);
if (!window.Create(L"riverpod_hooks_starter", origin, size)) {
return EXIT_FAILURE;
}
window.SetQuitOnClose(true);
FlutterWindow 是 继承自 Win32Window的类, 这里大概明白是创建了一个(10, 10, 1280, 720)的窗口, 我们的应用是竖屏, 那么先改成 (10, 10, 600, 800) 看看效果, 顺便改下title
Win32Window::Point origin(10, 10);
Win32Window::Size size(600, 800);
if (!window.Create(L"Welcome", origin, size)) {
return EXIT_FAILURE;
}
行了嘿, 再看看怎么限制用户的拖拽窗口大小,
回头去看那个Create方法的实现
HWND window = CreateWindow(
window_class, title.c_str(), WS_OVERLAPPEDWINDOW,
Scale(origin.x, scale_factor), Scale(origin.y, scale_factor),
Scale(size.width, scale_factor), Scale(size.height, scale_factor),
nullptr, nullptr, GetModuleHandle(nullptr), this);
核心就是这个CreateWindow了, 看了下他不是方法, 而是一个Macro,
#define CreateWindowA(lpClassName, lpWindowName, dwStyle, x, y,\
nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam)\
CreateWindowExA(0L, lpClassName, lpWindowName, dwStyle, x, y,\
nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam)
#define CreateWindowW(lpClassName, lpWindowName, dwStyle, x, y,\
nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam)\
CreateWindowExW(0L, lpClassName, lpWindowName, dwStyle, x, y,\
nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam)
#ifdef UNICODE
#define CreateWindow CreateWindowW
#else
#define CreateWindow CreateWindowA
#endif // !UNICODE
再往内部的实现现在暂时看不到, 去看看官方文档怎么说的吧
然后搜到了这个 CreateWindowExA function (winuser.h) - Win32 apps | Microsoft Learn
好吧, 现在才知道这是win32开发, 也是比较陈旧的了, 负面还比较多, 最新的应该是MAUI,
然后第三个参数的常量是 窗口样式 (Winuser.h) - Win32 apps | Microsoft Learn
使用异或(^)来调整样式
HWND window = CreateWindow(
window_class, title.c_str(), WS_OVERLAPPEDWINDOW^WS_THICKFRAME^WS_MAXIMIZEBOX,
Scale(origin.x, scale_factor), Scale(origin.y, scale_factor),
Scale(size.width, scale_factor), Scale(size.height, scale_factor),
nullptr, nullptr, GetModuleHandle(nullptr), this);
行了嘿, 窗口大小也不能调整了, 最大化按钮也失效了, 完美。