From a970c6db8c6b04ac30336f7a0b285fff5e83aa2b Mon Sep 17 00:00:00 2001 From: Cheney Date: Thu, 29 Oct 2026 16:06:53 +0800 Subject: [PATCH] =?UTF-8?q?nameit:=20=E9=80=9A=E7=94=A8=E5=8C=96=E8=AE=BE?= =?UTF-8?q?=E5=A4=87=E5=90=8D=E6=B0=B4=E5=8D=B0=EF=BC=88AHK=20v2=EF=BC=89?= =?UTF-8?q?=EF=BC=8C=E6=94=AF=E6=8C=81=E9=85=8D=E7=BD=AE/=E5=BC=80?= =?UTF-8?q?=E6=9C=BA=E8=87=AA=E5=90=AF/README?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 155 ++++++++++++++++++++++++ docs/preview.png | Bin 0 -> 5785 bytes nameit.ahk | 307 +++++++++++++++++++++++++++++++++++++++++++++++ nameit.ini | 36 ++++++ 4 files changed, 498 insertions(+) create mode 100644 README.md create mode 100644 docs/preview.png create mode 100644 nameit.ahk create mode 100644 nameit.ini diff --git a/README.md b/README.md new file mode 100644 index 0000000..87a72bf --- /dev/null +++ b/README.md @@ -0,0 +1,155 @@ +# nameit —— 屏幕角落设备名水印 + +在屏幕任意角落常驻显示一段文字(默认是本机**电脑名**),像水印一样浮在所有窗口最上层, +**鼠标点击完全穿透**,不影响任何操作。白色字身 + 黑色描边,深浅背景都清晰。 + +![效果预览](docs/preview.png) + +> 上图:同样一段文字,上半部在白色背景上(黑色描边清晰),下半部在深色背景上(白色字身清晰)。 + +--- + +## 1. 依赖 + +只需要 **[AutoHotkey v2](https://www.autohotkey.com/v2/)**,无需 Python / .NET / 任何第三方库。 + +- 安装 AHK v2 后,`AutoHotkey64.exe` 通常在 `C:\Program Files\AutoHotkey\v2\`。 +- 脚本用 `A_AhkPath` 记录自身解释器路径,所以 AHK 装在别处也能正常开机自启。 + +## 2. 目录结构 + +``` +D:\workbench\nameit\ +├─ nameit.ahk 主程序(双击即可运行) +├─ nameit.ini 配置文件(文字、字体、颜色、位置) +├─ README.md 本说明 +└─ docs\ + └─ preview.png 效果图 +``` + +## 3. 快速开始 + +1. 双击 **`nameit.ahk`**,屏幕左下角立刻出现电脑名。 +2. 托盘区出现 AutoHotkey 图标,右键可进行全部操作。 + +默认显示的是本机电脑名(`A_ComputerName`)。想改成任意文字,见下面的配置说明。 + +## 4. 开机自启 + +任选一种: + +| 方式 | 操作 | +| --- | --- | +| 托盘菜单(推荐) | 右键托盘图标 → 勾选 **开机自启**;再点一次即取消 | +| 命令行 | `nameit.ahk --install` 设置;`nameit.ahk --uninstall` 取消 | +| 手动 | 把 `nameit.ahk` 的快捷方式放进 `shell:startup` 文件夹 | + +实际做法是在 `%APPDATA%\Microsoft\Windows\Start Menu\Programs\Startup\nameit.lnk` +生成一个指向 `AutoHotkey64.exe "…\nameit.ahk"` 的快捷方式,不写注册表、不改系统设置。 + +## 5. 配置说明(nameit.ini) + +改完保存后,右键托盘图标 → **重新载入配置**(或重启脚本)即可生效。 + +### [general] + +| 键 | 默认 | 说明 | +| --- | --- | --- | +| `Text` | 空 | 显示的文字。**留空 = 自动使用电脑名** | +| `Case` | `as-is` | 大小写:`as-is` 原样 / `upper` 全大写 / `lower` 全小写 | + +### [font] + +| 键 | 默认 | 说明 | +| --- | --- | --- | +| `Face` | 空 | 字体名。留空 = 自动(纯英文 `Segoe UI`,含中文 `Microsoft YaHei UI`) | +| `SizePx` | `50` | **字高,单位像素**(精确到像素,不是磅值) | +| `Weight` | `700` | 字重:`700` 粗体,`400` 常规 | + +### [color] + +| 键 | 默认 | 说明 | +| --- | --- | --- | +| `Text` | `FFFFFF` | 字身颜色,RGB 十六进制 | +| `Stroke` | `000000` | 描边颜色 | +| `StrokeWidth` | `4` | 描边粗细(像素),`0` = 不要描边 | + +### [layout] + +| 键 | 默认 | 说明 | +| --- | --- | --- | +| `Corner` | `bottom-left` | 位置:`top`/`middle`/`bottom` + `left`/`center`/`right` | +| `Monitor` | `1` | 显示器编号,`1` = 主显示器 | +| `MarginX` | `24` | 距屏幕左右边缘的距离(像素) | +| `MarginY` | `18` | 距屏幕上/下边缘的距离(像素,自动避开任务栏) | + +### 常用示例 + +```ini +; 显示固定文字,全大写,字号 72 +[general] +Text=HORSE +Case=upper +[font] +SizePx=72 + +; 放到右上角、第二块显示器 +[layout] +Corner=top-right +Monitor=2 + +; 黑字白边(浅色桌面上就是实心黑字) +[color] +Text=000000 +Stroke=FFFFFF +``` + +## 6. 托盘菜单 + +| 菜单项 | 作用 | +| --- | --- | +| 显示 / 隐藏 | 临时隐藏水印,再点恢复 | +| 重新载入配置 | 重新读取 `nameit.ini` 并重绘 | +| 打开配置文件 | 用默认编辑器打开 `nameit.ini` | +| 开机自启 | 勾选/取消开机启动 | +| 退出 | 结束程序 | + +## 7. 卸载 + +1. 右键托盘图标 → 取消勾选 **开机自启**(或运行 `nameit.ahk --uninstall`)→ **退出**。 +2. 删除 `D:\workbench\nameit` 整个目录即可,不残留注册表项。 + +## 8. 常见问题 + +**Q:双击没反应 / 弹出「不是有效的 Win32 程序」?** +装的是 AHK **v1**。本脚本要求 v2,请到 安装 v2。 + +**Q:文字被任务栏挡住?** +程序定位用的是「工作区」(自动扣掉任务栏),正常不会重叠。若任务栏自动隐藏或换了位置, +拖动后 2 秒内会自动重新对齐。 + +**Q:多显示器只在一块屏上显示?** +默认主显示器(`Monitor=1`)。改 `Monitor=2`、`3`… 即可换屏;编号与 Windows 显示设置里的顺序一致。 + +**Q:全屏游戏 / 视频上看不到?** +独占全屏(DirectX exclusive fullscreen)的程序会盖住所有普通窗口,包括置顶窗口。 +改成「无边框窗口化」即可看到。 + +**Q:字被某些深色/花哨壁纸淹没?** +把 `StrokeWidth` 调大到 `5`~`6`,或反过来用黑字白边(`Text=000000` / `Stroke=FFFFFF`)。 + +**Q:会影响我点击图标吗?** +不会。窗口带 `WS_EX_TRANSPARENT`,鼠标事件直接穿透到下方窗口;也不抢焦点、不出现在 Alt+Tab。 + +## 9. 实现原理(简述) + +- 一个无边框 `WS_EX_LAYERED` 窗口,背景设为色键色,用 `SetLayeredWindowAttributes(LWA_COLORKEY)` + 把背景抠成全透明,只剩文字。 +- 文字用 GDI `CreateFontW(-像素高)` 创建,保证「字高 = 指定像素」;再 `WM_SETFONT` 应用到静态文本控件。 +- 描边 = 以字形为中心、按半径采样一圈整数偏移,叠加多个同色文字层,最上层放白色字身。 +- 置顶用 `WS_EX_TOPMOST` + `WinSetAlwaysOnTop`;穿透用 `WS_EX_TRANSPARENT`;不抢焦点用 `WS_EX_NOACTIVATE`。 +- 每 2 秒按工作区重新定位,应对分辨率/任务栏/显示器变化。 + +--- + +许可:随意使用与修改。 diff --git a/docs/preview.png b/docs/preview.png new file mode 100644 index 0000000000000000000000000000000000000000..94ac873e7deca28ebc9e1fdbc17a6f04a3060aa4 GIT binary patch literal 5785 zcmds*c~nwsyTEC%L9-;yDbvhT4msser*bGYwA2(c#SzV%K%-1eF(5lRbaH4COG{HS zal{Fy6igd6GgBd@G%IsJ(o{e};BKt%o;vH?_1(4Z{pa34Hmv>fywCXV=lN|eJ0G=` zmQ`@<@uGZ8xFjc3|sS3$quX@?6B4@@nFmD13ORnU5O8OjxeN6t?wEfXzPh8Mx#$T zN>ew?8!~zdi{sD_am4cR;pVr?Kn}~}B|tp~{Fb$t$iP5`(ktab4lDk@EwxRzG}hOT zRb>#v9YMci5`BxHr)zG3$)RA-(QJSBP&q|&eQ+OV4X98meq`l^o{^KwcM`}H@~g43 z)fdjl!0xg^hU=G?RI7rX9`uW%t!VjuP3bE%NO5(1pT`E!r>zzHm}+J*6%XUMU%$@G z%v9H2D?ZjdK$c-ck70%yqjq|0PQ7cGEgCi7pl0#z{ljypb9@d9@z4dcihWij6qIn3 zc%{W%JUW_{#3?L*gO-<6`YIric73ibx;}TH0(l*?8pj0d8VbEYK;MOseq_f|dn94H zru4qA!fSPf;p>g{_W4=IYS-b*(yv+W2Ca%eUPMp$L`M}tydX8g-c8T;K}IT<8P4qF z+0DzEw9)IbDqTsjo2cb;3$vpS=_L5nU~^m@e|osB(2YJO*n=9J^lgd(*X{{VdqK^G z(kx<9KtS zZ{0R}eo(Kt$QvLYRJctAc{$&+QE2W>7$54W*q6|{F%b7)`8G+Se78R_ zuyTtmv+~pvwAULwm5N_Lb_L>+5;L^;v!|j`@&i7pbzU&Y3|-EI%?qY2;y9DXMru#y zWpr;mK+A+!csYNC7xAVVBuewJ`Ch>gkF9HT>(mCz^liG{B!mXlyhD4yvn)&UFwoRf zyEeUci7#Hujo3dT%n0Jo2nGBSVJXUyLr*K=JV9B@E`nC#8R>5(trW5hX$iiyJ;{WE z@JRnGFF#CRe7=l!9jgzGc@^Tb`%MYvsb|Q7A>F#*`~{0OJ5)W^X}0nz&^JN49JLTK$(iHo-@ zYc|~Oue*u;JboNz08SkPiDL=SJs{NNT-Yge+-ct5q@_y73eA-$SjWu_O0v~4L>huc z)IysLzkN5y`7oyxEkBo&@|P!m0aJRzZ$8ID+;Aysr}>Pwb=kJw$c8dJ>(PSor0$rx zk{8p9xekt+xE8P6{qCqqql-`KSnEwC4-ChNYL{AX5`owfwSY3Ie!UY}C*$|l<8_=- zEv=5GL>cUT;z3~d7fe0*ds$rQ#RKWMM*YPkMF#+lz1*WT{- z9P$jFM;l9J6+8ns^=q9R&woYi<42hX2*t zoyMc>Yoli(Zuad{e{Uace;ZmtDwCBwmXHh-c$1>XbI5FXV?p@AXWg~PVrq!$OVo-M z#pvC0IXBDLWl@PFuIfxnptPmVEZ`!NNy~5X;58iWu&Y@;WO-rNWZ0Ow_V+BSH3Wu? zx1w&-Ul9A~w6g7t(aBv`RnHHBo>o-naqovMMJ;%K4l5=l;CqSI3Xzd#bneYjc4Sm1X|goUg@P2%X1JzlRnOx_)>*km zG@Qxq$6q`$a286obRw~|@An1E-9mSzL2J!H0dMN(p(0w?28wRt zYI)Fso&Sdhy222K`+hz6%&N7zHg_P)rND*PTC5(2{#GG#M)}vJrg;wI*?ybH*_;v* zVC*FqNVZ4qv6LLKS3E<6IEJ6RGh)9yK4%f1kZk=<1gUTm8-}Ib znS=*aT~Y13_i;w2*Zn9>p93r>i+ShAN`wB+IZLb48ghd8=GMe>r(zeg)TNjOTl zP?mz@s-NugA~!E(0VDI>wT`Vb)GgkgOFGcy#YO){HOc7=L$ye_-OqufhGAdabKQ;+&n3v%4+UvP<&5gIKeogv$xwE^KhWtHTR(49Tg`k#`MGQTa-*x3(3CxJVEHVLRSZ1<>3lu zHi{w;va?Z(GlO`x@N?%h+g`wLTn87m3CsEPCj-hZrke~Kf5(W>sS|b1!+GI4D*5bY zeHJwhid+Lhh;-}og^sk`FX(2DIMo`u?o<38iOA=N>hJ4+jo1(E)J8svND26yE}c^d zgsy7RIzZKLhQp_v-mHUDd#R+3Y4!+qqV*fI&Xu6Y5QPYeN(2_PU2iJ;ML5_wY$f(3 zPZg-co#;z_h(uDIpr`3ixI1rgVfHT)@KCN72o)Ush) z1-2<}asJtADo@r}%)rA;wsa=WY2u=%tn2p1bY1?92sx}}Q&)~T-?c%{BP6h91aqIz5L1G6NOl^;xZ1?QctG(mil!jpe?ct>~1oi+&rBKY2 zMzj{Ox5!rxk6EP-#8!8wQVl!hs}2|%<2mZaeEgeqvt~)=_I$8Uq^b{dC|J-*nlc9V zZ;B5bS~ZVa&BF^`{4PoTxAZ%SM2^aK6jqedqs65)ZPlS}hw&$zp04w8M!uZp`v-*+ zVspphdnPwGiczsFUfb(S&pK8*uN)dlJlX7snYH@qTZR%@_ zOBVh`V|0IR3c%Dq7#nTnn`_@CwGg$0!V(!<7+N(|dmEJP2@L_C>Vk8fRMEo9CP4%V zC}{L*w}r9`4MD#skkrN0{zcL$Ka=!4D`PZWu&1N2x|A+{roGSD!?4B`zCTC6baT!v z;o?t+&X~2)`Jdu`rfa=%OO2c?sIM;26~Fum#(zD|f~$Iq#2JL+O0kaSM$Q^pjLQ)B z;u5gWEg&8IPgey!1}+-?U8yE@iCAtv;^B4rmXhw`F!|zI60ud%V^)Py5gb zQMXqBfR(i657p`}A6k%Q#|!M**E;@DIpSuZQ^64l9T&n6imEKNjn4~QL=^otdbVEr z@?NZ_X7y+;{tM}3B48^CPT#Cz+TMuANwkW>w2b#XK)y1-qp%Hhpj#{XH}Kx*p1#z2 zK;cyX(T;w-g4b&b!rXz*QXO#bpF!LmyW31{>1oz27>{cGDvIm;*@K_Re3;qsX_y`> z_dpU195x-ps;jAA7?Jjji)n;#x+|{R?A8!uK}0{fFo%y5k25g72Bz>$d=7E0u;0G5>_{Y7HFV?}~`&a47eggAK?d#(0apNAd{{6Ea_91EZ zEKKfCJH0H)udgddja^LBKPqu^kbXacGyPepY0gmHKs|~$S$H{$F{%~GrqGzxdJ-8m zqxlG2jxXbwT}hXgAv2 zCq#p@KR`Vb0CfW8vs+#PIC}$(^qtg4#jIhy!XBa-)=5l%P7DV=?fwDSdu@yUj_k$1 zAp58(&;o`5G=e`^LK1*pmkRce2=(Q~Dw^fuCxd9*{3lUV(QYW5Dr8$8r)zxd6bBHg zp_}juC0c;DMh#NuJE#MKXH!_NM@5Ft%lz8p7;kaQ9&bT&CQ;`^0!z{6RjKs!961D{ z#G;)$(uL*hc_>;W4eeR2_8p}()nFnXN`y6asp6V!)A{2m1S$`chwP4U30DdtZ?%4$ zEpETnTl_P0?t4zieER~x-Ps#0ycbTw^W5yA#b|C%u8_^061*Q0Egtcr?dv1b20Of! z{WE5dVlRyhx!a8&??4oeRGDu}6AyxFDcxqBo9zsXID_j9>&Lr*M>dvLcPV-&aj#xy zcn0%UjID~e<7#e!$?F6vE*zd4!@nNlEnLegOSf7NMm+@*=d`clzQpy5%uFh;k2?#6 zhC51WzaUDUX#$d)bKdXp=1`9hbC=v=y*yrF)IY++8R>7)Q9Cq!*10jGI;sG1)~;Ut zW2d+y$!X}?m{|f6zr0%f*Twno^6mc+kAG~Bq7Diy3Cy`+W!D&6;O}J6;X_Al%B}n^ F{s$i<45t79 literal 0 HcmV?d00001 diff --git a/nameit.ahk b/nameit.ahk new file mode 100644 index 0000000..513408b --- /dev/null +++ b/nameit.ahk @@ -0,0 +1,307 @@ +; ============================================================ +; nameit —— 屏幕角落设备名水印(AutoHotkey v2) +; +; 功能:在屏幕指定角落显示设备名/任意文字 +; · 字高按像素精确控制 +; · 白色字身 + 黑色描边,深浅背景都清晰 +; · 始终置顶,鼠标完全穿透 +; 依赖:仅需 AutoHotkey v2(无需其他组件) +; 配置:同目录 nameit.ini,托盘菜单可打开/重载 +; 用法:见 README.md 或运行 nameit.ahk --help +; ============================================================ +#Requires AutoHotkey v2.0 +#SingleInstance Force +Persistent + +APP_NAME := "nameit" +INI := A_ScriptDir "\nameit.ini" +LNK := A_Startup "\" APP_NAME ".lnk" + +; ---------------------- 命令行 ---------------------- +if (A_Args.Length > 0) { + cmd := A_Args[1] + if (cmd = "--install" || cmd = "-i") { + ok := EnsureStartup() + MsgBox(ok ? "已设置开机自启:`n" LNK : "设置开机自启失败,请检查权限。", APP_NAME, ok ? "Iconi" : "Icon!") + } else if (cmd = "--uninstall" || cmd = "-u") { + RemoveStartup() + MsgBox("已取消开机自启。", APP_NAME, "Iconi") + ExitApp + } else if (cmd = "--help" || cmd = "-h" || cmd = "/?") { + MsgBox(UsageText(), APP_NAME, "Iconi") + ExitApp + } +} + +; ---------------------- 读取配置 ---------------------- +if !FileExist(INI) + try FileAppend(IniTemplate(), INI, "UTF-8") + +CFG_TEXT := Cfg("general", "Text", A_ComputerName) +CASE_MODE := Cfg("general", "Case", "as-is") +FONT_FACE := Cfg("font", "Face", "") +FONT_PX := Integer(Cfg("font", "SizePx", "50")) +FONT_WT := Integer(Cfg("font", "Weight", "700")) +COL_TEXT := Cfg("color", "Text", "FFFFFF") +COL_STROKE := Cfg("color", "Stroke", "000000") +STROKE_W := Integer(Cfg("color", "StrokeWidth", "4")) +CORNER := Cfg("layout", "Corner", "bottom-left") +MONITOR := Integer(Cfg("layout", "Monitor", "1")) +MARGIN_X := Integer(Cfg("layout", "MarginX", "24")) +MARGIN_Y := Integer(Cfg("layout", "MarginY", "18")) + +if (CASE_MODE = "upper") + CFG_TEXT := StrUpper(CFG_TEXT) +else if (CASE_MODE = "lower") + CFG_TEXT := StrLower(CFG_TEXT) + +if (FONT_FACE = "") + FONT_FACE := RegExMatch(CFG_TEXT, "[\x{4E00}-\x{9FFF}]") ? "Microsoft YaHei UI" : "Segoe UI" + +if (FONT_PX < 1) + FONT_PX := 50 +if (STROKE_W < 0) + STROKE_W := 0 + +; 透明色键:抠掉这个颜色即"看不见背景";确保不与文字/描边同色 +KEY_COLOR := "0A0A0A" +if (COL_TEXT = KEY_COLOR || COL_STROKE = KEY_COLOR) + KEY_COLOR := "010203" + +; ---------------------- 创建窗口 ---------------------- +hFont := CreateFontPx(FONT_PX, FONT_WT, FONT_FACE) +sz := MeasureText(hFont, CFG_TEXT) + +; WS_EX_TRANSPARENT(0x20) 鼠标穿透 | WS_EX_LAYERED(0x80000) 色键透明 | WS_EX_NOACTIVATE(0x08000000) 不抢焦点 +g := Gui("+AlwaysOnTop -Caption +ToolWindow +E0x20 +E0x80000 +E0x08000000", APP_NAME "Overlay") +g.BackColor := KEY_COLOR +g.MarginX := 0 +g.MarginY := 0 + +padL := STROKE_W + 2 +ctlW := sz.w + 4 +ctlH := sz.h + 4 + +; 1) 黑色描边层:绕字形外圈放多个同色文字控件(BackgroundTrans 使它们互不遮挡) +if (STROKE_W > 0) { + g.SetFont("c" COL_STROKE, FONT_FACE) + for off in RingOffsets(STROKE_W) { + lbl := g.Add("Text", "x" padL + off.x " y" padL + off.y " w" ctlW " h" ctlH " BackgroundTrans", CFG_TEXT) + DllCall("SendMessageW", "Ptr", lbl.Hwnd, "UInt", 0x0030, "Ptr", hFont, "Ptr", 1) ; WM_SETFONT + } +} + +; 2) 字身层(最后添加 = 位于最上层) +g.SetFont("c" COL_TEXT, FONT_FACE) +main := g.Add("Text", "x" padL " y" padL " w" ctlW " h" ctlH " BackgroundTrans", CFG_TEXT) +DllCall("SendMessageW", "Ptr", main.Hwnd, "UInt", 0x0030, "Ptr", hFont, "Ptr", 1) ; WM_SETFONT + +W := ctlW + 2 * padL +H := ctlH + 2 * padL + +g.Show("NoActivate w" W " h" H) +WinSetAlwaysOnTop(1, "ahk_id " g.Hwnd) +DllCall("SetLayeredWindowAttributes", "Ptr", g.Hwnd, "UInt", BGR(KEY_COLOR), "UInt", 255, "UInt", 1) +PlaceOverlay() +SetTimer(PlaceOverlay, 2000) ; 分辨率/任务栏/显示器变化时自动重新定位 + +; ---------------------- 托盘菜单 ---------------------- +A_IconTip := "nameit:" CFG_TEXT +BuildMenu() + +; ====================================================== +; 函数 +; ====================================================== +Cfg(section, key, def) { + global INI + v := "" + try v := IniRead(INI, section, key, "") + return (v = "" ? def : v) +} + +CreateFontPx(pixelHeight, weight, face) { + return DllCall("CreateFontW" + , "Int", -pixelHeight ; 负值 = 字身高度(像素) + , "Int", 0, "Int", 0, "Int", 0 + , "Int", weight + , "UInt", 0, "UInt", 0, "UInt", 0 ; 斜体 / 下划线 / 删除线 + , "UInt", 1 ; DEFAULT_CHARSET + , "UInt", 0, "UInt", 0 + , "UInt", 4 ; ANTIALIASED_QUALITY + , "UInt", 0 + , "WStr", face, "Ptr") +} + +MeasureText(hFont, text) { + hdc := DllCall("GetDC", "Ptr", 0, "Ptr") + old := DllCall("SelectObject", "Ptr", hdc, "Ptr", hFont, "Ptr") + size := Buffer(8, 0) + DllCall("GetTextExtentPoint32W", "Ptr", hdc, "WStr", text, "Int", StrLen(text), "Ptr", size) + DllCall("SelectObject", "Ptr", hdc, "Ptr", old) + DllCall("ReleaseDC", "Ptr", 0, "Ptr", hdc) + return { w: NumGet(size, 0, "Int"), h: NumGet(size, 4, "Int") } +} + +; 半径 radius 的一圈整数像素偏移(去重) +RingOffsets(radius) { + offsets := [] + seen := Map() + steps := 64 + Loop steps { + a := (A_Index - 1) * (360 / steps) * 3.14159265358979 / 180 + dx := Round(Cos(a) * radius) + dy := Round(Sin(a) * radius) + if (!dx && !dy) + continue + k := dx "," dy + if seen.Has(k) + continue + seen[k] := 1 + offsets.Push({ x: dx, y: dy }) + } + return offsets +} + +BGR(c) => ((Integer("0x" c) & 0xFF) << 16) | (Integer("0x" c) & 0xFF00) | ((Integer("0x" c) >> 16) & 0xFF) + +PlaceOverlay() { + global g, CORNER, MONITOR, MARGIN_X, MARGIN_Y + if !g + return + n := MONITOR + if (n < 1 || n > MonitorGetCount()) + n := 1 + MonitorGetWorkArea(n, &mL, &mT, &mR, &mB) + g.GetPos(, , &w, &h) + + vert := "bottom", horiz := "left" + parts := StrSplit(CORNER, "-") + if (parts.Length >= 2) { + vert := parts[1] + horiz := parts[2] + } + + if (horiz = "left") + x := mL + MARGIN_X + else if (horiz = "right") + x := mR - w - MARGIN_X + else + x := mL + (mR - mL - w) // 2 + + if (vert = "top") + y := mT + MARGIN_Y + else if (vert = "middle") + y := mT + (mB - mT - h) // 2 + else + y := mB - h - MARGIN_Y + + g.Move(x, y) +} + +ToggleOverlay() { + global g + if DllCall("IsWindowVisible", "Ptr", g.Hwnd) + g.Hide() + else + g.Show("NoActivate") +} + +BuildMenu() { + global INI, LNK + A_TrayMenu.Delete() + A_TrayMenu.Add("显示 / 隐藏", (*) => ToggleOverlay()) + A_TrayMenu.Add("重新载入配置", (*) => Reload()) + A_TrayMenu.Add("打开配置文件", (*) => Run('"' INI '"')) + A_TrayMenu.Add() + A_TrayMenu.Add("开机自启", MenuToggleStartup) + A_TrayMenu.Add() + A_TrayMenu.Add("退出", (*) => ExitApp()) + if FileExist(LNK) + A_TrayMenu.Check("开机自启") +} + +MenuToggleStartup(ItemName, ItemPos, MyMenu) { + global LNK + if FileExist(LNK) { + RemoveStartup() + MyMenu.Uncheck(ItemName) + } else { + EnsureStartup() + if FileExist(LNK) + MyMenu.Check(ItemName) + } +} + +EnsureStartup() { + global APP_NAME, LNK + if FileExist(LNK) + return true + try { + sh := ComObject("WScript.Shell") + sc := sh.CreateShortcut(LNK) + sc.TargetPath := A_AhkPath + sc.Arguments := '"' A_ScriptFullPath '"' + sc.WorkingDirectory := A_ScriptDir + sc.IconLocation := A_AhkPath ",0" + sc.Description := "nameit - 屏幕角落设备名水印" + sc.Save() + } catch { + return false + } + return FileExist(LNK) ? true : false +} + +RemoveStartup() { + global LNK + if FileExist(LNK) + try FileDelete LNK +} + +UsageText() { + return "nameit - 屏幕角落设备名水印`n`n" + . "用法:`n" + . " 双击 nameit.ahk 启动水印`n" + . " nameit.ahk --install 设置开机自启(并启动)`n" + . " nameit.ahk --uninstall 取消开机自启`n" + . " nameit.ahk --help 显示本帮助`n`n" + . "配置:编辑同目录 nameit.ini,托盘右键菜单可打开/重新载入。" +} + +IniTemplate() { + return "; ============================================================" "`n" + . "; nameit 配置文件(UTF-8)" "`n" + . "; 修改后:托盘图标右键 -> 重新载入配置(或重启脚本)" "`n" + . "; ============================================================" "`n" + . "" "`n" + . "[general]" "`n" + . "; 显示的文字;留空 = 自动使用本机电脑名" "`n" + . "Text=" "`n" + . "; 大小写:as-is 原样 / upper 全大写 / lower 全小写" "`n" + . "Case=as-is" "`n" + . "" "`n" + . "[font]" "`n" + . "; 字体名;留空 = 自动(纯英文用 Segoe UI,含中文用 Microsoft YaHei UI)" "`n" + . "Face=" "`n" + . "; 字高(像素)" "`n" + . "SizePx=50" "`n" + . "; 字重:700 粗体 / 400 常规" "`n" + . "Weight=700" "`n" + . "" "`n" + . "[color]" "`n" + . "; 字身颜色(RRGGBB)" "`n" + . "Text=FFFFFF" "`n" + . "; 描边颜色(RRGGBB)" "`n" + . "Stroke=000000" "`n" + . "; 描边粗细(像素),0 = 不描边" "`n" + . "StrokeWidth=4" "`n" + . "" "`n" + . "[layout]" "`n" + . "; 位置: top / middle / bottom 配 left / center / right" "`n" + . "; 例如 bottom-left、top-right、middle-center" "`n" + . "Corner=bottom-left" "`n" + . "; 显示器编号:1 = 主显示器,2 = 第二块…" "`n" + . "Monitor=1" "`n" + . "; 到屏幕边缘的间距(像素)" "`n" + . "MarginX=24" "`n" + . "MarginY=18" "`n" +} diff --git a/nameit.ini b/nameit.ini new file mode 100644 index 0000000..d515a1c --- /dev/null +++ b/nameit.ini @@ -0,0 +1,36 @@ +; ============================================================ +; nameit 配置文件(UTF-8) +; 修改后:托盘图标右键 -> 重新载入配置(或重启脚本) +; ============================================================ + +[general] +; 显示的文字;留空 = 自动使用本机电脑名 +Text= +; 大小写:as-is 原样 / upper 全大写 / lower 全小写 +Case=as-is + +[font] +; 字体名;留空 = 自动(纯英文用 Segoe UI,含中文用 Microsoft YaHei UI) +Face= +; 字高(像素) +SizePx=50 +; 字重:700 粗体 / 400 常规 +Weight=700 + +[color] +; 字身颜色(RRGGBB) +Text=FFFFFF +; 描边颜色(RRGGBB) +Stroke=000000 +; 描边粗细(像素),0 = 不描边 +StrokeWidth=4 + +[layout] +; 位置: top / middle / bottom 配 left / center / right +; 例如 bottom-left、top-right、middle-center +Corner=bottom-left +; 显示器编号:1 = 主显示器,2 = 第二块… +Monitor=1 +; 到屏幕边缘的间距(像素) +MarginX=24 +MarginY=18