鸿蒙Harmony-Next 徒手撸一个日历控件
本文将介绍如何使用鸿蒙Harmony-Next框架实现一个自定义的日历控件。我们将创建一个名为CalendarView的组件(注意,这里不能叫 Calendar因为系统的日历叫这个),它具有以下功能:
- 显示当前月份的日历
- 支持选择日期
- 显示农历日期
- 可以切换上一月和下一月
组件结构
我们的CalendarView组件主要由以下部分组成:
- 月份导航栏
- 星期标题
- 日期网格
实现代码
@Component
export struct CalendarView {// 组件状态@State selectedDate: Date = new Date()@State isDateSelected: boolean = false@State currentMonth: number = new Date().getMonth()@State currentYear: number = new Date().getFullYear()build() {Column() {// 月份导航栏Row() {// ... 月份切换和显示逻辑 ...}// 星期标题Row() {// ... 星期标题显示逻辑 ...}// 日期网格Grid() {// ... 日期显示和选择逻辑 ...}}}// ... 其他辅助方法 ...
}
关键功能实现
1. 月份切换
通过onMonthChange方法实现月份的切换:
private onMonthChange(increment: number) {// ... 月份切换逻辑 ...
}
2. 日期选择
使用onDateSelected方法处理日期选择:
private onDateSelected(day: number) {// ... 日期选择逻辑 ...
}
3. 农历日期显示
利用LunarDate类来计算和显示农历日期:
private getLunarDate(day: number): string {return LunarDate.solarToLunar(this.currentYear, this.currentMonth + 1, day);
}
4. 日期颜色处理
根据日期状态(过去、当前、选中)设置不同的颜色:
private getDateColor(day: number): string {// ... 日期颜色逻辑 ...
}
农历日期转换(LunarDate农历算法实现)
LunarDate类来实现公历到农历的转换,本算法实现主要依赖于预先编码的农历数据和巧妙的位运算 , 优点是计算速度快,代码相对简洁。但缺点是依赖于预先编码的数据,如果需要扩展到1900年之前或2100年之后,就需要额外的数据,及算法上的调整。这个类包含了大量的位运算, 主要方法包括:
solarToLunar: 将公历日期转换为农历日期getLunarYearDays: 计算农历年的总天数getLeapMonth: 获取闰月getLeapDays: 获取闰月的天数getLunarMonthDays: 获取农历月的天数
1. 农历数据编码
private static lunarInfo: number[] = [0x04bd8, 0x04ae0, 0x0a570, /* ... 更多数据 ... */
];
这个数组包含了从1900年到2100年的农历数据编码。每个数字都是一个16位的二进制数,包含了该年的闰月、大小月等信息。
- 最后4位: 表示闰月的月份,为0则表示没有闰月。
- 中间12位: 分别代表12个月,为1表示大月(30天),为0表示小月(29天)。
- 最高位: 闰月是大月还是小月,仅当存在闰月时有意义。
2. 公历转农历的核心算法
static solarToLunar(year: number, month: number, day: number): string {// ... 前置检查代码 ...let offset = Math.floor((objDate.getTime() - baseDate.getTime()) / 86400000);// 1. 计算农历年for (i = 1900; i < 2101 && offset > 0; i++) {temp = LunarDate.getLunarYearDays(i);offset -= temp;}const lunarYear = i - 1;// 2. 计算闰月leap = LunarDate.getLeapMonth(lunarYear);isLeap = false;// 3. 计算农历月和日for (i = 1; i < 13 && offset > 0; i++) {// ... 月份计算逻辑 ...}const lunarMonth = i;const lunarDay = offset + 1;// 4. 转换为农历文字表示return dayStr === '初一' ? monthStr + "月" : dayStr;
}
主要步骤是:
- 计算从1900年1月31日(农历1900年正月初一)到目标日期的总天数。
- 逐年递减这个天数,确定农历年份。
- 确定该年是否有闰月,以及闰月的位置。
- 逐月递减剩余天数,确定农历月份和日期。
- 将数字转换为对应的农历文字表示。
3. 辅助方法
获取农历年的总天数
private static getLunarYearDays(year: number): number {let i = 0, sum = 348;for (i = 0x8000; i > 0x8; i >>= 1) {sum += (LunarDate.lunarInfo[year - 1900] & i) ? 1 : 0;}return sum + LunarDate.getLeapDays(year);
}
这个方法通过位运算来计算一年中每个月的天数,再加上闰月的天数(如果有的话)。
获取闰月信息
private static getLeapMonth(year: number): number {return LunarDate.lunarInfo[year - 1900] & 0xf;
}private static getLeapDays(year: number): number {if (LunarDate.getLeapMonth(year)) {return (LunarDate.lunarInfo[year - 1900] & 0x10000) ? 30 : 29;}return 0;
}
这些方法用于确定某一年是否有闰月,以及闰月的具体月份和天数。
获取农历月的天数
private static getLunarMonthDays(year: number, month: number): number {return (LunarDate.lunarInfo[year - 1900] & (0x10000 >> month)) ? 30 : 29;
}
这个方法通过位运算来确定某个农历月是大月(30天)还是小月(29天)。
完整的代码如下:
@Component
export struct CalendarView {@State selectedDate: Date = new Date()@State isDateSelected: boolean = false@State currentMonth: number = new Date().getMonth()@State currentYear: number = new Date().getFullYear()build() {Column() {Row() {Text('上一月').fontColor('#165dff').decoration({type: TextDecorationType.Underline,color: '#165dff'}).onClick(() => this.onMonthChange(-1))Text(`${this.currentYear}年${this.currentMonth + 1}月`).fontSize(20).fontWeight(FontWeight.Bold).margin({ left: 15, right: 15 })Text('下一月').fontColor('#165dff').decoration({type: TextDecorationType.Underline,color: '#165dff'}).onClick(() => this.onMonthChange(1))}.width('100%').justifyContent(FlexAlign.Center).margin({ top: 20, bottom: 30 })// 星期标题Row() {ForEach(['日', '一', '二', '三', '四', '五', '六'], (day: string) => {Text(day).width('14%').textAlign(TextAlign.Center).fontSize(18).fontColor('#999999')}, (day: string) => day)}.margin({ bottom: 10 })Grid() {ForEach(this.getDaysInMonth(), (day: number) => {GridItem() {Column() {Text(day.toString()).fontSize(18).fontWeight(this.isSelectedDate(day) ? FontWeight.Bold : FontWeight.Normal).fontColor(this.getDateColor(day))Text(this.getLunarDate(day)).fontSize(12).fontColor(this.getDateColor(day))}.width('100%').height('100%').borderRadius(25).backgroundColor(this.isSelectedDate(day) ? '#007DFF' : Color.Transparent).justifyContent(FlexAlign.Center)}.aspectRatio(1).onClick(() => this.onDateSelected(day))}, (day: number) => day.toString())}.width('100%').columnsTemplate('1fr 1fr 1fr 1fr 1fr 1fr 1fr').rowsGap(8).columnsGap(8)}.width('100%').padding({ left: 16, right: 16, top: 16, bottom: 16 }).backgroundColor('#F5F5F5')}private onMonthChange(increment: number) {let newMonth = this.currentMonth + incrementlet newYear = this.currentYearif (newMonth > 11) {newMonth = 0newYear++} else if (newMonth < 0) {newMonth = 11newYear--}this.currentMonth = newMonththis.currentYear = newYear}private onDateSelected(day: number) {const newSelectedDate = new Date(this.currentYear, this.currentMonth, day)if (this.isDateSelected &&this.selectedDate.getDate() === day &&this.selectedDate.getMonth() === this.currentMonth &&this.selectedDate.getFullYear() === this.currentYear) {// 如果点击的是已选中的日期,取消选中this.isDateSelected = false} else {// 否则,选中新的日期this.selectedDate = newSelectedDatethis.isDateSelected = true}}private isSelectedDate(day: number): boolean {return this.isDateSelected &&this.selectedDate.getDate() === day &&this.selectedDate.getMonth() === this.currentMonth &&this.selectedDate.getFullYear() === this.currentYear}private getDaysInMonth(): number[] {const daysInMonth = new Date(this.currentYear, this.currentMonth + 1, 0).getDate()return Array.from<number, number>({ length: daysInMonth }, (_, i) => i + 1)}private getDateColor(day: number): string {const currentDate = new Date(this.currentYear, this.currentMonth, day)const today = new Date()today.setHours(0, 0, 0, 0)if (currentDate < today) {return '#CCCCCC' // 灰色显示过去的日期} else if (this.isSelectedDate(day)) {return '#ffffff' // 选中日期的文字颜色} else {return '#000000' // 未选中日期的文字颜色}}private getLunarDate(day: number): string {return LunarDate.solarToLunar(this.currentYear, this.currentMonth + 1, day);}
}class LunarDate {private static lunarInfo: number[] = [0x04bd8, 0x04ae0, 0x0a570, 0x054d5, 0x0d260, 0x0d950, 0x16554, 0x056a0, 0x09ad0, 0x055d2,0x04ae0, 0x0a5b6, 0x0a4d0, 0x0d250, 0x1d255, 0x0b540, 0x0d6a0, 0x0ada2, 0x095b0, 0x14977,0x04970, 0x0a4b0, 0x0b4b5, 0x06a50, 0x06d40, 0x1ab54, 0x02b60, 0x09570, 0x052f2, 0x04970,0x06566, 0x0d4a0, 0x0ea50, 0x06e95, 0x05ad0, 0x02b60, 0x186e3, 0x092e0, 0x1c8d7, 0x0c950,0x0d4a0, 0x1d8a6, 0x0b550, 0x056a0, 0x1a5b4, 0x025d0, 0x092d0, 0x0d2b2, 0x0a950, 0x0b557,0x06ca0, 0x0b550, 0x15355, 0x04da0, 0x0a5d0, 0x14573, 0x052d0, 0x0a9a8, 0x0e950, 0x06aa0,0x0aea6, 0x0ab50, 0x04b60, 0x0aae4, 0x0a570, 0x05260, 0x0f263, 0x0d950, 0x05b57, 0x056a0,0x096d0, 0x04dd5, 0x04ad0, 0x0a4d0, 0x0d4d4, 0x0d250, 0x0d558, 0x0b540, 0x0b5a0, 0x195a6,0x095b0, 0x049b0, 0x0a974, 0x0a4b0, 0x0b27a, 0x06a50, 0x06d40, 0x0af46, 0x0ab60, 0x09570,0x04af5, 0x04970, 0x064b0, 0x074a3, 0x0ea50, 0x06b58, 0x055c0, 0x0ab60, 0x096d5, 0x092e0,0x0c960, 0x0d954, 0x0d4a0, 0x0da50, 0x07552, 0x056a0, 0x0abb7, 0x025d0, 0x092d0, 0x0cab5,0x0a950, 0x0b4a0, 0x0baa4, 0x0ad50, 0x055d9, 0x04ba0, 0x0a5b0, 0x15176, 0x052b0, 0x0a930,0x07954, 0x06aa0, 0x0ad50, 0x05b52, 0x04b60, 0x0a6e6, 0x0a4e0, 0x0d260, 0x0ea65, 0x0d530,0x05aa0, 0x076a3, 0x096d0, 0x04bd7, 0x04ad0, 0x0a4d0, 0x1d0b6, 0x0d250, 0x0d520, 0x0dd45,0x0b5a0, 0x056d0, 0x055b2, 0x049b0, 0x0a577, 0x0a4b0, 0x0aa50, 0x1b255, 0x06d20, 0x0ada0];private static Gan = ["甲", "乙", "丙", "丁", "戊", "己", "庚", "辛", "壬", "癸"];private static Zhi = ["子", "丑", "寅", "卯", "辰", "巳", "午", "未", "申", "酉", "戌", "亥"];private static Animals = ["鼠", "牛", "虎", "兔", "龙", "蛇", "马", "羊", "猴", "鸡", "狗", "猪"];private static lunarMonths = ["正", "二", "三", "四", "五", "六", "七", "八", "九", "十", "冬", "腊"];private static lunarDays = ["初一", "初二", "初三", "初四", "初五", "初六", "初七", "初八", "初九", "初十","十一", "十二", "十三", "十四", "十五", "十六", "十七", "十八", "十九", "二十","廿一", "廿二", "廿三", "廿四", "廿五", "廿六", "廿七", "廿八", "廿九", "三十"];static solarToLunar(year: number, month: number, day: number): string {if (year < 1900 || year > 2100) {return "无效年份";}const baseDate = new Date(1900, 0, 31);const objDate = new Date(year, month - 1, day);let offset = Math.floor((objDate.getTime() - baseDate.getTime()) / 86400000);let i: number, leap = 0, temp = 0;for (i = 1900; i < 2101 && offset > 0; i++) {temp = LunarDate.getLunarYearDays(i);offset -= temp;}if (offset < 0) {offset += temp;i--;}const lunarYear = i;leap = LunarDate.getLeapMonth(i);let isLeap = false;for (i = 1; i < 13 && offset > 0; i++) {if (leap > 0 && i === (leap + 1) && isLeap === false) {--i;isLeap = true;temp = LunarDate.getLeapDays(lunarYear);} else {temp = LunarDate.getLunarMonthDays(lunarYear, i);}if (isLeap === true && i === (leap + 1)) {isLeap = false;}offset -= temp;}if (offset === 0 && leap > 0 && i === leap + 1) {if (isLeap) {isLeap = false;} else {isLeap = true;--i;}}if (offset < 0) {offset += temp;--i;}const lunarMonth = i;const lunarDay = offset + 1;const monthStr = (isLeap ? "闰" : "") + LunarDate.lunarMonths[lunarMonth - 1];const dayStr = LunarDate.lunarDays[lunarDay - 1];return dayStr === '初一' ? monthStr + "月" : dayStr;}private static getLunarYearDays(year: number): number {let i = 0, sum = 348;for (i = 0x8000; i > 0x8; i >>= 1) {sum += (LunarDate.lunarInfo[year - 1900] & i) ? 1 : 0;}return sum + LunarDate.getLeapDays(year);}private static getLeapMonth(year: number): number {return LunarDate.lunarInfo[year - 1900] & 0xf;}private static getLeapDays(year: number): number {if (LunarDate.getLeapMonth(year)) {return (LunarDate.lunarInfo[year - 1900] & 0x10000) ? 30 : 29;}return 0;}private static getLunarMonthDays(year: number, month: number): number {return (LunarDate.lunarInfo[year - 1900] & (0x10000 >> month)) ? 30 : 29;}
}
使用
Column() {CalendarView()}.width('100%').height('100%').backgroundColor('#F5F5F5')
最终的效果如下:

至此我们就徒手撸了一个日历控件的实现了, 各位可以基于这个基础实现,进一步扩展相关的功能,如添加事件标记、自定义主题等,以满足不同应用场景的需求。
相关文章:
鸿蒙Harmony-Next 徒手撸一个日历控件
本文将介绍如何使用鸿蒙Harmony-Next框架实现一个自定义的日历控件。我们将创建一个名为CalendarView的组件(注意,这里不能叫 Calendar因为系统的日历叫这个),它具有以下功能: 显示当前月份的日历支持选择日期显示农历日期可以切换上一月和下一月 组件…...
直播音频解决方案
音频解决方案公司具体解决的是什么样的问题?什么样的客户需要找音频方案公司?相信还是有很多人不是很了解。音频解决方案公司工作就像是为音频设备“量身定制衣服”,帮助客户解决各种音频相关的问题。无论你是音响制造商、会议设备商、耳机品…...
Git基本用法总结
设置全局用户名 git config --global user.name xxx #设置全局用户名 设置全局邮箱地址 git config --global user.email xxxxxx.com #设置全局邮箱地址 查看所有的 Git 配置,包括用户信息 git config --list #查看所有的 Git 配置,包括用户信…...
SQLite的入门级项目学习记录(四)
性能评估和测试 规划项目 1、框架选择:前端交互和线程控制用pyside,SQLite作为数据库支持。 2、预估数据量:每秒10个数据,每个月约26000000(26M)条。 3、压力测试:首先用python脚本创建一个数据…...
Docker工作目录迁移
文章目录 前言一、迁移步骤1.停掉docker服务2.创建存储目录3.迁移docker数据4.备份5.添加软链接6.重启docker服务,测试 总结 前言 安装docker,默认的情况容器的默认存储路径会存储系统盘的 /var/lib/docker 目录下,系统盘一般默认 50G&#…...
【多维动态规划】64. 最小路径和(面试真题+面试官调整后的题目)
64. 最小路径和 难度:中等 力扣地址:https://leetcode.cn/problems/minimum-path-sum/description/ 1. 原题以及解法 1.1 题目 给定一个包含非负整数的 m x n 网格 grid ,请找出一条从左上角到右下角的路径,使得路径上的数字总和…...
Web后端开发技术:RESTful 架构详解
RESTful 是一种基于 REST(表述性状态转移,Representational State Transfer)架构风格的 API 设计方式,通常用于构建分布式系统,特别是在 Web 应用开发中广泛应用。REST 是一种轻量级的架构模式,利用标准的 …...
【Fastapi】参数获取,json和query
【Fastapi】参数获取,json和query 前言giteegithub query形式json传递同步方法使用json 前言 花了半个月的时间看了一本小说,懈怠了…今天更新下fastapi框架的参数获取 gitee https://gitee.com/zz1521145346/fastapi_frame.git github https://git…...
【Node.js】初识微服务
概述 Node.js 的微服务架构是一种通过将应用程序分解为独立的、松耦合的小服务的方式进行系统设计。 每个微服务负责处理一个特定的业务功能,并且这些服务可以独立开发、部署、扩展和管理,并且可以通讯。 它的核心思想就是解耦。 微服务和微前端是类…...
React项目实战(React后台管理系统、TypeScript+React18)
### 项目地址:(线上发布) (1)别人的项目地址 gitgitee.com:zqingle/lege-react-management.git (2)我自己的项目地址 gitgitee.com:huihui-999/lege-react-management.git ### B站讲解视频地址 https://www.bilibili.com/video/BV1FV4y157Zx?p37&spm_id_frompageDrive…...
【专题】2024中国生物医药出海现状与趋势蓝皮书报告合集PDF分享(附原数据表)
原文链接:https://tecdat.cn/?p37719 出海已成为中国医药产业实现提速扩容的重要途径。目前,中国医药产业发展态势良好,创新能力不断增强,然而也面临着医保政策改革和带量集采带来的压力。政府积极出台多项政策支持医药企业出海…...
【iOS】KVC
文章目录 KVC的定义 容器类中KVC的实现 KVC设值 KVC取值 KVC使用KeyPath KVC处理异常 KVC处理设值nil异常 KVC处理UndefinedKey异常 KVC处理数值和结构体类型属性 KVC键值验证 KVC处理集合 简单集合运算符 对象运算符 KVC处理字典 KVC应用 动态地取值和设值 用…...
【2024年华为杯研究生数学建模竞赛C题】完整论文与代码
这里写目录标题 基于数据驱动下磁性元件的磁芯损耗建模一、问题重述1.1问题背景1.2问题回顾 问题分析与模型假设模型建立与求解 基于数据驱动下磁性元件的磁芯损耗建模 一、问题重述 1.1问题背景 在现代电力电子和变压器设计中,磁性元件是确保能量高效传递和系统稳…...
svn回退到以前历史版本修改并上传
svn回退到以前版本,并在以前版本上修改代码后,上传到svn库当中,如下步骤: 3、 以回退到版本号4为例:选中版本号4,右键->Revert to this version,在出现的对话框中 点击yes! 4、 5、...
fiddler抓包07_抓IOS手机请求
课程大纲 前提:电脑和手机连接同一个局域网 (土小帽电脑和手机都连了自己的无线网“tuxiaomao”。) 原理如下: 电脑浏览器抓包时,直接就是本机网络。手机想被电脑Fiddler抓包,就要把Fiddler变成手机和网络…...
Windows系统及Ubuntu系统安装Java
Java语言简介 Java是一种高级编程语言,Java语言的创始可以追溯到1990年代初,当时任职于Sun Microsystems(后来被甲骨文公司收购)的詹姆斯高斯林(James Gosling)等人开始开发一种名为“Oak”(名字来源于詹姆…...
uni-data-select 使用 localdata 传入数据出现 不回显 | 下拉显示错误的 解决方法
目录 1. 问题所示2. 正确Demo3. 下拉显示错误(Bug复现)4. 下拉不回显(Bug复现)1. 问题所示 uni-app的下拉框uni-data-select 使用 localdata 传入数据 主要总结正确的Demo以及复现一些Bug 数据不回显数据不显示下拉选项2. 正确Demo 详细的基本知识推荐阅读:uni-app中的…...
图解 TCP 四次挥手|深度解析|为什么是四次|为什么要等2MSL
写在前面 今天我们来图解一下TCP的四次挥手、深度解析为什么是四次? 上一片文章我们已经介绍了TCP的三次握手 解析四次挥手 数据传输完毕之后,通信的双方都可释放连接。现在客户端A和服务端B都处于ESTABLISHED状态。 第一次挥手 客户端A的应用进…...
DevExpress中文教程:如何将WinForms数据网格连接到ASP. NET Core WebAPI服务?
日前DevExpress官方发布了DevExpress WinForms的后续版本——将.NET桌面客户端连接到安全后端Web API服务(EF Core with OData),在本文中我们将进一步演示如何使用一个更简单的服务来设置DevExpress WinForms数据网格。 P.S:DevExpress WinForms拥有180…...
SpringBoot3核心特性-核心原理
目录 传送门前言一、事件和监听器1、生命周期监听2、事件触发时机 二、自动配置原理1、入门理解1.1、自动配置流程1.2、SPI机制1.3、功能开关 2、进阶理解2.1、 SpringBootApplication2.2、 完整启动加载流程 三、自定义starter1、业务代码2、基本抽取3、使用EnableXxx机制4、完…...
避坑指南:Flutter混合开发时Android依赖冲突的终极解决方案(含阿里云镜像配置)
Flutter混合开发中Android依赖冲突的深度解决方案与优化实践 Flutter混合开发已经成为许多团队的首选方案,但当你试图在现有Android项目中集成Flutter模块时,依赖冲突问题往往会让你陷入"构建地狱"。特别是当不同模块对同一库有不同版本要求时…...
Qwen3.5-9B惊艳效果:食品包装图片→成分表识别→过敏原标记→健康评分生成
Qwen3.5-9B惊艳效果:食品包装图片→成分表识别→过敏原标记→健康评分生成 1. 模型能力概览 Qwen3.5-9B作为新一代多模态大模型,在食品健康领域展现出令人惊艳的端到端处理能力。它能从一张简单的食品包装照片开始,自动完成成分表识别、过敏…...
StructBERT模型Transformer架构深度解析:从原理到相似度计算实践
StructBERT模型Transformer架构深度解析:从原理到相似度计算实践 1. 引言 如果你对自然语言处理(NLP)感兴趣,一定听说过BERT、GPT这些名字。它们背后的核心引擎,就是Transformer。今天我们要聊的StructBERTÿ…...
提示工程架构师访谈:文化科技融合的未来在哪里?
提示工程架构师视角下的文化科技融合:从技术赋能到范式重构 元数据框架 标题 提示工程架构师视角下的文化科技融合:从技术赋能到范式重构 关键词 提示工程、文化科技融合、大语言模型(LLM)、语义接口设计、数字人文、生成式AI、文…...
避坑指南:北醒TFmini-S雷达连接上位机,数据曲线不显示?可能是这个鼠标操作惹的祸
北醒TFmini-S雷达上位机波形图消失的深度排查与交互优化指南 当你在深夜赶工,盯着北醒TFmini-S雷达的上位机界面,明明距离数值在跳动,波形图区域却像被施了隐身咒——这种抓狂时刻我经历过太多次。作为工业自动化领域的常用传感器,…...
基于PI+重复控制的三相APF仿真系统:特点与应用
可基于PI重复控制的三相APF仿真系统,直流电压700V,采用PI控制。 接LCL滤波器,带非线性负载。 特点: 1)采用并联型APF有源滤波器 2)谐波检测采用dq方法 3)电压环采用PI控制,定性好 (若稳定性较差,会影响补偿效果) 4)电流…...
终极指南:如何利用Spinnaker实现合规报告自动化——清晰、准确、及时的最佳实践
终极指南:如何利用Spinnaker实现合规报告自动化——清晰、准确、及时的最佳实践 【免费下载链接】spinnaker spinnaker - 这是一个开源的持续交付和持续集成平台,用于自动化部署、测试、回滚等流程。适用于团队协同工作、持续集成、持续交付等场景。 项…...
Shell脚本报错No such file or directory?这9个排查技巧帮你快速定位问题
Shell脚本报错"No such file or directory"的深度排查指南 当你在终端运行Shell脚本时,突然跳出的"No such file or directory"错误提示往往让人措手不及。这个看似简单的错误信息背后,可能隐藏着从路径拼写到系统配置的多种问题。…...
Ext2Read:在Windows上轻松读取Linux分区的3个关键步骤
Ext2Read:在Windows上轻松读取Linux分区的3个关键步骤 【免费下载链接】ext2read A Windows Application to read and copy Ext2/Ext3/Ext4 (With LVM) Partitions from Windows. 项目地址: https://gitcode.com/gh_mirrors/ex/ext2read Ext2Read是一款专为W…...
51单片机学习记录
1.流水灯#include "reg51.h"// 定义LED灯的位选数组 unsigned char led0[] {0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};// 延时函数 void delay(unsigned int n){unsigned int i0,j0;for(i 0;i<n;i){for(j 0;j<120;j);} } // LED流水灯函数 void led(){int…...
