Zenモードで時計を表示する方法
-
AutoHotkey v2を使って実現できたので紹介します。
元々はWindows11のタスクバーの仕様変更により時計をカスタマイズするフリーソフトTTClockが使用できなくなり、代用としてタスクバー上に時計をオーバーライドするElevenClockやDigital Desktop Clockを使用しました。
しかし、重かったのとAutoHotkey v2でも出来そうと試行錯誤したところ実現でき、たまたまMeryのZenモードでも表示されたままになることを発見しました。;; TaskBarClock ;; TaskBarClock := Gui() TaskBarClock.Title := "TaskBarClock" TaskBarClock.MarginX := 8 TaskBarClock.MarginY := 1 TaskBarClock.BackColor := "000000" TaskBarClock.SetFont("s12", "Meiryo UI") TaskBarClock.Opt("+AlwaysOnTop -Border -Caption +Disabled +ToolWindow") ShowClock := TaskBarClock.Add("Text", "cFFFFFF", "2025/01/01 (Mon) 00:00 AM") SetTimer(UpdateClock, 15000) UpdateClock() TaskBarClock.Show("x" A_ScreenWidth-240 " y" A_ScreenHeight-28 " AutoSize NoActivate") ;; UpdateClock() { ShowClock.Value := FormatTime(, "yyyy/MM/dd (ddd) HH:mm tt") } ;; MouseOver(title) { MouseGetPos ,, &id return WinExist(title " ahk_id " id) } ;; ClickClock(key_code) { WinHide "TaskBarClock" if (key_code) { Send(key_code) } else { CoordMode("Mouse", "Screen") MouseClick("left", A_ScreenWidth-160, A_ScreenHeight-16, 1) } WinShow "TaskBarClock" } ;; #HotIf MouseOver("TaskBarClock") LButton:: ClickClock("{LButton}") ;; Show TaskBar Calender RButton:: Run("control timedate.cpl") ;; Time & Date Properties #HotIf| enaka | 返信 -
情報ありがとうございます。
> たまたまMeryのZenモードでも表示されたままになることを発見しました。
なるほど、こうやればタスクバーや他のソフトに依存せずに表示できるんですね。…って、そんなの発見しないでください~😅
でも、プログラムが苦手な方もいると思うので、そういう時はサクッと使える公式の Zen モード時計 プラグインもありますよ (白目)
- インストールするだけで表示
- フォントや位置も簡単に設定可能
- アナログ時計なども選べます
共有いただいた方法も面白いので、興味がある方は両方試してみてくださいね♪
それにしても、AutoHotkey って本当に何でもできちゃいますね。
Mery へのちょっとしたご要望も、AHK を使えば意外と簡単に解決できるものが結構ありそうですね。
| Kuro | 返信 -
> でも、プログラムが苦手な方もいると思うので、そういう時はサクッと使える公式の [Zen モード時計 プラグイン](https://mery.booth.pm/items/4420344)もありますよ (白目)
存じ上げませんでした。シンプルなアナログ時計いいですね。Zenモード以外でも使いたい。
> それにしても、AutoHotkey って本当に何でもできちゃいますね。
時計の副産物で常に最前面のコントロールもAutoHotkey v2で出来てしまいました。さよなら、最前面でポーズ。
;; Always On Top ;; AlwaysOnTop() { MouseGetPos(,, &id) WinActivate(id) WinSetAlwaysOnTop(-1, id) ExStyle := WinGetExStyle(id) if (ExStyle & 0x8) ToolTip "常に最前面 【ON】" else ToolTip "常に最前面 【OFF】" SetTimer(ToolTip, -3000) } ;; Pause:: AlwaysOnTop() ;;> Mery へのちょっとしたご要望も、AHK を使えば意外と簡単に解決できるものが結構ありそうですね。
F3が遠いのでAutoHotkey v2により、Emacs検索風に検索/置換ダイアログ呼出と次候補/前候補を、C-S/C-Rに同居するというのを実現しています。
簡単なので興味がある人への宿題ということで。| enaka | 返信 -
最前面でポーズは PowerToys に乗り換えました。境界線 4px の設定で、最前面であることがはっきりわかります。
enaka さんなら境界線も AHK で実装してしまうかもですが。| TN24 | 返信 -
>> enaka さん
> 存じ上げませんでした。シンプルなアナログ時計いいですね。Zenモード以外でも使いたい。
以前にも今回と似た話題があって、そのときにちょっと遊びで試作してみたんですよね。
【参考】Zenモードに時計を追加できないか
https://www.haijin-boys.com/discussions/6246↑ ダウンロードリンクもありますが、当時のものはけっこう簡易版で、設定も INI ファイルを直接編集するしかありませんでした。
BOOTH 版では、画面上から設定できるようになっていて、ドラッグ アンド ドロップで移動できたり、タイマー機能も追加されています。
たしか「Zen らしく音で通知せず、視覚的にこっそり知らせてほしい」というご要望に応えて、Windows 95 のラインアート風通知やバイナリ時計など、ちょっとマニアックな機能も詰め込みましたw
> 時計の副産物で常に最前面のコントロールもAutoHotkey v2で出来てしまいました。さよなら、最前面でポーズ。
最前面でポーズ、ついに小粒アプリから卒業ですね…。
それにしても、AHK のコード、すごくシンプル!これならアプリを使うより軽くて安心ですね。
>> TN24 さん
> 最前面でポーズは PowerToys に乗り換えました。境界線 4px の設定で、最前面であることがはっきりわかります。
Mery でも、[タイトル バーとウィンドウの境界線を強調表示する] をオンにすると、最前面時に PowerToys みたいに境界線を色付きで表示できるのですが、この機能は残念ながら Windows 11 限定なんですよね…。
私も以前は PowerToys を使っていたのですが、うちの低スペック PC ではちょっと重くて。
そこで、「なんちゃって PowerToys」的な境界線表示機能を Mery に実装してみました。Windows 11 に移行されたときは、ぜひ試してみてください〜。
| Kuro | 返信 -
>enaka さんなら境界線も AHK で実装してしまうかもですが。
試行錯誤したところ実装出来ました。AHK関数だけでは無理だったため、DllCallを用いています。
自分仕様ということで、ダイアログを含めたアクティブなウィンドウに太枠をつけ、常に最前面だった場合には色を変更、としています。
複数ウィンドウ対応等、好きにカスタマイズしてください。> Mery でも、[タイトル バーとウィンドウの境界線を強調表示する] をオンにすると、最前面時に PowerToys みたいに境界線を色付きで表示できるのですが、この機能は残念ながら Windows 11 限定なんですよね…。
Windows10にも対応しました。Windows11ならばDllCallでCreateRectRgnの代わりにCreateRoundRectRgnを使うと角が丸く出来ます。
;; GroupAdd must be written before any Hotkey bindings. ;; GroupAdd("Invalid", "ActiveBorder") ;; AutoHotkey Script GroupAdd("Invalid", "TaskBarClock") ;; : GroupAdd("Invalid", "ahk_exe RetroBar.exe") ;; WindowsXP like Task Bar GroupAdd("Invalid", "ahk_exe StartMenuX.exe") ;; WindowsXP like Start Menu ;; CheckValid(id) { if (WinExist(id) == 0) return 0 for invalid_id in WinGetList("ahk_group Invalid") if (id == invalid_id) return 0 return 1 } ;; ;; ActiveBorder ;; global aot_color := "FF0000" global act_color := "FFFFFF" global act_name := "ActiveBorder" global act_width := 4 global act_preid := 0 global act_X, act_Y, act_W, act_H ActiveBorder := Gui() ActiveBorder.Title := act_name ActiveBorder.BackColor := act_color ActiveBorder.Opt("+AlwaysOnTop -Caption +ToolWindow +E0x20") ActiveBorder.Show("NoActivate") global act_id := WinExist(act_name) SetTimer(UpdateBorder, 500) UpdateBorder() ;; UpdateBorder() { global act_preid, act_X, act_Y, act_W, act_H global act_color, top_color, act_id id := WinExist("A") if (CheckValid(id) == 0) { ActiveBorder.Hide return } Style := WinGetStyle(id) if (Style & 0x20000000) { ActiveBorder.Hide return } ExStyle := WinGetExStyle(id) if (ExStyle & 0x8) ActiveBorder.BackColor := aot_color else ActiveBorder.BackColor := act_color WinGetPos(&X, &Y, &W, &H, id) if (act_preid == id && act_X == X && act_Y == Y && act_W == W && act_H == H) return act_preid := id act_X := X act_Y := Y act_W := W act_H := H outRect := DllCall("CreateRectRgn", "Int", 0, "Int", 0, "Int", W, "Int", H) inRect := DllCall("CreateRectRgn", "Int", act_width, "Int", act_width, "Int", W - act_width, "Int", H - act_width) actRect := DllCall("CreateRectRgn", "Int", 0, "Int", 0, "Int", 0, "Int", 0, "Ptr") DllCall("CombineRgn", "Ptr", actRect, "Ptr", outRect, "Ptr", inRect, "Int", 4) DllCall("SetWindowRgn", "Ptr", ActiveBorder.Hwnd, "Ptr", actRect, "Int", 1) DllCall("DeleteObject", "Ptr", outRect) DllCall("DeleteObject", "Ptr", inRect) ActiveBorder.Show("x" X " y" Y " w" W " h" H " NoActivate") }| enaka | 返信 -
本当に実装されるとは。いやー恐れ入りました。
確かに PowerToys は全体的に軽いとはいえないので、Always On Top のみの使用なら AHK に乗り換えたいところです。私は FancyZones も使っているので、当面は手放せません。| TN24 | 返信 -
>私は FancyZones も使っているので、当面は手放せません。
すでにAHK v1で実装した方がおられるようです。v2には要修正かなあ。
https://github.com/jgpaiva/GridMove軽量な代替アプリもあるようです。
http://windowgrid.net自分は、WindowsSnapすら無効化してWin+Up/Downだけ実装し、また、逆順のタスクスイッチが3つ同時キー押しが辛いので変更しています。
;; Window Switch and Resize ;; WinSize(cur) { global previous_id if WinExist(previous_id) { if (WinGetMinMax(previous_id) == -1 && cur == "up") { WinActivate(previous_id) for id in WinGetList() { if CheckValid(id) { if (WinGetMinMax(id) == -1) { previous_id := id } } } return 0 } } id := WinExist("A") if CheckValid(id) { if (WinGetMinMax(id) == 0 && cur == "up") { WinMaximize(id) return 0 } if (WinGetMinMax(id) == -1 && cur == "up") { WinActivate(id) return 0 } if (WinGetMinMax(id) == 0 && cur == "down") { WinMinimize(id) previous_id := id return 0 } if (WinGetMinMax(id) == 1 && cur == "down") { WinRestore(id) return 0 } } } ;; RWin & Enter:: Send("#{Tab}{Rwin up}") ;; Windows Task View LWin & Enter:: Send("#{Tab}{Rwin up}") ;; Alt & Esc:: ShiftAltTab RWin & Left:: ShiftAltTab LWin & Left:: ShiftAltTab ;; Alt & Tab:: AltTab RWin & Right:: AltTab LWin & Right:: AltTab ;; RWin & Esc:: Send("!{Esc}{Rwin up}") LWin & Esc:: Send("!{Esc}{Lwin up}") ;; RWin & Tab:: Send("!+{Esc}{Rwin up}") LWin & Tab:: Send("!+{Esc}{Lwin up}") ;; RWin & Up:: WinSize("up") LWin & Up:: WinSize("up") RWin & Down:: WinSize("down") LWin & Down:: WinSize("down") ;; Ctrl & Esc:: Send("^+{Tab}") Ctrl & Tab:: Send("^{Tab}") ;; #t:: Run("taskmgr") ;; Task Manager #+t:: Run("taskschd.msc") ;; Task Schedule #w:: Send("#{Tab}{Rwin up}") ;; Windows Task View| enaka | 返信