雪月花 发表于 2019-11-1 13:44:06

FileChoose.dll与Dock皮肤的关联方式设计

本帖最后由 雪月花 于 2021-1-31 17:37 编辑

该文为新插件发布,面向对象为皮肤制作者。
搞不懂插件与皮肤的区别、搞不懂如何使用皮肤的新人还请退散。

FileChoose.dll
版本:1.2.0.1
作者:雪月花(Setsukka)

Plugin=FileChoose
该插件允许用户打开文件/文件夹浏览框,以选定文件/文件夹/图片,然后获得该文件的相关信息以设置皮肤。
该插件也允许用户提供一串地址路径,通过解析该路径,获得对应文件的相关信息以关联

官方论坛发布地址:https://forum.rainmeter.net/viewtopic.php?f=128&t=33767
个人LOFTER发布地址:
https://setsukka.lofter.com/post/1de9f951_1c6f1153b
插件示例皮肤:

插件说明文档:


Dock皮肤的关联
目前DOCK皮肤的关联方式主要存在以下几种:
一、 直接改变量的
省事是省事,但是对新手其实非常不友好。更不用说那些直接要用户深入代码去改的了。
当然现在的新手们也普遍有一个误区,就是拿到皮肤以后二话不说上来就去翻代码,最后自己DOCK没改明白,还把整体功能给破坏了。(这时候才想起来去翻主控台,一关联,hey,不好使,这皮肤有毛病!不知道该怎么吐槽好)
二、利用InputText.dll手动输入
这种方式能稍微高级一些,它允许用户在控制面板上直接输入路径文字,点击回车生效。但这依旧免不了要用户自己去找程序地址的麻烦。

一般推荐的成熟的关联方式是两种:浏览关联和拖拽关联。如,下图为我正在写的一款皮肤的中控台的Dock皮肤关联部分。其中浏览关联采用的是FileChoose.dll来实现的,拖拽关联采用了Drag&Drop.dll配合FileChoose.dll一起实现的。


三、浏览关联
常用的浏览关联是用RainFile.exe来实现的。这个Addon的功能是,打开一个浏览框,然后选择程序,即可获得路径,并物理改写对应变量,最后强制刷新全部皮肤。十分好用,而且会自动获取快捷方式的指向地址。一般比如Neon Space,Avenger等套装皮肤普遍采用RainFile。他的缺点有:有些快捷方式不能解析就不能选,只获取路径不管显示名称和图标,分类只有文件与文件夹,强制刷新皮肤。当然最后一点基本不成问题。
国内见到的方法有一些是在用LauncherL.exe来实现。典型的比如无界的智能线条快捷等。这个Addon的功能是,打开一个浏览框,然后仅允许选择exe文件和lnk文件(如果我没记错的话)。选择后,直接把lnk文件以特定命名复制到特定文件夹下,并把对应的文件名写入到特定文件内。它的缺点最主要是,由于对皮肤结构有要求,不适合做一些大型皮肤。而且不能自动刷新皮肤强制更改生效。最后,依然不管图标。
其实图标这个事,可以通过FileView.dll这个自带插件来解决,但是,首先这个插件由于刷新机制的问题,非常难用。其次,要想获得图标,需要首先将路径分解为所在目录和文件名称两部分,这些额外工作几乎只能在lua脚本里完成,就很不爽。最后,他在获取256x256大小的图标的时候,若图片不存在256大小的图标,他会获取到48x48的图标并置于256x256大小的图片的左上角(这就非常不爽了)。总之用起来就是很不爽。
相比于前面的方式,FileChoose.dll插件的好处主要体现在:
1. 不需要强制刷新皮肤,这意味着允许皮肤作者通过!SetVariable来修改,仅在点击皮肤上设的确定按钮后才物理性生效变更,点取消按钮可以不变更。
2. 可以完美获取到显示名称、路径、图标三者,也不存在同步问题。
3. 对皮肤结构没什么要求。是一种万能的选择。
四、拖拽关联
拖拽关联最初的典型代表是Quicklink.dll,由IZZZZI编写发布。后来随着Rainmeter升级,该插件无法正常工作,被废弃。
现在能够实现拖拽关联的插件仅有theAzack9做的Drag&Drop.dll。
发布地址:https://forum.rainmeter.net/viewtopic.php?f=128&t=23107&sid=27b6b6d39f771b4f7ea233399cb47544
这个插件的做法是:通过拖拽来获取文件路径,如果是lnk可以设定将其复制到缓存文件夹里去(就跟LauncherL.exe的思想很像)。然后自身附带一定的解析功能,能够获得显示名称、所属文件夹、完整路径等。可以通过将显示名称和所属文件夹两项丢到FileView.dll中来获得图标了,所以图标也不用愁。这已经是一套比较完整成熟的方案。
但我前面也说了,FileView对图标的获取还是有一定问题的,我更愿意选择通过Drag&Drop仅输出文件路径,然后用FileChoose.dll来进行解析,我认为这个方案更有实践价值。
Drag&Drop.dll自身有个最大的BUG,就是只能开一个拖拽口。假设我想拽到Meter1上,让程序关联到Dock1,拽到Meter2上,程序关联到Dock2。对不起,结果是无论你拽到Meter1还是Meter2,都会把程序关联到Dock1上去。
这个问题可以通过一个小技巧来解决,就在上面插件发布地址的第9页附近的一个人的回复。
他插件的OnDropAction是不识别拖拽的窗口的,但是OnOverAction和OnLeaveAction识别。而且在我们拖拽程序进来的时候,必然会首先触发OnOverAction。因此可以通过OnOverAction和OnLeaveAction来首先给OnDropAction赋值,这样的方法来解决。下面是提出此技巧的人所给出的示例代码。

