欢迎加入开源鸿蒙PC社区:
https://harmonypc.csdn.net/

atomgit仓库地址: https://atomgit.com/gcw_7DJ1SfsY/PCsuofang
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在开发鸿蒙PC端应用时,窗口配置是一个常见但容易出错的环节。本文将详细记录在实际项目中遇到的窗口配置问题,包括配置文件错误、API调用错误等,并提供完整的解决方案。

问题背景

在开发一个鸿蒙PC端应用时,我们需要对窗口行为进行控制,具体需求是实现窗口不可缩放的功能。在尝试配置过程中,遇到了一系列构建错误,包括配置文件验证失败和编译错误。

遇到的问题

问题一:module.json5配置文件验证失败

第一次构建时,遇到了以下错误:

> hvigor ERROR: Failed :entry:default@PreBuild... 
> hvigor ERROR: 00303038 Configuration Error 
Error Message: Schema validate failed, at file: entry/src/main/module.json5

Error: Property 'windowResizable' does not exist
Error: Property 'windowMode' does not exist

原始配置文件中使用了以下无效属性:

{
  "module": {
    "abilities": [
      {
        "name": "EntryAbility",
        "windowResizable": true,
        "windowMode": "floating"
      }
    ]
  }
}

问题二:API调用不存在

修复配置文件后,又遇到编译错误:

> hvigor ERROR: ArkTS Compiler Error
Error: Property 'setWindowResizable' does not exist on type 'Window'
Error: Property 'setWindowMode' does not exist on type 'Window'
Error: Property 'WindowMode' does not exist on type 'typeof window'
Error: Property 'setWindowMinSize' does not exist on type 'Window'
Error: Property 'setWindowPreferredSize' does not exist on type 'Window'

原始代码中尝试通过API动态设置窗口属性:

mainWindow.setWindowResizable(true);
mainWindow.setWindowMode(window.WindowMode.FLOATING);
mainWindow.setWindowMinSize(400, 300);
mainWindow.setWindowPreferredSize(800, 600);

问题三:supportWindowMode值错误

在尝试修复时,使用了错误的窗口模式值:

Error: must be equal to one of the allowed values
allowedValues: ['fullscreen', 'split', 'floating']

配置中使用了 "fixed" 这个不存在的值:

"supportWindowMode": ["fullscreen", "fixed"]

问题分析

鸿蒙窗口配置机制

在鸿蒙系统中,窗口的行为控制主要通过配置文件实现,而不是通过代码动态设置。这是鸿蒙与传统桌面应用开发的一个重要区别。

配置优先原则:窗口的基本能力(是否可缩放、支持的窗口模式等)在应用安装时就已经确定,通过 module.json5 配置文件声明。这样做的好处是:

  1. 系统可以在应用启动前就知道窗口特性,提前做好资源分配
  2. 避免运行时频繁改变窗口模式带来的性能开销
  3. 提供一致的用户体验,防止应用随意改变窗口行为

配置文件结构

module.json5 是鸿蒙应用的模块配置文件,其中 abilities 数组定义了应用的能力(Ability)。每个Ability可以配置以下窗口相关属性:

属性名类型说明
supportWindowModestring[]支持的窗口模式,可选值:fullscreen、split、floating
minWindowWidthnumber最小窗口宽度(vp)
minWindowHeightnumber最小窗口高度(vp)
maxWindowWidthnumber最大窗口宽度(vp)
maxWindowHeightnumber最大窗口高度(vp)
maxWindowRationumber最大窗口宽高比
minWindowRationumber最小窗口宽高比

窗口模式详解

鸿蒙PC端支持三种窗口模式:

  1. fullscreen(全屏模式)

    • 窗口占据整个屏幕
    • 不显示窗口边框和控制按钮
    • 用户无法调整窗口大小
    • 适用于沉浸式体验的应用,如游戏、视频播放器
  2. split(分屏模式)

    • 窗口可以与其他应用分屏显示
    • 支持拖拽调整分屏比例
    • 适用于需要多任务并行的场景
  3. floating(浮动窗口模式)

    • 窗口以独立浮动窗口形式显示
    • 显示完整的窗口边框和控制按钮(最小化、最大化、关闭)
    • 用户可以自由拖拽调整窗口位置和大小
    • 适用于常规桌面应用

解决方案

核心代码一:正确的配置文件设置

要实现窗口不可缩放,需要在 module.json5 中只声明支持全屏模式:

