-
vfp教程之为Visual FoxPro应用程序增加文件压缩功能
压缩文件可以认为是一个包装文件的容器。通过文件压缩,大量文件可以被打包起来并当作一个文件来看待。此外,压缩文件在尺寸上普遍比原文件小,如文本文件在压缩以后的平均大小是原来的40%。因此,文件压缩能够大幅度的节省存储空间和网络传输时间,从而使得文件的携带和传输更加方便快捷。
在DOS环境下,经常使用到的压缩程序是ARJ、RAR和PKZIP/PKUNZIP。在Windows环境下,经常使用到的压缩软件是WinZip和CleverZip。这些软件基本上都是共享软件,都可以从网络上免费获取。
在数据库应用程序中,经常需要对数据文件进行压缩备份或者从压缩文件中恢复。以Visual FoxPro为例,通常的做法是通过FoxPro语句调用压缩软件,然后在该压缩软件的操作界面上进行文件压缩或者文件恢复。这种做法不仅在操作界面上非常不友好,而且大大地削弱了应用程序的整体性。以下介绍的FoxPro程序利用了两个共享的动态链接库AZIP.DLL和AUNZIP.DLL在Visual FoxPro内部实现了文件压缩与解压缩功能,从而较好地解决了这个问题。
文件压缩程序
* 程序名称:AZIP.PRG
* 程序说明:在Visual FoxPro中实现文件压缩
* 程序要求:AZIP32.DLL放置在Windows的System目录或当前目录下
* 使用方法:USAGE: AZIP(lInitialize, sArchive, sInclFiles[, ZipParams])
* 参数说明:
--lInitialize:.T. – 第一次使用本程序,.F. – 非第一次使用本程序
--sArchive: 带有扩展名的压缩文件名,如"C:\THISFILE.ZIP"
--sInclFiles:需要压缩的文件名称,不同文件名之间有一个空格
例1: "D:\CUSTDATA.DBF"
例2: "C:\CUSTOMER.DBF D:\*.TXT D:\DATABASES\*.*"
--ZIPparams:文件压缩参数[可选]
e(x) x = 'X' 最大程度压缩
x = '0' 无压缩
x = 'S' 最小程度压缩
x = 'N' 普通压缩(缺省)
P 包括目录信息
S 使用密码(必须是最后一部分)
* 示范语句:AZIP(.T., "ZIPFILE", "*.DBF *.TXT Customer.doc")
* 返回参数:被压缩的文件数目,如果没有指定文件名则返回-1
* 接受参数
PARAMETERS lInitialize, sArchive, sInclFiles, ZIPparams
PRIVATE Params, sTemp
Params = PARAMETERS()
* 声明需要调用的DLL函数并使当前窗口获得焦点
IF Params = 0 OR lInitialize
PRIVATE HWND
DECLARE INTEGER GetActiveWindow IN win32api
HWND = GetActiveWindow()
DECLARE addZIP_Initialise IN AZIP32
DECLARE SHORT addZIP_SetParentWindowHandle IN AZIP32 SHORT @ HWindow
DECLARE SHORT addZIP_ArchiveName IN AZIP32 STRING @ sArchName
DECLARE SHORT addZIP_Include IN AZIP32 STRING @ sFileName
DECLARE SHORT addZIP_Recurse IN AZIP32 SHORT @ nRecurse
DECLARE SHORT addZIP_SetCompressionLevel IN AZIP32 SHORT @ nComprLvl
DECLARE SHORT addZIP_IncludeDirectoryEntries IN AZIP32 SHORT @ nInclDir
DECLARE SHORT addZIP_IncludeEmptyDirectoryEntries IN AZIP32 SHORT @ nInclEDir
DECLARE SHORT addZIP_Update IN AZIP32 SHORT @ nUpdate
DECLARE SHORT addZIP_Update IN AZIP32 SHORT @ nUpdate
DECLARE SHORT addZIP IN AZIP32
DECLARE SHORT addZIP_Register IN AZIP32 String @ RegName, Integer @ RegNum
DECLARE SHORT addZIP_Encrypt IN AZIP32 STRING @ sPassw
addZIP_Initialise()
addZIP_SetParentWindowHandle(HWND)
* 如果使用的是本动态链接库的注册版本,则可以添加下面一行
addZIP_Register("RegistrationName", RegistrationNumber)
* 其作用是在压缩文件中使用密码保护
* 如果没有指定压缩文件名,则返回0(没有文件被压缩)
IF Params < 2
RETURN 0
ENDIF
ENDIF
* 如果没有指定被压缩文件名,则响铃并返回0(没有文件被压缩)
IF Params < 3
?? CHR(7)
MESSAGEBOX('缺少操作参数!',0, 'AZip 警告!')
RETURN 0
ENDIF
* 如果指定了文件压缩参数,按照参数进行压缩选择
IF Params > 3
ZIPparams = ALLT(ZIPparams)
PRIVATE LastPos, PASSWORD, nCurPos
LastPos = LEN(ZIPparams) + 1
* 检查是否存在压缩密码
nCurPos = ATC('S', ZIPparams)
IF nCurPos > 0
cPassWord = SUBSTR(ZIPparams, nCurPos+1)
addZIP_Encrypt(cPassWord)
ZIPparams = LEFT(ZIPparams, nCurPos -1)
ENDIF
* 检查是否保存目录信息
nCurPos = ATC('P', ZIPparams)
IF nCurPos > 0
addZIP_Recurse(1)
addZIP_IncludeDirectoryEntries(1)
ENDIF
* 检查文件压缩的程度
nCurPos = ATC('E', ZIPparams)
IF nCurPos > 0
PRIVATE cCompLevel, nCompLevel
cCompLevel = SUBSTR(ZIPparams, nCurPos + 1, 1)
DO CASE
* 最大程度压缩
CASE cCompLevel = 'X'
nCompLevel = 3
* 最小程度压缩
CASE cCompLevel = 'S' && min compression
nCompLevel = 1
* 没有压缩
CASE cCompLevel = '0' && no compression
nCompLevel = 0
* 正常压缩
OTHERWISE && normal/default compression
nCompLevel = 2
ENDCASE
addZIP_SetCompressionLevel(nCompLevel)
ENDIF
ELSE
addZIP_SetCompressionLevel(2)
ENDIF
* 指定压缩文件的路径
addZIP_ArchiveName(sArchive)
* 检查需要进行压缩的文件
sInclFiles = ALLT(STRTRAN(sInclFiles, ' ', '|'))
* 建立压缩文件信息
addZIP_Include(sInclFiles) && (sInclFiles)
* 压缩文件并返回被压缩的文件数目
Return addZIP()
文件解压缩程序
* 程序名称:AUNZIP.PRG
* 程序说明:在Visual FoxPro中实现文件解压缩
* 程序要求:AUNZIP32.DLL放置在Windows的System目录或当前目录下
* 使用方法:AUNZIP(lInitialize, sArchive sDir[, sExtractFiles[, UnZIPparams]])
* 参数说明:
* lInitialize:.T. – 第一次使用本程序,.F. – 非第一次使用本程序
* sArchive: 带有扩展名的压缩文件名,如"C:\THISFILE.ZIP"
* sDir: 目标目录,如"D:\TEMP"
* sExtractFiles:需要进行解压缩的文件名称[可选],不同文件名之间有一个空格
* 缺省:"*.*"
* 例1:"C:\CUSTOMER.DBF"
* 例2:"C:\CUSTOMER.DBF D:\*.TXT D:\DATABASES\*.*"
* UnZIPparams:压缩参数[可选]
* F 文件更新
* D 包括目录信息
* OA 全部覆盖(缺省)
* O0 不覆盖
* OU 提问是否覆盖
* S 使用密码 (必须是最后一部分)
* 示范语句:AUNZIP(.T., "ZIPFILE", "*.DBF *.TXT Customer.doc")
* 返回参数:被解压缩的文件数目,如果没有指定压缩文件名则返回-1
* 接受参数
PARAMETERS Initialize, sArchive, sDir, sExtractFiles, UnZIPparams
PRIVATE Params, sTemp
Params = PARAMETERS()
* 声明需要的动态链接库并使当前窗口获得焦点
IF Params = 0 OR Initialize
PRIVATE HWND
DECLARE INTEGER GetActiveWindow IN win32api
HWND = GetActiveWindow()
DECLARE addUNZIP_Initialise IN AUNZIP32
DECLARE SHORT addUNZIP_SetParentWindowHandle IN AUNZIP32 SHORT @ HWindow
DECLARE SHORT addUNZIP_ArchiveName IN AUNZIP32 STRING @ sArchName
DECLARE SHORT addUNZIP_RestoreStructure IN AUNZIP32 SHORT @ nResStr
DECLARE SHORT addUNZIP_Freshen IN AUNZIP32 SHORT @ nFreshn
DECLARE SHORT addUNZIP_Include IN AUNZIP32 STRING @ sFileName
DECLARE SHORT addUNZIP_ExtractTo IN AUNZIP32 STRING @ sExtrTo
DECLARE SHORT addUNZIP_Register IN AUNZIP32 STRING @ RegName, INTEGER @ RegNum
DECLARE SHORT addUNZIP_Decrypt IN AUNZIP32 STRING @ sPassw
DECLARE SHORT addUNZIP_Overwrite IN AUNZIP32 SHORT @ nOvLevel
DECLARE SHORT addUNZIP IN AUNZIP32
addUNZIP_Initialise()
addUNZIP_SetParentWindowHandle(HWND)
* addUNZIP_Register("RegistrationName", RegistrationNumber)
* 如果使用的是本动态链接库的注册版本,则可以添加上面一行
* 其作用是在压缩文件中使用密码保护
* 如果没有指定压缩文件名,则返回0(没有文件被解压缩)
IF Params < 2
RETURN 0
ENDIF
ENDIF
* 如果没有指定解压缩目标目录,则响铃并返回0(没有文件被解压缩)
IF Params < 3
?? CHR(7)
MESSAGEBOX('缺少解压缩参数!',0, 'AUNZip 警告!')
RETURN 0
ENDIF
* 如果存在解压缩参数,则获取解压缩参数
IF Params > 3
UnZIPparams = ALLT(UnZIPparams)
PRIVATE LastPos, PASSWORD, nCurPos
LastPos = LEN(UnZIPparams) + 1
* 检查是否使用密码
nCurPos = ATC('S', UnZIPparams)
IF nCurPos > 0
cPassWord = SUBSTR(UnZIPparams, nCurPos+1)
addUNZIP_Decrypt(cPassWord)
UnZIPparams = LEFT(UnZIPparams, nCurPos -1)
ENDIF
* 检查是否恢复目录信息
nCurPos = ATC('D', UnZIPparams)
IF nCurPos > 0
addUNZIP_RestoreStructure(1)
ENDIF
* 检查是否进行文件更新
nCurPos = ATC('F', UnZIPparams)
IF nCurPos > 0
addUNZIP_RestoreStructure(1)
ENDIF
* 检查是否覆盖文件
DO CASE
* 全部覆盖
CASE 'OA' $ UnZIPparams
addUNZIP_Overwrite(0x0b)
* 不覆盖
CASE 'O0' $ UnZIPparams
addUNZIP_Overwrite(0x0c)
* 提问是否覆盖
CASE 'OU' $ UnZIPparams
addUNZIP_Overwrite(0x0a)
ENDCASE
IF nCurPos > 0
addUNZIP_RestoreStructure(1)
ENDIF
ELSE
addUNZIP_Overwrite(0x000a)
ENDIF
* 确认需要解压缩的压缩文件名
addUNZIP_ArchiveName(sArchive)
* 确认解压缩目标路径
addUNZIP_ExtractTo(ALLT(sDir))
* 确认需要进行解压缩的文件
sExtractFiles = IIF(Params<4, "*.*", ALLT(STRTRAN(sExtractFiles, ' ', '|')))
* 构造解压缩信息
addUNZIP_Include(sExtractFiles)
* 解压缩文件并返回被解压缩的文件数目
RETURN addUNZIP()
[补充说明]
动态链接库AZIP.DLL和AUNZIP.DLL是NetCom公司英国分部的工程师Stephen Darlington编写的共享软件AddZip中的一部分。
作者:蒋清野
通讯地址:清华大学23#421 (100084)
电子邮件:qyjohn@letterbox.com
在DOS环境下,经常使用到的压缩程序是ARJ、RAR和PKZIP/PKUNZIP。在Windows环境下,经常使用到的压缩软件是WinZip和CleverZip。这些软件基本上都是共享软件,都可以从网络上免费获取。
在数据库应用程序中,经常需要对数据文件进行压缩备份或者从压缩文件中恢复。以Visual FoxPro为例,通常的做法是通过FoxPro语句调用压缩软件,然后在该压缩软件的操作界面上进行文件压缩或者文件恢复。这种做法不仅在操作界面上非常不友好,而且大大地削弱了应用程序的整体性。以下介绍的FoxPro程序利用了两个共享的动态链接库AZIP.DLL和AUNZIP.DLL在Visual FoxPro内部实现了文件压缩与解压缩功能,从而较好地解决了这个问题。
文件压缩程序
* 程序名称:AZIP.PRG
* 程序说明:在Visual FoxPro中实现文件压缩
* 程序要求:AZIP32.DLL放置在Windows的System目录或当前目录下
* 使用方法:USAGE: AZIP(lInitialize, sArchive, sInclFiles[, ZipParams])
* 参数说明:
--lInitialize:.T. – 第一次使用本程序,.F. – 非第一次使用本程序
--sArchive: 带有扩展名的压缩文件名,如"C:\THISFILE.ZIP"
--sInclFiles:需要压缩的文件名称,不同文件名之间有一个空格
例1: "D:\CUSTDATA.DBF"
例2: "C:\CUSTOMER.DBF D:\*.TXT D:\DATABASES\*.*"
--ZIPparams:文件压缩参数[可选]
e(x) x = 'X' 最大程度压缩
x = '0' 无压缩
x = 'S' 最小程度压缩
x = 'N' 普通压缩(缺省)
P 包括目录信息
S 使用密码(必须是最后一部分)
* 示范语句:AZIP(.T., "ZIPFILE", "*.DBF *.TXT Customer.doc")
* 返回参数:被压缩的文件数目,如果没有指定文件名则返回-1
* 接受参数
PARAMETERS lInitialize, sArchive, sInclFiles, ZIPparams
PRIVATE Params, sTemp
Params = PARAMETERS()
* 声明需要调用的DLL函数并使当前窗口获得焦点
IF Params = 0 OR lInitialize
PRIVATE HWND
DECLARE INTEGER GetActiveWindow IN win32api
HWND = GetActiveWindow()
DECLARE addZIP_Initialise IN AZIP32
DECLARE SHORT addZIP_SetParentWindowHandle IN AZIP32 SHORT @ HWindow
DECLARE SHORT addZIP_ArchiveName IN AZIP32 STRING @ sArchName
DECLARE SHORT addZIP_Include IN AZIP32 STRING @ sFileName
DECLARE SHORT addZIP_Recurse IN AZIP32 SHORT @ nRecurse
DECLARE SHORT addZIP_SetCompressionLevel IN AZIP32 SHORT @ nComprLvl
DECLARE SHORT addZIP_IncludeDirectoryEntries IN AZIP32 SHORT @ nInclDir
DECLARE SHORT addZIP_IncludeEmptyDirectoryEntries IN AZIP32 SHORT @ nInclEDir
DECLARE SHORT addZIP_Update IN AZIP32 SHORT @ nUpdate
DECLARE SHORT addZIP_Update IN AZIP32 SHORT @ nUpdate
DECLARE SHORT addZIP IN AZIP32
DECLARE SHORT addZIP_Register IN AZIP32 String @ RegName, Integer @ RegNum
DECLARE SHORT addZIP_Encrypt IN AZIP32 STRING @ sPassw
addZIP_Initialise()
addZIP_SetParentWindowHandle(HWND)
* 如果使用的是本动态链接库的注册版本,则可以添加下面一行
addZIP_Register("RegistrationName", RegistrationNumber)
* 其作用是在压缩文件中使用密码保护
* 如果没有指定压缩文件名,则返回0(没有文件被压缩)
IF Params < 2
RETURN 0
ENDIF
ENDIF
* 如果没有指定被压缩文件名,则响铃并返回0(没有文件被压缩)
IF Params < 3
?? CHR(7)
MESSAGEBOX('缺少操作参数!',0, 'AZip 警告!')
RETURN 0
ENDIF
* 如果指定了文件压缩参数,按照参数进行压缩选择
IF Params > 3
ZIPparams = ALLT(ZIPparams)
PRIVATE LastPos, PASSWORD, nCurPos
LastPos = LEN(ZIPparams) + 1
* 检查是否存在压缩密码
nCurPos = ATC('S', ZIPparams)
IF nCurPos > 0
cPassWord = SUBSTR(ZIPparams, nCurPos+1)
addZIP_Encrypt(cPassWord)
ZIPparams = LEFT(ZIPparams, nCurPos -1)
ENDIF
* 检查是否保存目录信息
nCurPos = ATC('P', ZIPparams)
IF nCurPos > 0
addZIP_Recurse(1)
addZIP_IncludeDirectoryEntries(1)
ENDIF
* 检查文件压缩的程度
nCurPos = ATC('E', ZIPparams)
IF nCurPos > 0
PRIVATE cCompLevel, nCompLevel
cCompLevel = SUBSTR(ZIPparams, nCurPos + 1, 1)
DO CASE
* 最大程度压缩
CASE cCompLevel = 'X'
nCompLevel = 3
* 最小程度压缩
CASE cCompLevel = 'S' && min compression
nCompLevel = 1
* 没有压缩
CASE cCompLevel = '0' && no compression
nCompLevel = 0
* 正常压缩
OTHERWISE && normal/default compression
nCompLevel = 2
ENDCASE
addZIP_SetCompressionLevel(nCompLevel)
ENDIF
ELSE
addZIP_SetCompressionLevel(2)
ENDIF
* 指定压缩文件的路径
addZIP_ArchiveName(sArchive)
* 检查需要进行压缩的文件
sInclFiles = ALLT(STRTRAN(sInclFiles, ' ', '|'))
* 建立压缩文件信息
addZIP_Include(sInclFiles) && (sInclFiles)
* 压缩文件并返回被压缩的文件数目
Return addZIP()
文件解压缩程序
* 程序名称:AUNZIP.PRG
* 程序说明:在Visual FoxPro中实现文件解压缩
* 程序要求:AUNZIP32.DLL放置在Windows的System目录或当前目录下
* 使用方法:AUNZIP(lInitialize, sArchive sDir[, sExtractFiles[, UnZIPparams]])
* 参数说明:
* lInitialize:.T. – 第一次使用本程序,.F. – 非第一次使用本程序
* sArchive: 带有扩展名的压缩文件名,如"C:\THISFILE.ZIP"
* sDir: 目标目录,如"D:\TEMP"
* sExtractFiles:需要进行解压缩的文件名称[可选],不同文件名之间有一个空格
* 缺省:"*.*"
* 例1:"C:\CUSTOMER.DBF"
* 例2:"C:\CUSTOMER.DBF D:\*.TXT D:\DATABASES\*.*"
* UnZIPparams:压缩参数[可选]
* F 文件更新
* D 包括目录信息
* OA 全部覆盖(缺省)
* O0 不覆盖
* OU 提问是否覆盖
* S 使用密码 (必须是最后一部分)
* 示范语句:AUNZIP(.T., "ZIPFILE", "*.DBF *.TXT Customer.doc")
* 返回参数:被解压缩的文件数目,如果没有指定压缩文件名则返回-1
* 接受参数
PARAMETERS Initialize, sArchive, sDir, sExtractFiles, UnZIPparams
PRIVATE Params, sTemp
Params = PARAMETERS()
* 声明需要的动态链接库并使当前窗口获得焦点
IF Params = 0 OR Initialize
PRIVATE HWND
DECLARE INTEGER GetActiveWindow IN win32api
HWND = GetActiveWindow()
DECLARE addUNZIP_Initialise IN AUNZIP32
DECLARE SHORT addUNZIP_SetParentWindowHandle IN AUNZIP32 SHORT @ HWindow
DECLARE SHORT addUNZIP_ArchiveName IN AUNZIP32 STRING @ sArchName
DECLARE SHORT addUNZIP_RestoreStructure IN AUNZIP32 SHORT @ nResStr
DECLARE SHORT addUNZIP_Freshen IN AUNZIP32 SHORT @ nFreshn
DECLARE SHORT addUNZIP_Include IN AUNZIP32 STRING @ sFileName
DECLARE SHORT addUNZIP_ExtractTo IN AUNZIP32 STRING @ sExtrTo
DECLARE SHORT addUNZIP_Register IN AUNZIP32 STRING @ RegName, INTEGER @ RegNum
DECLARE SHORT addUNZIP_Decrypt IN AUNZIP32 STRING @ sPassw
DECLARE SHORT addUNZIP_Overwrite IN AUNZIP32 SHORT @ nOvLevel
DECLARE SHORT addUNZIP IN AUNZIP32
addUNZIP_Initialise()
addUNZIP_SetParentWindowHandle(HWND)
* addUNZIP_Register("RegistrationName", RegistrationNumber)
* 如果使用的是本动态链接库的注册版本,则可以添加上面一行
* 其作用是在压缩文件中使用密码保护
* 如果没有指定压缩文件名,则返回0(没有文件被解压缩)
IF Params < 2
RETURN 0
ENDIF
ENDIF
* 如果没有指定解压缩目标目录,则响铃并返回0(没有文件被解压缩)
IF Params < 3
?? CHR(7)
MESSAGEBOX('缺少解压缩参数!',0, 'AUNZip 警告!')
RETURN 0
ENDIF
* 如果存在解压缩参数,则获取解压缩参数
IF Params > 3
UnZIPparams = ALLT(UnZIPparams)
PRIVATE LastPos, PASSWORD, nCurPos
LastPos = LEN(UnZIPparams) + 1
* 检查是否使用密码
nCurPos = ATC('S', UnZIPparams)
IF nCurPos > 0
cPassWord = SUBSTR(UnZIPparams, nCurPos+1)
addUNZIP_Decrypt(cPassWord)
UnZIPparams = LEFT(UnZIPparams, nCurPos -1)
ENDIF
* 检查是否恢复目录信息
nCurPos = ATC('D', UnZIPparams)
IF nCurPos > 0
addUNZIP_RestoreStructure(1)
ENDIF
* 检查是否进行文件更新
nCurPos = ATC('F', UnZIPparams)
IF nCurPos > 0
addUNZIP_RestoreStructure(1)
ENDIF
* 检查是否覆盖文件
DO CASE
* 全部覆盖
CASE 'OA' $ UnZIPparams
addUNZIP_Overwrite(0x0b)
* 不覆盖
CASE 'O0' $ UnZIPparams
addUNZIP_Overwrite(0x0c)
* 提问是否覆盖
CASE 'OU' $ UnZIPparams
addUNZIP_Overwrite(0x0a)
ENDCASE
IF nCurPos > 0
addUNZIP_RestoreStructure(1)
ENDIF
ELSE
addUNZIP_Overwrite(0x000a)
ENDIF
* 确认需要解压缩的压缩文件名
addUNZIP_ArchiveName(sArchive)
* 确认解压缩目标路径
addUNZIP_ExtractTo(ALLT(sDir))
* 确认需要进行解压缩的文件
sExtractFiles = IIF(Params<4, "*.*", ALLT(STRTRAN(sExtractFiles, ' ', '|')))
* 构造解压缩信息
addUNZIP_Include(sExtractFiles)
* 解压缩文件并返回被解压缩的文件数目
RETURN addUNZIP()
[补充说明]
动态链接库AZIP.DLL和AUNZIP.DLL是NetCom公司英国分部的工程师Stephen Darlington编写的共享软件AddZip中的一部分。
作者:蒋清野
通讯地址:清华大学23#421 (100084)
电子邮件:qyjohn@letterbox.com
最新更新
nodejs爬虫
Python正则表达式完全指南
爬取豆瓣Top250图书数据
shp 地图文件批量添加字段
爬虫小试牛刀(爬取学校通知公告)
【python基础】函数-初识函数
【python基础】函数-返回值
HTTP请求:requests模块基础使用必知必会
Python初学者友好丨详解参数传递类型
如何有效管理爬虫流量?
SQL SERVER中递归
2个场景实例讲解GaussDB(DWS)基表统计信息估
常用的 SQL Server 关键字及其含义
动手分析SQL Server中的事务中使用的锁
openGauss内核分析:SQL by pass & 经典执行
一招教你如何高效批量导入与更新数据
天天写SQL,这些神奇的特性你知道吗?
openGauss内核分析:执行计划生成
[IM002]Navicat ODBC驱动器管理器 未发现数据
初入Sql Server 之 存储过程的简单使用
这是目前我见过最好的跨域解决方案!
减少回流与重绘
减少回流与重绘
如何使用KrpanoToolJS在浏览器切图
performance.now() 与 Date.now() 对比
一款纯 JS 实现的轻量化图片编辑器
关于开发 VS Code 插件遇到的 workbench.scm.
前端设计模式——观察者模式
前端设计模式——中介者模式
创建型-原型模式