2021.10.03 BeautifulToolTip 高兼容 高性能 简单易用 自定义效果丰富的 ToolTip

这是用 GDI+ 完全重写的 ToolTip 。

BeautifulToolTip ,以下简称 BTT  。


为什么要重写一个 ToolTip 呢,因为下面4个问题真的很烦人。

  • 闪烁

  • 坐标乱飘

  • 文本难以对齐

  • 难以在显示前预知大小

BTT 被设计为可以完全取代 ToolTip ,所以它完全兼容 ToolTip 的语法及设置。

  • 显示一个内容
    btt("This is BeautifulToolTip")​
  • 清空一个内容
    btt()​
  • 指定 x,y 及 WhichToolTip
    btt("This is BeautifulToolTip`n`nWhichToolTip = 2",500,500,2)
    Sleep, 5000
    btt(,,,2)
  • CoordMode 命令也对 BTT 生效
    CoordMode, ToolTip, Screen
    btt("This is BeautifulToolTip")
    Sleep, 5000
    btt()

除了上面基本用法, BTT 还拥有多个内置样式,使用依然简单。

  • 使用内置样式“Style1”
    btt("This is BeautifulToolTip",,,, "Style1")
  • 更多内置样式的效果
  • 自定义样式也非常简单,只需更改模板参数!
    #SingleInstance Force
    SetBatchLines, -1
    
    Text=
    (
    使用模板可以轻松创建自己的风格。
    欢迎分享,带张截图!!!
    
    Use template to easily create your own style.
    Please share your custom style and include a screenshot.
    It will help a lot of people.
    )
    
    ; 照着模板改参数就可以创建自己的风格了。建好后可以添加到 btt() 函数里,就可以变内置风格了。
    Template :=  {Border:20                                      ; If omitted, 1 will be used. Range 0-20.
                , Rounded:30                                     ; If omitted, 3 will be used. Range 0-30.
                , Margin:30                                      ; If omitted, 5 will be used. Range 0-30.
                , TabStops:[50, 80, 100]                         ; If omitted, [50] will be used. This value must be an array.
                , BorderColor:0xffaabbcc                         ; ARGB
                , BorderColorLinearGradientStart:0xff16a085      ; ARGB
                , BorderColorLinearGradientEnd:0xfff4d03f        ; ARGB
                , BorderColorLinearGradientAngle:45              ; Mode=8 Angle 0(L to R) 90(U to D) 180(R to L) 270(D to U)
                , BorderColorLinearGradientMode:1                ; Mode=4 Angle 0(L to R) 90(D to U), Range 1-8.
                , TextColor:0xff112233                           ; ARGB
                , TextColorLinearGradientStart:0xff00416a        ; ARGB
                , TextColorLinearGradientEnd:0xffe4e5e6          ; ARGB
                , TextColorLinearGradientAngle:90                ; Mode=8 Angle 0(L to R) 90(U to D) 180(R to L) 270(D to U)
                , TextColorLinearGradientMode:1                  ; Mode=4 Angle 0(L to R) 90(D to U), Range 1-8.
                , BackgroundColor:0xff778899                     ; ARGB
                , BackgroundColorLinearGradientStart:0xff8DA5D3  ; ARGB
                , BackgroundColorLinearGradientEnd:0xffF4CFC9    ; ARGB
                , BackgroundColorLinearGradientAngle:135         ; Mode=8 Angle 0(L to R) 90(U to D) 180(R to L) 270(D to U)
                , BackgroundColorLinearGradientMode:1            ; Mode=4 Angle 0(L to R) 90(D to U), Range 1-8.
                , Font:"Font Name"                               ; If omitted, ToolTip's Font will be used. Can specify the font file.
                , FontSize:20                                    ; If omitted, 12 will be used.
                , FontRender:5                                   ; If omitted, 5 will be used. Range 0-5.
                , FontStyle:"Regular Bold Italic BoldItalic Underline Strikeout"}
    
    ; Same as Style7
    OwnStyle1 := {Border:20
                , Rounded:30
                , Margin:30
                , BorderColor:0xffaabbcc
                , TextColor:0xff112233
                , BackgroundColorLinearGradientStart:0xffF4CFC9
                , BackgroundColorLinearGradientEnd:0xff8DA5D3
                , BackgroundColorLinearGradientAngle:0
                , BackgroundColorLinearGradientMode:8
                , FontStyle:"BoldItalic Underline"}
    
    btt(Text,,,,OwnStyle1)
    Sleep, 10000
    ExitApp


通过更改 BTT 的 Options 参数,可以很容易的实现一些特效。

  • 淡入