{
  "module": {
    "name": "entry",
    "type": "entry",
    "description": "$string:module_desc",
    "mainElement": "EntryAbility",
    "deviceTypes": [
      "2in1"
    ],
    "deliveryWithInstall": true,
    "installationFree": false,
    "pages": "$profile:main_pages",
    "abilities": [
      {
        "name": "EntryAbility",
        "srcEntry": "./ets/entryability/EntryAbility.ets",
        "description": "$string:EntryAbility_desc",
        "icon": "$media:layered_image",
        "label": "$string:EntryAbility_label",
        "startWindowIcon": "$media:startIcon",
        "startWindowBackground": "$color:start_window_background",
        "exported": true,
        "skills": [
          {
            "entities": [
              "entity.system.home"
            ],
            "actions": [
              "ohos.want.action.home"
            ]
          }
        ],
        // 只支持全屏模式,窗口不可缩放
        "supportWindowMode": ["fullscreen"]
      }
    ]
  }
}

关键点说明

  • deviceTypes: ["2in1"] 表示这是一个PC端应用(2in1设备)
  • supportWindowMode: ["fullscreen"] 只声明支持全屏模式,系统不会显示窗口控制按钮
  • 不需要设置 minWindowWidthminWindowHeight,因为全屏模式下这些配置无效

核心代码二:支持窗口缩放的配置

如果需要支持窗口缩放,应该配置浮动窗口模式:

{
  "module": {
    "abilities": [
      {
        "name": "EntryAbility",
        // 支持全屏和浮动两种模式
        "supportWindowMode": ["fullscreen", "floating"],
        // 设置窗口最小尺寸限制
        "minWindowWidth": 400,
        "minWindowHeight": 300,
        // 可选:设置窗口最大尺寸限制
        "maxWindowWidth": 1920,
        "maxWindowHeight": 1080
      }
    ]
  }
}

关键点说明

  • supportWindowMode 数组可以包含多个值,表示应用支持多种窗口模式
  • 包含 "floating" 时,窗口会显示边框和控制按钮,用户可以缩放窗口
  • minWindowWidthminWindowHeight 防止用户将窗口缩放到过小导致UI变形
  • 尺寸单位是 vp(虚拟像素),会根据屏幕密度自动适配

核心代码三:EntryAbility中的正确处理方式

在代码中,不应该尝试调用不存在的窗口设置API。正确的做法是:

import { AbilityConstant, ConfigurationConstant, UIAbility, Want } from '@kit.AbilityKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
import { window } from '@kit.ArkUI';
import { BusinessError } from '@kit.BasicServicesKit';

const DOMAIN = 0x0000;

export default class EntryAbility extends UIAbility {
  onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
    try {
      this.context.getApplicationContext().setColorMode(
        ConfigurationConstant.ColorMode.COLOR_MODE_NOT_SET
      );
    } catch (err) {
      hilog.error(DOMAIN, 'testTag', 'Failed to set colorMode. Cause: %{public}s', 
        JSON.stringify(err));
    }
    hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onCreate');
  }

  onDestroy(): void {
    hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onDestroy');
  }

  onWindowStageCreate(windowStage: window.WindowStage): void {
    hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onWindowStageCreate');

    // 窗口配置说明:
    // 在鸿蒙中,窗口的缩放能力和模式通过 module.json5 配置
    // - supportWindowMode: ["fullscreen"] 只支持全屏,窗口不可缩放
    // - supportWindowMode: ["fullscreen", "floating"] 支持浮动窗口,可缩放

    // 如需动态调整窗口大小,可使用 resize() 方法
    try {
      windowStage.getMainWindow((err: BusinessError, mainWindow: window.Window) => {
        if (err) {
          hilog.error(DOMAIN, 'testTag', 'Failed to get main window. Cause: %{public}s', 
            JSON.stringify(err));
          return;
        }

        // 设置窗口初始大小(仅在浮动模式下有效)
        mainWindow.resize(800, 600, (err: BusinessError) => {
          if (err) {
            hilog.error(DOMAIN, 'testTag', 'Failed to resize window. Cause: %{public}s', 
              JSON.stringify(err));
            return;
          }
          hilog.info(DOMAIN, 'testTag', 'Window size set to 800x600');
        });
      });
    } catch (e) {
      hilog.error(DOMAIN, 'testTag', 'Window configuration exception: %{public}s', 
        JSON.stringify(e));
    }

    windowStage.loadContent('pages/Index', (err) => {
      if (err.code) {
        hilog.error(DOMAIN, 'testTag', 'Failed to load the content. Cause: %{public}s', 
          JSON.stringify(err));
        return;
      }
      hilog.info(DOMAIN, 'testTag', 'Succeeded in loading the content.');
    });
  }

  onWindowStageDestroy(): void {
    hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onWindowStageDestroy');
  }

  onForeground(): void {
    hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onForeground');
  }

  onBackground(): void {
    hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onBackground');
  }
}

关键点说明

  • 不要使用 setWindowResizable()setWindowMode() 等不存在的API
  • 可以使用 resize(width, height) 方法动态调整窗口大小
  • resize() 方法只在浮动窗口模式下有效,全屏模式下调用会被忽略

