2026/02/28(土) [n年前の日記]
#1 [golang] Go言語でスクリーンセーバを作れた
Go言語(golang)でWindows用のスクリーンセーバを作れたような気がする。環境は Windows11 x64 25H2 + Go 1.25.7 64bit。
githubにアップロードしておいた。
_mieki256/ssgolang: Go言語(golang)製のWindows用スクリーンセーバサンプル
これで一応、Go言語(golang)を使ってもWindows用のスクリーンセーバを作れることが分かった。
もっとも、今の御時世にスクリーンセーバなんて作ってどうするんだと言われそうではあるけれど…。省電力云々を考えたらPCをスリープさせるか、ディスプレイをスタンバイモードにするほうがいいし…。
ただ、今回作業してみて、Go言語について色々勉強することはできた。
お勉強のための課題として、スクリーンセーバ作成というネタはそんなに悪くない気もする。まあ、作ってみても実用性はゼロなのだけど…。
githubにアップロードしておいた。
_mieki256/ssgolang: Go言語(golang)製のWindows用スクリーンセーバサンプル
これで一応、Go言語(golang)を使ってもWindows用のスクリーンセーバを作れることが分かった。
もっとも、今の御時世にスクリーンセーバなんて作ってどうするんだと言われそうではあるけれど…。省電力云々を考えたらPCをスリープさせるか、ディスプレイをスタンバイモードにするほうがいいし…。
ただ、今回作業してみて、Go言語について色々勉強することはできた。
- go mod init xxxx や go mod tidy というコマンドがあると知った。
- go build でビルドできることが分かった。
- go-task や go-winres というツールがあることを知った。
- Ebitengine の使い方も少し分かった。
- golang.org/x/sys/windows や lxn/win で Windows APIを利用できると知った。
- Go言語の defer、便利ですね。
お勉強のための課題として、スクリーンセーバ作成というネタはそんなに悪くない気もする。まあ、作ってみても実用性はゼロなのだけど…。
◎ 余談 :
自分がどうしてスクリーンセーバの作り方についてアレコレ調べてるかというと、それはおそらくスクリーンセーバというジャンルが盛況だった頃に作り方を全然知らないまま過ごしてしまったからだろうなと…。「こういうのってどうやって作るんだろう?」と疑問を持ったままここまで来てしまったので、そのあたりがずっと引っ掛かっていて…。子供の頃に○○を買ってもらえなかったので大人になってから爆買いするようになった、みたいな状態に近い…?
当時、Windows用の何かしらを作るためには、開発環境を揃えるだけでもそれなりのお金が必要だった気がする…。Windows上で利用できるCコンパイラは有償製品ばかりだったし…。何をどうしたら作れるのかさっぱり分かっていないのに、いきなり有償製品を買うというのも、ちょっと勇気が…。ネットも普及してなかったから情報は書籍経由で入手するしかなかったし…。
今は無料で色々な開発環境が入手できるから、気になったらすぐに試用を始められるし、ググれば何かしらの情報に辿り着けるから、いい時代になったなと…。求められるのは、やる気だけ。いや、時間も必要か…。
どうせそのうちAIにお願いすればソースコードが数秒で出てくる時代になりそうでもあるけど。
当時、Windows用の何かしらを作るためには、開発環境を揃えるだけでもそれなりのお金が必要だった気がする…。Windows上で利用できるCコンパイラは有償製品ばかりだったし…。何をどうしたら作れるのかさっぱり分かっていないのに、いきなり有償製品を買うというのも、ちょっと勇気が…。ネットも普及してなかったから情報は書籍経由で入手するしかなかったし…。
今は無料で色々な開発環境が入手できるから、気になったらすぐに試用を始められるし、ググれば何かしらの情報に辿り着けるから、いい時代になったなと…。求められるのは、やる気だけ。いや、時間も必要か…。
どうせそのうちAIにお願いすればソースコードが数秒で出てくる時代になりそうでもあるけど。
[ ツッコむ ]
#2 [nitijyou] 犬用のワイヤーを購入
車庫の横に設置してある犬用のワイヤーが千切れかかっていたので、DCMホーマックでワイヤーを購入。
鎖のほうがいいのかなと思ったけれど、ワイヤーより鎖のほうが高かった…。
- Petio タフギア ワイヤーチェーンプラス。商品コード W24590。商品名 タフギア ワイヤーチェーン プラス 3.5mm レッド。適応体重20kgまで。中型犬用。長さ137cm。色は赤。本体ワイヤー長が115cm。取付け用ワイヤー長が輪っか状態で22cm。合わせて137cm、ということらしい。本体ワイヤー、取り付け用ワイヤー、小判カンのセット。材質 鉄+塩化ビニル樹脂。税込2,728円。
鎖のほうがいいのかなと思ったけれど、ワイヤーより鎖のほうが高かった…。
[ ツッコむ ]
#3 [nitijyou] 電気カミソリが分解できなくて困ってる
愚痴です。
台所に置いてある、不燃ごみが入ってるダンボール箱の中身を目にしたら、電気カミソリが入っていた。親父さんがそのまま捨てたらしい。型番は National ES8046。充電式。Panasonic じゃなくて National なのか…。
この手の電気カミソリを捨てる際は、分解して、中に入ってるバッテリーを取り出した状態で捨てないといけない。廃棄時の分解の仕方は取扱説明書にちゃんと書いてあるし、「必ずバッテリーを取り出してから捨てるように」とも書いてある。今回の親父さんの行為は完全にアウト。こういう捨て方をしちゃいけない。
てなあたりを親父さんに注意したけれど、もうボケちゃってるから何がいけないのか全然ピンと来てない様子。仕方ない。自分が分解してバッテリーを取り出すしかないな…。
しかし確認してみたら、ネジ穴が潰れちゃっていて、ネジが外せず分解できない。あの糞オヤジ…。さては自分で分解して修理しようとしてサイズの合わないドライバーでグリグリやって潰しやがったな…。LR44とLR1130の違いすら分からない状態だから平気でそういうことをやらかす…。これじゃ分解できないし、バッテリーも取り出せないだろ…。
中に入ってるバッテリーはリチウムイオン充電池。あかん。衝撃や高熱で火を噴いたり爆発するタイプやん。これは絶対に取り出さないと。しかし本来の手順では分解できない。どうしたもんか。
ネジ穴が潰れたネジを取り外す方法をググってみたけれど、ガムテープを使ったり、瞬間接着剤を使う方法を試してもダメだった。専用工具が必要かな…。しかしそれだって5分以上延々トライしてようやく、といった状態になるらしい。購入しても本当に役立つのかどうか…。
ノコギリで部分的に切ってどうにかできないものか…。尻のパーツさえ外せたら他のパーツも外せるはずなんだけど…。なんでこんな設計にしたんだ、って防水も売りにしてる製品だからか。参ったなあ…。
こういうのって市販のニッケル水素充電池で動くように作れないものかな…。そうすればバッテリーの取り外しで悩まなくても済むのに…。電池ケースの蓋のあたりを防水にするのが難しいのだろうか。でも、タミヤの水中モータだって一応防水は実現できてるよな…。だけどアレも気づいたら中に水が入っちゃったりしてたか…。
リチウムイオン充電池が入ってるから、容易にケースを開けられる設計ではマズイ。しかし廃棄時は分解できないと困るから、それなりに分解しやすい設計じゃないとマズい。相反する仕様を求められる。設計するのは面倒臭いだろうなあ…。
とにかく困った。どうしよう。
台所に置いてある、不燃ごみが入ってるダンボール箱の中身を目にしたら、電気カミソリが入っていた。親父さんがそのまま捨てたらしい。型番は National ES8046。充電式。Panasonic じゃなくて National なのか…。
この手の電気カミソリを捨てる際は、分解して、中に入ってるバッテリーを取り出した状態で捨てないといけない。廃棄時の分解の仕方は取扱説明書にちゃんと書いてあるし、「必ずバッテリーを取り出してから捨てるように」とも書いてある。今回の親父さんの行為は完全にアウト。こういう捨て方をしちゃいけない。
てなあたりを親父さんに注意したけれど、もうボケちゃってるから何がいけないのか全然ピンと来てない様子。仕方ない。自分が分解してバッテリーを取り出すしかないな…。
しかし確認してみたら、ネジ穴が潰れちゃっていて、ネジが外せず分解できない。あの糞オヤジ…。さては自分で分解して修理しようとしてサイズの合わないドライバーでグリグリやって潰しやがったな…。LR44とLR1130の違いすら分からない状態だから平気でそういうことをやらかす…。これじゃ分解できないし、バッテリーも取り出せないだろ…。
中に入ってるバッテリーはリチウムイオン充電池。あかん。衝撃や高熱で火を噴いたり爆発するタイプやん。これは絶対に取り出さないと。しかし本来の手順では分解できない。どうしたもんか。
ネジ穴が潰れたネジを取り外す方法をググってみたけれど、ガムテープを使ったり、瞬間接着剤を使う方法を試してもダメだった。専用工具が必要かな…。しかしそれだって5分以上延々トライしてようやく、といった状態になるらしい。購入しても本当に役立つのかどうか…。
ノコギリで部分的に切ってどうにかできないものか…。尻のパーツさえ外せたら他のパーツも外せるはずなんだけど…。なんでこんな設計にしたんだ、って防水も売りにしてる製品だからか。参ったなあ…。
こういうのって市販のニッケル水素充電池で動くように作れないものかな…。そうすればバッテリーの取り外しで悩まなくても済むのに…。電池ケースの蓋のあたりを防水にするのが難しいのだろうか。でも、タミヤの水中モータだって一応防水は実現できてるよな…。だけどアレも気づいたら中に水が入っちゃったりしてたか…。
リチウムイオン充電池が入ってるから、容易にケースを開けられる設計ではマズイ。しかし廃棄時は分解できないと困るから、それなりに分解しやすい設計じゃないとマズい。相反する仕様を求められる。設計するのは面倒臭いだろうなあ…。
とにかく困った。どうしよう。
[ ツッコむ ]
#4 [nitijyou] 親父さんが退院
詳細はGRPでメモ。
[ ツッコむ ]
2026/02/27(金) [n年前の日記]
#1 [golang] Go言語でスクリーンセーバを作れないか実験中。その2
Go言語(golang)でWindows用のスクリーンセーバを作れそうかどうか実験しているところ。環境は Windows11 x64 25H2 + Go 1.25.7 64bit。
◎ フルスクリーン表示時の不具合について :
昨日の時点ではフルスクリーン表示になった時に表示が固まったり暗い画面しか出てこなかったりしたけれど、Ebitengine利用時に以下の対策を入れてみたら改善した…。ような気がする。
この修正をしたら、10回ぐらいスクリーンセーバを起動させてもおかしな状態にはならなかった。どの修正が効いてくれたのか分からないけれど、それっぽく動いてるから、まあええやろ…。
- ebiten.SetFullscreen(true) を呼ばずにフルスクリーン表示するようにした。
- OpenGLを利用するように強制した。os.Setenv("EBITENGINE_GRAPHICS_LIBRARY", "opengl") を追加。
- テクスチャの解放をするようにした。
- ebiten.SetWindowFloating(true) を呼ばないようにした。最前面表示を指定するAPIらしい。
この修正をしたら、10回ぐらいスクリーンセーバを起動させてもおかしな状態にはならなかった。どの修正が効いてくれたのか分からないけれど、それっぽく動いてるから、まあええやろ…。
◎ Windows APIの操作 :
昨日の段階では golang.org/x/sys/windows だけを使って Windows API を操作していたのだけど。
_windows package - golang.org/x/sys/windows - Go Packages
ウインドウ生成その他をするために API の定義をしないといけなくて、このあたり何かしらのライブラリでまとめてあったりしないのかなと思えてきた。
AI(Google Gemini)に尋ねてみたらいくつかライブラリを提案されたけれど、github.com/lxn/win が良さそうだなと…。
_win package - github.com/lxn/win - Go Packages
_lxn/win: A Windows API wrapper package for the Go Programming Language
"github.com/lxn/win" を import したら、win.* という記述でAPIや定数が利用できるようになった。大量に並んでいた独自定義部分をごっそり削除することができた。
_windows package - golang.org/x/sys/windows - Go Packages
ウインドウ生成その他をするために API の定義をしないといけなくて、このあたり何かしらのライブラリでまとめてあったりしないのかなと思えてきた。
AI(Google Gemini)に尋ねてみたらいくつかライブラリを提案されたけれど、github.com/lxn/win が良さそうだなと…。
_win package - github.com/lxn/win - Go Packages
_lxn/win: A Windows API wrapper package for the Go Programming Language
"github.com/lxn/win" を import したら、win.* という記述でAPIや定数が利用できるようになった。大量に並んでいた独自定義部分をごっそり削除することができた。
[ ツッコむ ]
#2 [movie] 「ゴールデンカムイ 北海道刺青囚人争奪編」特別編集版を視聴
金曜ロードショーで放送されていたので視聴。漫画を原作とする実写ドラマの総集編らしい。1話につき60分、全9話を、2時間の尺に編集。
9時間を2時間にするわけだからダイジェストになるのは必然で、原作やアニメ版を見ている人ならともかく、初見でこの版だけを視聴しても話の流れがさっぱり分からないだろうとは感じたけれど。それでも色々と本気で作ってることは伝わってくる映像だった。原作リスペクト感がスゴイ…。台詞にしろ構図にしろ、そこまで再現するか…。
9時間を2時間にするわけだからダイジェストになるのは必然で、原作やアニメ版を見ている人ならともかく、初見でこの版だけを視聴しても話の流れがさっぱり分からないだろうとは感じたけれど。それでも色々と本気で作ってることは伝わってくる映像だった。原作リスペクト感がスゴイ…。台詞にしろ構図にしろ、そこまで再現するか…。
[ ツッコむ ]
2026/02/26(木) [n年前の日記]
#1 [golang] Go言語でスクリーンセーバを作れないか実験中
Go言語(golang)でWindows用のスクリーンセーバを作れそうかどうか実験しているところ。環境は Windows11 x64 25H2 + Go 1.25.7 64bit。
Windows用スクリーンセーバには3つのモードがある。コマンドラインオプションに応じて動作を変えないといけない。
今回は以下のような処理にする。
たぶんこの構成(?)で実現できるのではないかなあと思っているのだけど…。
プレビュー画面モードだけがちょっと面倒臭い。HWND(ウインドウハンドル)を利用して子ウインドウを作成するというのがちょっと…。このあたりの処理をするだけでも、結構ソースが長くなってしまう…。
Windows用スクリーンセーバには3つのモードがある。コマンドラインオプションに応じて動作を変えないといけない。
- /s : フルスクリーン表示モード。
- /c or /c:HWND or コマンドラインオプション無し : 設定画面モード。
- /p HWND : プレビュー画面モード。
今回は以下のような処理にする。
- フルスクリーン表示モード : Go言語で2Dゲームを制作できると謳う Ebitengine を使用。
- 設定画面モード : Windows API の MessageBox を呼んで「設定項目は無いよ」と表示。
- プレビュー画面モード : Windows API で、与えられたHWNDを親ウインドウとした子ウインドウを作成して、その中にbmp画像を表示するだけにする。
たぶんこの構成(?)で実現できるのではないかなあと思っているのだけど…。
プレビュー画面モードだけがちょっと面倒臭い。HWND(ウインドウハンドル)を利用して子ウインドウを作成するというのがちょっと…。このあたりの処理をするだけでも、結構ソースが長くなってしまう…。
◎ リソースファイル作成で悩んだ :
リソースファイルにはアイコンやファイルバージョン等を含めることができるけれど、Windows用スクリーンセーバを作る場合、リソースファイルに STRINGTABLE なる種類のデータを用意して、そこでスクリーンセーバ名を記述しないといけない。
_第128章 スクリーンセーバー その2
_スクリーンセーバーを作ったが、名前を設定できずにファイル名になってしまう
_よしいずの雑記帳 スクリーンセーバーの作り方
また、今回作ろうとしているスクリーンセーバは、プレビュー画面モード用にbmp画像を内包しないといけないので、そのあたりもリソースファイルに記述したい。
MinGW等に付属している windres を使えばそういった記述が可能なのだけど…。今回、go-winres というツールを使って済ませられないかと思ってしまって、そこから悩み始めてしまった。書き方が分からない…。
_tc-hib/go-winres: Command line tool for adding Windows resources to executable files
go-winres は windres と違って、winres.json というjsonファイルにリソースについて記述していくのだけど…。
bmp画像については、おそらく "RT_BITMAP" という指定でいいのかなと…。github上のサンプル(?)にもそういう記述が見えるし…。
_go-winres/_testdata/test.json at main - tc-hib/go-winres
ただ、STRINGTABLE はどう書けばいいのか分からない…。いくらググっても使用事例が見つからない…。AI(Google Gemini)に尋ねてもエラーが出る書き方ばかり提示してくる。学習元となる情報がおそらく存在しないから嘘を言ってくるのだろう…。
解決策が見つからなくて、結局 MinGW の windres を使ってリソースを書くことにしてしまった。しかしこれだと、ビルド時には go.exe 以外にも MinGW が必要になってしまう…。
_第128章 スクリーンセーバー その2
_スクリーンセーバーを作ったが、名前を設定できずにファイル名になってしまう
_よしいずの雑記帳 スクリーンセーバーの作り方
また、今回作ろうとしているスクリーンセーバは、プレビュー画面モード用にbmp画像を内包しないといけないので、そのあたりもリソースファイルに記述したい。
MinGW等に付属している windres を使えばそういった記述が可能なのだけど…。今回、go-winres というツールを使って済ませられないかと思ってしまって、そこから悩み始めてしまった。書き方が分からない…。
_tc-hib/go-winres: Command line tool for adding Windows resources to executable files
go-winres は windres と違って、winres.json というjsonファイルにリソースについて記述していくのだけど…。
bmp画像については、おそらく "RT_BITMAP" という指定でいいのかなと…。github上のサンプル(?)にもそういう記述が見えるし…。
_go-winres/_testdata/test.json at main - tc-hib/go-winres
ただ、STRINGTABLE はどう書けばいいのか分からない…。いくらググっても使用事例が見つからない…。AI(Google Gemini)に尋ねてもエラーが出る書き方ばかり提示してくる。学習元となる情報がおそらく存在しないから嘘を言ってくるのだろう…。
解決策が見つからなくて、結局 MinGW の windres を使ってリソースを書くことにしてしまった。しかしこれだと、ビルド時には go.exe 以外にも MinGW が必要になってしまう…。
◎ Ebitengineの動作が怪しい :
一応、Go言語でWindows用スクリーンセーバを作れたような感じになってきたのだけど、動作確認をしてみたら Ebitengine を利用してフルスクリーン表示をしているあたりで問題が発生した。
GPUリセットをしないと画面が出てこないスクリーンセーバなんて致命的過ぎる…。
キーを押したら、デスクトップ画面が表示されたり、マウスカーソルが表示された。つまり、プログラムの終了条件チェック処理は動いている。
ということは、Ebitengine の update() はちゃんと呼ばれ続けている。update() の中でキー入力チェックやマウス関係のチェックをしてプログラムを終了するようにしてあるので、もし update() が呼ばれていない状態に陥っていたら終了することすらできないはず。
となると、Ebitengine が描画関連で不具合を発生させていた、ということになりそうだけど…。
AI(Google Gemini)に尋ねたら、フルスクリーン表示を指定するあたりが怪しいと言い出した。ebiten.SetFullscreen(true) を呼んで済ませずに、ebiten.SetWindowDecorated(false) を呼んでウインドウの枠無しをあえて指定して、ウインドウサイズをディスプレイの解像度に設定してみたらどうか、と言い出したので、ダメ元でそういう処理にしてみた。これって効果あるのかなあ…。
Ebitengine の issue を眺めていたら、クラッシュ報告が結構多いことにも気づいた。Windowsの場合はDirectX12を使おうとしてそこで不具合が発生するからDirectX11にした、という話も見かけたし、DirectX より OpenGL のほうがパフォーマンスも安定性も高いというユーザ報告も見かけた。
OpenGLの使用を強制してみようか…。os.Setenv("EBITENGINE_GRAPHICS_LIBRARY", "opengl") を呼んで、環境変数 EBITENGINE_GRAPHICS_LIBRARY に opengl を設定。本来ここは auto になっていて、OSに応じて適切なものを選んでくれるらしいけど…。
テクスチャの解放もしてなかったので、プログラム終了時にそのあたりも処理するようにした。Go言語には defer という命令があって、これを使うとその関数から抜ける際にその処理をしてくれるらしいので、テクスチャの解放処理を defer で指定しておけばいい。便利だな…。
_Go言語のdeferを正しく理解する | How defer in Golang works #初心者 - Qiita
ただ、os.exit() で強制終了したり、log.Fatal() で処理を打ち切った時は defer で指定した処理は行われないから注意しないといけない。らしい。
_log.Fatalは使わないようにしよう
_【Go】log.Fatalは気軽に使わない #ログ - Qiita
_Go言語のエラーハンドリングについて 〜panic編〜 #Go - Qiita
- 1回目の起動時はそれっぽく動いてくれた。
- 2回目の起動時はスプライト群が表示されたもののピクリとも動かない。画面が固まっている…。
- 3回目の起動時は真っ暗な画面しか出てこない…。Win + Ctrl + Shift + B を叩いてGPUをリセットしないとデスクトップ画面が出てこなかった。
GPUリセットをしないと画面が出てこないスクリーンセーバなんて致命的過ぎる…。
キーを押したら、デスクトップ画面が表示されたり、マウスカーソルが表示された。つまり、プログラムの終了条件チェック処理は動いている。
ということは、Ebitengine の update() はちゃんと呼ばれ続けている。update() の中でキー入力チェックやマウス関係のチェックをしてプログラムを終了するようにしてあるので、もし update() が呼ばれていない状態に陥っていたら終了することすらできないはず。
となると、Ebitengine が描画関連で不具合を発生させていた、ということになりそうだけど…。
AI(Google Gemini)に尋ねたら、フルスクリーン表示を指定するあたりが怪しいと言い出した。ebiten.SetFullscreen(true) を呼んで済ませずに、ebiten.SetWindowDecorated(false) を呼んでウインドウの枠無しをあえて指定して、ウインドウサイズをディスプレイの解像度に設定してみたらどうか、と言い出したので、ダメ元でそういう処理にしてみた。これって効果あるのかなあ…。
Ebitengine の issue を眺めていたら、クラッシュ報告が結構多いことにも気づいた。Windowsの場合はDirectX12を使おうとしてそこで不具合が発生するからDirectX11にした、という話も見かけたし、DirectX より OpenGL のほうがパフォーマンスも安定性も高いというユーザ報告も見かけた。
OpenGLの使用を強制してみようか…。os.Setenv("EBITENGINE_GRAPHICS_LIBRARY", "opengl") を呼んで、環境変数 EBITENGINE_GRAPHICS_LIBRARY に opengl を設定。本来ここは auto になっていて、OSに応じて適切なものを選んでくれるらしいけど…。
テクスチャの解放もしてなかったので、プログラム終了時にそのあたりも処理するようにした。Go言語には defer という命令があって、これを使うとその関数から抜ける際にその処理をしてくれるらしいので、テクスチャの解放処理を defer で指定しておけばいい。便利だな…。
_Go言語のdeferを正しく理解する | How defer in Golang works #初心者 - Qiita
ただ、os.exit() で強制終了したり、log.Fatal() で処理を打ち切った時は defer で指定した処理は行われないから注意しないといけない。らしい。
_log.Fatalは使わないようにしよう
_【Go】log.Fatalは気軽に使わない #ログ - Qiita
_Go言語のエラーハンドリングについて 〜panic編〜 #Go - Qiita
[ ツッコむ ]
以上、3 日分です。