for k, v in [15,35,55,75,95,115,135,155,175,195,215,235,255]
{
	btt(Text,,,,"Style7",{Transparent:v})
	Sleep, 30
}
  • 淡出
for k, v in [240,220,200,180,160,140,120,100,80,60,40,20,0]
{
	btt(Text,,,,"Style7",{Transparent:v})
	Sleep, 30
}

  • 改变“渐变角度”参数实现动画效果

  • 窗口跟随
btt(Text,800-1,600-1,,"Style1",{TargetHWND:target})

  • 计算最终显示大小
ret := btt("test",,,,,{JustCalculateSize:1})
MsgBox, % "宽:" ret.w " 高:" ret.h


除了以上这些 BTT 还实现了

  • 多显示器支持
  • 多DPI支持

但这里就不再演示了,自己看打包的示例或者源码中的说明。


最后,在即没有原版那些烦人问题,又拥有诸多新特性的同时。

BTT 的性能    ——     比原版快 2-1000 倍!!!!!!

  • 原版 CPU 占用率

  • BTT CPU 占用率

  • 耗时对比


强烈建议你把 BTT库 及 引用库 放 AHK 公用 Lib 目录里。

也就是说,把 BTT.ahk 、 Gdip_All.ahk 、 NonNull.ahk 放下面目录里(没有就手动新建)

C:\我的电脑\Documents\AutoHotkey\Lib

这样你在每次使用的时候,就不需要再 #Include BTT.ahk 了。


好了,快抛弃 ToolTip 拥抱 BTT 吧!!!秀出你自定义的style!!!

下载地址:

https://github.com/telppa/BeautifulToolTip/releases


更新日志:

  • 2021.10.03
    改变 Include 方式,降低库冲突的可能性。
  • 2021.09.29
    支持设置 TabStops 。
    除 GDIP 库外所有函数内置到 Class 中,降低库冲突的可能性。
  • 2021.04.30
    修复 Win7 下不能运行的 bug 。(2021.04.20 引起)
  • 2021.04.20
    支持根据显示器 DPI 缩放比例自动缩放,与 ToolTip 特性保持一致。
    支持直接使用未安装的本地字体。
    Options 增加 JustCalculateSize 参数,可在不绘制内容的前提下直接返回尺寸。
  • 2021.03.07
    增加 4 种渐变模式。
  • 2021.03.05
    删除渐变方向参数。
    增加渐变角度参数,支持 360° 渐变。
    增加渐变模式参数,支持 4 种模式。
  • 2021.03.03
    文本色支持渐变。
    增加 Style8 。
    增加3个渐变方向。
  • 2021.03.02
    细边框色支持渐变。
    增加 Style7 。
    增加2个渐变方向。
  • 2021.03.01
    BTT 的总在最上级别现在跟 ToolTip 一样高了。
    解决 BTT 被不明原因置底导致误以为没显示的问题。
    增加 Style6 。
    文字显示更加居中。
  • 2021.02.22
    增加返回值与 Transparent 参数。
 

给TA买糖
共{{data.count}}人
人已赞赏
AHKV1办公

Radial menu v4(Autohotkey轮盘)

2021-2-19 21:19:15

AHKV1游戏

HX云顶之弈自动选牌挂机脚本

2021-2-21 12:33:44