Update=-1
AccurateText=1
DynamicWindowSize=1


Measure=Plugin
Plugin=Drag&Drop


Measure=Plugin
Plugin=Drag&Drop
Parent=DragNDropParent
Bounds=DropMeter1
Action=Path
OnOverAction=[!SetOption DragNDropChild1 OnDropAction """[!Log "You dropped a file in the first child!"][!SetOption DragNDropChild1 OnDropAction ""][!Update]"""][!Update]
OnLeaveAction=[!SetOption DragNDropChild1 OnDropAction ""][!Update]
OnDropAction=


Measure=Plugin
Plugin=Drag&Drop
Parent=DragNDropParent
Bounds=DropMeter2
Action=Path
OnOverAction=[!SetOption DragNDropChild2 OnDropAction """[!Log "You dropped a file in the second child!"][!SetOption DragNDropChild2 OnDropAction ""][!Update]"""][!Update]
OnLeaveAction=[!SetOption DragNDropChild2 OnDropAction ""][!Update]
OnDropAction=


Meter=Image
W=100
H=200
SolidColor=255,255,255


Meter=Image
X=200
W=100
H=200
SolidColor=255,255,255
经尝试,此法的确有效。这样,跟拖拽关联相关的问题就全部解决了。
我将FileChoose的示例皮肤按照上述技巧进行了修改,加入了拖拽关联后的示例皮肤如下,可供大家参考。


地址路径与lua脚本
说一下用地址路径与lua脚本时候经常会遇到的问题。
最主要就是,无论是InputText还是什么其他方法,只要你需要调用lua脚本,需要把路径作为函数的输入变量,用!CommandMeasure来调用函数,就会有一个最致命的问题:
由于在lua中,"\"作为转义字符来看待,所以轻则输出的路径中"\"全无,重则直接各种乱七八糟报错,函数无法正常执行。
据说这个问题可以用inline lua来解决,不过我没用过。根据我的经验,这种时候最好的办法是,直接在lua脚本中取用measure的返回值。
下面是调用InputText.dll的示例

; Rainmeter代码

Measure=Plugin
Plugin=InputText
xxxxxxxx
Comand1=[!Log "$UserInput[      DISCUZ_CODE_1      ]quot;][!CommandMeasure MeasureScript "InputOver()"]
; 由于InputText要求CommandN中必须由$UserInput$,否则不会单独执行,所以我前面加了个无用的!Log命令

-- lua脚本代码
function InputOver()
    local Measure=SKIN:GetMeasure('MeasureInput')
    local Value=Measure:GetStringValue()
    -- Value就是从MeasureInput的返回值处得到的完整的输入信息
    -- 接下来是其他赋值等操作
end
其他插件也可效仿。
而在FileChoose中,由于可能在同一时刻需要获取的信息有图标、名字、路径等很多,难以用单一的返回值来获取,因此仅针对此插件,可以通过更新Measure的方式来处理 (因为该插件,在选择完一个文件后,直到下次选择文件之前,存储的信息不会改变,而我所设定的插件的返回值只是一个指向不同字符串的指针而已):

; Rainmeter代码

Measure=Plugin
Plugin=FileChoose
xxxxxxxx
Command1=[!CommandMeasure MeasureScript "ChooseOver()"]
-- lua脚本代码
function ChooseOver()
    local Measure=SKIN:GetMeasure('MeasureChoose')
    -- 获取该Measure
    SKIN:Bang('!SetOption','MeasureChoose','ReturnValue','WholePath')
    SKIN:Bang('!UpdateMeasure','MeasureChoose')
    local Path=Measure:GetStringValue()
    -- 从返回值获取文件地址Path
    SKIN:Bang('!SetOption','MeasureChoose','ReturnValue','Icon')
    SKIN:Bang('!UpdateMeasure','MeasureChoose')
    local Icon=Measure:GetStringValue()
    -- 从返回值获取文件图标Icon
    SKIN:Bang('!SetOption','MeasureChoose','ReturnValue','Name')
    SKIN:Bang('!UpdateMeasure','MeasureChoose')
    local Name=Measure:GetStringValue()
    -- 从返回值获取文件显示名称Name
    -- 其他处理操作
end
更新日志

版本1.2.0.1 —— 2021年01月31日
       修复了GetIcon=0时,选择文件夹和图片不生效的问题
       增加了选项FileInitialDirectory和ImageDirectory用以设定对话框打开时的初始路径


版本1.1.0.4 —— 2021年01月23日
       修复了当浏览窗口尚在时,关闭皮肤会导致Rainmeter崩溃的问题

版本1.1.0.2 —— 2019年12月08日
       重新修订了保存图标部分的代码,以解决部分图标获取到空白图片的问题

版本1.1.0.1 —— 2019年10月31日
       增加了新的动作变量$Icon$用以获取图标
       增加了新的bang指令"Resolve N Path"用以解析现有路径


dujianaliuli 发表于 2019-11-15 22:37:13

小伙子有前途,我看好你{:10_407:}
页: [1]
查看完整版本: FileChoose.dll与Dock皮肤的关联方式设计