核心代码四:窗口尺寸限制的最佳实践

在实际项目中,合理的窗口尺寸限制可以提升用户体验:

{
  "module": {
    "abilities": [
      {
        "name": "EntryAbility",
        "supportWindowMode": ["fullscreen", "floating"],
        // 最小尺寸:确保UI元素可读
        "minWindowWidth": 800,
        "minWindowHeight": 600,
        // 最大尺寸:防止在大屏幕上窗口过大
        "maxWindowWidth": 1920,
        "maxWindowHeight": 1080,
        // 宽高比限制:保持UI布局合理性
        "minWindowRatio": 0.5,   // 最小宽高比 1:2
        "maxWindowRatio": 2.0    // 最大宽高比 2:1
      }
    ]
  }
}

配置建议

应用类型最小宽度最小高度最大宽度最大高度说明
文档编辑器80060019201080需要足够的编辑空间
聊天应用4005001200900可以保持较小窗口
图片查看器300300无限制无限制根据图片尺寸自适应
开发工具1024768无限制无限制需要大工作区域
设置面板500400800600固定范围,保持紧凑

常见错误对照表

在开发过程中,容易混淆的配置项和API:

错误用法正确用法说明
windowResizable: truesupportWindowMode: ["floating"]配置文件中不存在windowResizable属性
windowMode: "floating"supportWindowMode: ["floating"]应使用数组格式的supportWindowMode
supportWindowMode: ["fixed"]supportWindowMode: ["fullscreen"]不存在fixed模式,应使用fullscreen
mainWindow.setWindowResizable()配置文件设置不存在此API,应通过配置文件控制
mainWindow.setWindowMode()配置文件设置不存在此API,应通过配置文件控制
mainWindow.setWindowMinSize()配置minWindowWidth/Height不存在此API,应通过配置文件设置
window.WindowMode.FLOATING配置文件设置不存在WindowMode枚举

调试技巧

查看当前窗口模式

在代码中可以获取当前窗口的状态信息:

windowStage.getMainWindow((err, mainWindow) => {
  if (err) {
    return;
  }
  
  // 获取窗口属性
  mainWindow.getProperties((err, properties) => {
    if (err) {
      return;
    }
    
    hilog.info(DOMAIN, 'testTag', 'Window width: %{public}d', properties.windowRect.width);
    hilog.info(DOMAIN, 'testTag', 'Window height: %{public}d', properties.windowRect.height);
    hilog.info(DOMAIN, 'testTag', 'Window mode: %{public}d', properties.mode);
  });
});

验证配置是否生效

构建后可以查看生成的 module.json 文件(在 build/intermediates/merge_profile/default/ 目录下),确认配置是否正确合并:

{
  "module": {
    "abilities": [
      {
        "name": "EntryAbility",
        "supportWindowMode": ["fullscreen"]
      }
    ]
  }
}

完整修复流程

步骤一:清理错误配置

首先检查 module.json5 文件,移除所有无效的配置项:

// ❌ 删除这些无效配置
"windowResizable": true,
"windowMode": "floating"

步骤二:添加正确配置

根据需求添加正确的窗口模式配置:

// ✅ 窗口不可缩放
"supportWindowMode": ["fullscreen"]

// 或 ✅ 窗口可缩放
"supportWindowMode": ["fullscreen", "floating"],
"minWindowWidth": 400,
"minWindowHeight": 300

步骤三:清理错误代码

检查 EntryAbility.ets 文件,移除所有不存在的API调用:

// ❌ 删除这些不存在的API
mainWindow.setWindowResizable(true);
mainWindow.setWindowMode(window.WindowMode.FLOATING);
mainWindow.setWindowMinSize(400, 300);
mainWindow.setWindowPreferredSize(800, 600);

步骤四:重新构建

完成修改后,执行构建命令验证:

hvigorw --mode module -p module=entry@default -p product=default assembleHap

总结

鸿蒙PC端窗口配置与传统桌面应用开发有显著差异,主要体现在:

  1. 配置优先:窗口行为通过配置文件声明,而非代码动态设置
  2. 模式明确:三种窗口模式(fullscreen、split、floating)对应不同的用户交互方式
  3. API受限:不存在传统桌面开发中的窗口设置API,需要适应新的开发模式

理解这些差异,正确使用配置文件,是开发鸿蒙PC应用的基础。遇到类似问题时,应该:

  1. 查阅官方文档,确认配置项和API的有效性
  2. 理解配置与代码的职责划分
  3. 使用正确的配置方式实现需求
  4. 通过构建日志定位具体错误位置

希望本文能帮助开发者快速解决鸿蒙PC端窗口配置问题,避免踩坑。

Logo

赋能鸿蒙PC开发者,共建全场景原生生态,共享一次开发多端部署创新价值。

更多推荐