35 条回复 A文章作者 M管理员
  1. 1河许人

    下载链接呢,着急变成生产力

    • 空

      刚才搞排版呢,太难了。
      地址给出来了。

    • 1河许人

      哪里不舒服 跟我说 我反馈给模板作者

    • 空

      说实话,就没一样舒服的,简直就是折磨…… 比如,我添加了那个行最前面的小圆点,之后要加一个空白行出来,简直就太难,还不如直接编辑html简单。

    • 1河许人

      具体点,老哥,比如哪个地方 怎么不舒服,这个很需要

    • LionAHK1

      牛逼牛逼.

  2. sanmaodo

    这是我在本论坛看过最工整漂亮的一个帖子,感谢!!!💪😊👍

    • 空

      搞了1小时多呢,能不工整吗😭

  3. 星星雨

    感谢提供!

  4. LionAHK1

    不能加上一个鼠标拖放的功能 .这样用起来就更加爽了.

    • LionAHK1

      就是可以把显示的窗口随意拖放位置.

    • 空

      设计是替代 tooltip 的,所以这种功能我就不提供了,你可以自己包装一层实现一下,btt 提供了句柄返回值的。

  5. jly

    测试如下代码,按ESC退出脚本的时候经常出现AutoHotkey停止工作的情况。怀疑Show label中,如果里面的命令比较多的话,执行时间长,容易出问题。

    测试方法: 运行脚本1秒钟之后,按ESC退出脚本,反复测试几次,很容易出现AutoHotkey停止工作的错误.

    #SingleInstance Force
    SetBatchLines, -1
    CoordMode, ToolTip, Screen
    DetectHiddenWindows, Off

    SetTimer,Show, 10
    Show:
    f1()
    f1()
    f1()
    f1()
    Text := “hello world”
    btt(Text,,300,,”Style2″)
    return
    f1()
    {
    CoordMode, Mouse, Screen
    CoordMode, Pixel, Screen
    MouseGetPos, mX, mY, Win_Id,Ctrl_ClassNN
    CoordMode, Mouse, Window
    MouseGetPos, mX_w, mY_w
    PixelGetColor, colr1, %mX%, %mY%, RGB
    }
    esc::
    exitapp
    return

    • jly

      好像在 SetTimer,Show, 10 之后加一个 return 就可以了

  6. jly

    使用BeautifulToolTip 内存升高比较快,当BTT不显示的时候,能释放内存吗?

    • 空

      根据我的测试,每个不同的 WhichToolTip 大概增加8M内存。

      如果你一定要去释放这些内存的话,那么这样写。

      BTT := new BeautifulToolTip()
      BTT.ToolTip(11111111)
      BTT.ToolTip()
      BTT:=””
      #Include btt.ahk

      代价是速度会显著下降,并且写起来麻烦多了。

    • jly

      我测试发现 执行清理画布 Gdip_GraphicsClear(this[“G” WhichToolTip]) (大致在243行)这一行,内存一下子增加到30多M。 我把这个注释掉之后,可以正常显示,但内存维持在10M以内。 然后关闭显示btt(),内存也会一下子增加到30多M。 内存占用大 是不是画布的原因?

    • jly

      内存占用大 是不是 清理 画布的原因?

    • jly

      不清理画布,我打开15个tooltip 内存才18M

    • 空

      15个btt还是15个tooltip?

      另外你是同一个btt打开15次,还是whichtooltip参数分别设置为1-15的那样同时打开15个?

    • jly

      昨天测试的 是同一个btt whichtooltip参数分别设置为1-15的那样同时打开15个,当时我是把Gdip_GraphicsClear(this[“G” WhichToolTip])注释掉测试的。

      如果CreateDIBSection用的是整个虚拟屏幕的长和宽,则执行一次Gdip_GraphicsClear内存就立即升高到30M(我是双屏幕测试的)。 我在BeautifulToolTip Class中把CreateDIBSection的长和宽设置为1000和800 ,并把GraphicsClear的注释打开,测试内存只升高几M。 1000X800的尺寸对于一般的显示 完全够用。

      另外,我上面留言说 导致AutoHotkey 崩溃的问题,后来测试加上一个 return就没问题了,不知道什么原因。

      还有,当我BTT:=”” 这样释放内存后,按Win + L锁屏,再解锁,也出现了AutoHotkey崩溃 停止工作的问题, 不知道是什么原因?

    • jly

      1 关于锁屏崩溃的问题,因为我脚本中另外一个地方也用到了pToken,我把 BeautifulToolTip类中的
      pToken换成了全局统一用的pToken,而不是自己创建pToken,__Delete函数中注释掉 Gdip_Shutdown(this.pToken)。 然后锁屏就不再崩溃了。

      2 上面加return才不崩溃的问题,因为我另外一个脚本中有在用pToken,两个相互影响?? 我测试 把 Gdip_Shutdown(this.pToken)注释掉,就可以了。

      初步来看:
      1 好像同一个程序中,只能有一个pToken 。
      2 不同程序中,都打开了pToken,可能会相互影响。
      以上两点不知道,理解的对不对。

      另外,我在btt函数中添加了如下代码,每次Text为空时,检查所有whichtooltip的Text如果都为空,则释放内存,如果对内存要求高的,可以尝试。
      if(!Text and BTT and BTT.check_is_all_null()) ;如果每个tooltip都为空了,则清理内存。
      BTT:=””

      check_is_all_null() 是在BeautifulToolTip类中添加的函数 检测是否所有whichtooltip的Text如果都为空:
      check_is_all_null()
      {
      loop % this.NumToolTips
      if(this[“SavedText” A_Index])
      return 0
      return 1
      }

    • 空

      你这个问题吧,就是在于,不停的关闭gdip然后又初始化它,然后还多个地方初始化gdip,还没开多实例。

    • 空

      完全不建议其它人用同样的方式去做,你目前改代码属于拎着一半就跑的那种,意思就是很多地方的代码并没有完全弄明白就改掉了。这样就结果就是,虽然看起来好像运行了,但其实又给自己引入了很多bug(你后来的那些bug似乎都是这样引入的)。我建议如果你特别介意内存的问题,可以试试局部清空画布之类的方式去实现(这是基于你前面说,画布一清空,内存立马就飚高,所以我猜测,会不会是清空的时候,某种值填满了整个画布,所以建议你尝试局部清空。另外,你后面又说,改了画布初始大小,所以我现在也分不清,到底是大小问题影响的,还是清空问题影响的)。

    • 空

      CreateDIBSection 设很大,是因为你复制一篇很长的文章就明白了。

    • jly

      是的,画布设置小了,如果要显示的文字很多就会显示不全。
      所以我根据个人需要指定了一个适合自己的尺寸1000X800 。
      如果画布设置的大,执行Gdip_GraphicsClear,则内存升高的就多,如果设置的小,执行Gdip_GraphicsClear,则内存升高的小(这是我测试得到的结果)。
      我是双屏幕,画布由原来的尺寸(整个虚拟屏幕)改成1000X800,内存由原来的30多M变成了几M。

      如果不对BeautifulToolTip做任何修改的话,多次测试得到如下结论:
      1 我是双屏幕,每开一个whichtooltip,内存新增差不多30M。

      2 使用BTT的话,如果自己脚本中其他地方有用Gdip,在退出脚本的时候,如果清理自己创建的Gdip(Gdip_Shutdown(pToken)) 会导致AutohotKey崩溃。

      3 执行如下脚本,2秒过后,按ESC会导致AutoHotkey崩溃,把return的注释取消掉,就没事了,不知道什么原因,你可以测试一下。

      #SingleInstance Force
      CoordMode, ToolTip, Screen
      SetTimer,Show, 10
      ;return
      Show:
      Text := “hello world”
      btt(Text,,300,,”Style2″)
      return
      esc::exitapp

    • 空

      我会想想有没有不影响性能和兼容性的,纯改善内存占用的方法。如果没想出来的话,建议还是正常用,不要太在意那点内存占用(想想 chrome 一个页面都比咱全开完占的多 是不是好受一些了😁)

    • 空

      我测试了,return注释取消或不取消,2秒后或2秒内,都正常。

    • jly

      😥 我电脑的问题??
      好的,非常感谢你的脚本及抽空回答!

    • 空

      如果你要开很多个gdip,在初始化函数里,传入值 1(代表开启多实例)。还有注意返回值不要取一个名字,例如 pToken1 pToken2 pToken3.

    • jly

      好的,我抽空再试试

  7. jly

    SysGet, VirtualWidth, 78
    SysGet, VirtualHeight, 79
    this.DIBWidth := VirtualWidth
    this.DIBHeight := VirtualHeight

    this[“hbm” A_Index] := CreateDIBSection(this.DIBWidth, this.DIBHeight)

    如果创建hbm的时候,使用这个虚拟屏幕,则执行Gdip_GraphicsClear后,内存立即升高,我是双屏幕测试,内存立即升高到30多M。

  8. 汉文

    感谢大佬分享

  9. 浪子

    這邊高手真多,謝謝大老的分享,有的學習了。

  10. 1河许人

    一位网友,基于btt做的multibtt。
    #include

    CoordMode, ToolTip, Screen
    t1 := new muti_btt(“11111111”, 100, 100, 1000)
    t2 := new muti_btt(“22222222”, 200, 200, 2000)
    t3 := new muti_btt(“33333333”, 300, 300, 3000)
    t4 := new muti_btt(“44444444”, 400, 400, 4000)
    t5 := new muti_btt(“55555555”, 500, 500, 5000)
    class muti_btt {
    static s_tooltip_number := 1
    __New(txt, x, y, show_time) {
    this.timer := ObjBindMethod(this, “Tick”)
    this.x := x
    this.y := y
    this.txt := txt
    this.show_time := show_time
    this.which := this.base.s_tooltip_number
    if(this.base.s_tooltip_number == 20)
    {
    this.base.s_tooltip_number := 0
    }
    this.base.s_tooltip_number++
    this.Start()
    }
    Start() {
    timer := this.timer
    SetTimer % timer,% -this.show_time
    btt(this.txt, this.x, this.y, this.which)
    }
    Stop() {
    timer := this.timer
    SetTimer % timer, Off
    btt(,,, this.which)
    }
    Tick() {
    this.stop()
    }
    }

个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索