2024/01/20(土) [n年前の日記]
#1 [prog] C++とOpenGLで宇宙飛行的なWindows用のスクリーンセーバを作ってみた
ここ最近、C/C++ (MinGW gcc/g++ 6.3.0) と OpenGL を使って色々実験してたけど、ようやく Windwos用のスクリーンセーバを作れたので github にアップロードしておいた。昔あった、「宇宙飛行」みたいな描画をするスクリーンセーバ。
_mieki256/ssstars_opengl: C++ and OpenGL screensaver similar to ssstars.scr.
ユーザ名が日本語になってる環境でも動くことを確認できたし、サブPCに持っていっても動いてくれたので、他の環境でもおそらく動くのではないかなと…。
今回のスクリーンセーバの、プログラミング面のポイントとしては…。
_mieki256/ssstars_opengl: C++ and OpenGL screensaver similar to ssstars.scr.
- ssstars_opengl.scr をダウンロードして、C:\Windows\SysWOW64\ か C:\Windows\System32\ にコピーすれば、「Stars GL」というスクリーンセーバとして選べるようになる。
- Windows10 x64 22H2 で動作確認。
ユーザ名が日本語になってる環境でも動くことを確認できたし、サブPCに持っていっても動いてくれたので、他の環境でもおそらく動くのではないかなと…。
今回のスクリーンセーバの、プログラミング面のポイントとしては…。
- C/C++ と OpenGL で Windwos用のスクリーンセーバを作成できた。
- 実行ファイル(.scr)の中に png画像のバイナリを含めることができた。
- 実行ファイル(.scr)内のpng画像バイナリ = メモリ上のpng画像バイナリを展開して、OpenGL のテクスチャとして利用できた。OpenGLで画像の描画ができた。
- 設定を iniファイルに保存して読み書きできた。
◎ 少し解説 :
プログラム面について少し解説をメモ。
スクリーンセーバの処理は、ssstars_opengl.cpp で行ってる。
_ssstars_opengl/ssstars_opengl.cpp at main - mieki256/ssstars_opengl
C/C++ でWindows用のスクリーンセーバを作成する時は、スクリーンセーバ用のライブラリ scrnsave を利用すると作業が簡単になる。
scrnsave を利用すると、以下の3つの関数を自分で書くだけでスクリーンセーバが作れる。
一番最後の RegisterDialogClasses() は return TRUE; だけ書いておけばいいらしいので、実質2つの関数を書くだけでいい。
フルスクリーン表示を担当する ScreenSaverProc() には、以下のメッセージが飛んでくるので、それぞれ行うべき処理を書けばいい。
設定ダイアログの処理を担当する ScreenSaverConfigureDialog() には、以下のメッセージが飛んでくるので、これもそれぞれ行うべき処理を書けばいい。
設定ダイアログにどんなGUI部品を載せるか、どこに配置するかは、リソースファイル resource.rc の中に書く。
リソースファイルの中で、スクリーンセーバ名も記述できる。
今回のプログラムの、各関数の役割は以下。
png画像を実行ファイルに含めたり、iniファイルの読み書きをするあたりは、以前のメモを参考に。
_C言語でiniファイルの読み書きをしたい - mieki256's diary
_xxdというコマンドがあることを知った - mieki256's diary
_メモリ上のpngバイナリをOpenGLのテクスチャとして利用 - mieki256's diary
スクリーンセーバの処理は、ssstars_opengl.cpp で行ってる。
_ssstars_opengl/ssstars_opengl.cpp at main - mieki256/ssstars_opengl
C/C++ でWindows用のスクリーンセーバを作成する時は、スクリーンセーバ用のライブラリ scrnsave を利用すると作業が簡単になる。
- ヘッダーファイルとして scrnsave.h を include する。
- MinGW (gcc/g++ 6.3.0)なら libscrnsave.a ( or libscrnsavw.a ?) をリンクする。(-lscrnsave を gcc/g++ のオプションとしてつける。)
scrnsave を利用すると、以下の3つの関数を自分で書くだけでスクリーンセーバが作れる。
- ScreenSaverProc() : フルスクリーン表示時の処理
- ScreenSaverConfigureDialog() : 設定ダイアログの処理
- RegisterDialogClasses() : 謎。
一番最後の RegisterDialogClasses() は return TRUE; だけ書いておけばいいらしいので、実質2つの関数を書くだけでいい。
フルスクリーン表示を担当する ScreenSaverProc() には、以下のメッセージが飛んでくるので、それぞれ行うべき処理を書けばいい。
- WM_CREATE : ウインドウが生成された時にメッセージが飛んでくる。初期化時の処理を書く。タイマーもセットする。
- WM_TIMER : タイマーで指定した一定時間毎にメッセージが飛んでくる。各フレームの描画処理を書く。描画内容が少しずつ変化するような処理を書けばアニメーションができる。
- WM_DESTROY : ウインドウ破棄時にメッセージが飛んでくる。終了時の処理を書く。
設定ダイアログの処理を担当する ScreenSaverConfigureDialog() には、以下のメッセージが飛んでくるので、これもそれぞれ行うべき処理を書けばいい。
- WM_INITDIALOG : 設定ダイアログが表示される際にメッセージが飛んでくる。初期化処理を書く。
- WM_COMMAND : 設定ダイアログ上のボタン等が押された時にメッセージが飛んでくる。OKボタンが押された時、Cancelボタンが押された時の処理を書く。
設定ダイアログにどんなGUI部品を載せるか、どこに配置するかは、リソースファイル resource.rc の中に書く。
- #include "resource.h" を最初のほうに書いておく。
- ダイアログは、必ず、DLG_SCRNSAVECONFIGURE というIDを使って定義しておく。このIDにしておくだけで、scrnsaveライブラリが、このダイアログを設定ダイアログとして勝手に(?)表示してくれる。
リソースファイルの中で、スクリーンセーバ名も記述できる。
- IDS_DESCRIPTION を割り当てた文字列が、スクリーンセーバ名。
- Windowsのスクリーンセーバ設定ウインドウ上では、IDS_DESCRIPTION が割り当てられた文字列をスクリーンセーバ名として表示してくれる。
今回のプログラムの、各関数の役割は以下。
- InitGL() : OpenGL関係の初期化処理。
- SetupAnimation() : OpenGL関係の初期化処理と、オブジェクトワークの初期化。
- Render() : 毎フレームの描画処理。オブジェクトの座標を変更して、OpenGLで画面描画をしている。
- CleanupAnimation() : アニメーション関係の終了処理。ワーク等を確保して使っていたなら、ここで解放。
- CloseGL() : OpenGL関係の終了処理。確保して使っていたアレコレを解放。
- writeConfigToIniFile() : iniファイルに設定値を書き込み。
- getConfigFromIniFile() : iniファイルから設定値を読み込み。
png画像を実行ファイルに含めたり、iniファイルの読み書きをするあたりは、以前のメモを参考に。
_C言語でiniファイルの読み書きをしたい - mieki256's diary
_xxdというコマンドがあることを知った - mieki256's diary
_メモリ上のpngバイナリをOpenGLのテクスチャとして利用 - mieki256's diary
◎ 参考ページ :
_How to Scr: Writing an OpenGL Screensaver for Windows
_How to Scr: Sample Code for an OpenGL Screensaver
_OpenGLでスクリーンセーバ作成
_よしいずの雑記帳 スクリーンセーバーの作り方
_MinGWを使ってスクリーンセーバを作ってみた - roshi.tv::blog
_スクリーンセーバの作成 - MAGURO ONLINE Yokohama (WebArchive)
_スクリーンセーバーの作成(scrnsave.lib使用)(dinop.com) (WebArchive)
_C言語でスクリーンセーバーを作ってみる | Ygkrのブログ
_BB Programming Lab.
_How to write a 32bit screen saver
_Holistic Screensavers: Beginning to End
_Writing a windows ScreenSaver in C
_第127章 スクリーンセーバー その1 - Windows SDK編 第2部 - 猫でもわかるプログラミング
_第128章 スクリーンセーバー その2 - Windows SDK編 第2部 - 猫でもわかるプログラミング
_第129章 スクリーンセーバー その3 - Windows SDK編 第2部 - 猫でもわかるプログラミング
_VC++ でスクリーンセーバーのサンプルコード (WebArchive)
_VC++ でスクリーンセーバーのサンプルコード2 (WebArchive)
_スクリーンセーバー作成 (WebArchive)
_How to Scr: Sample Code for an OpenGL Screensaver
_OpenGLでスクリーンセーバ作成
_よしいずの雑記帳 スクリーンセーバーの作り方
_MinGWを使ってスクリーンセーバを作ってみた - roshi.tv::blog
_スクリーンセーバの作成 - MAGURO ONLINE Yokohama (WebArchive)
_スクリーンセーバーの作成(scrnsave.lib使用)(dinop.com) (WebArchive)
_C言語でスクリーンセーバーを作ってみる | Ygkrのブログ
_BB Programming Lab.
_How to write a 32bit screen saver
_Holistic Screensavers: Beginning to End
_Writing a windows ScreenSaver in C
_第127章 スクリーンセーバー その1 - Windows SDK編 第2部 - 猫でもわかるプログラミング
_第128章 スクリーンセーバー その2 - Windows SDK編 第2部 - 猫でもわかるプログラミング
_第129章 スクリーンセーバー その3 - Windows SDK編 第2部 - 猫でもわかるプログラミング
_VC++ でスクリーンセーバーのサンプルコード (WebArchive)
_VC++ でスクリーンセーバーのサンプルコード2 (WebArchive)
_スクリーンセーバー作成 (WebArchive)
◎ 余談。スクリーンセーバの関連情報がどんどん消えている気がする :
思考メモ。完全に余談。
C/C++でスクリーンセーバを作る方法について色々ググって眺めてたけど、どうもこのあたり、解説ページがどんどん消滅している気がする…。WebArchive に残っていればまだ助かるけれど、残ってない場合もチラホラあって…。
「スクリーンセーバなんて今時使うやつ居ないだろ」という風潮で消えつつあるのだろうか…。ディスプレイがブラウン管から液晶に変わったことで、画面の焼き付き防止というスクリーンセーバの実用性は、たしかにもう求められていないし…。
ただ、スクリーンセーバというものは、まだ実用性があった頃から少しずつ、観賞して楽しむものに変化したジャンルで…。つまるところ、日常生活にちょっとした潤いを与えてくれる、実にさりげないCGアート作品群に変質していた。なのに「実用性」「実用性」って…。
例えば、壁にA5〜B5サイズの額縁に入った絵画がひっそり飾られていたとして。「こんなもん実用性無いだろ。無駄だ無駄」と、君は平気でソレをゴミ箱に突っ込むのかと。実用性があるものはこの世に存在する価値があって、実用性がないものは無価値だからどんどん削除していくべきだと…。0/1だけで考えるのですかと。
そう考えると、スクリーンセーバの作り方について解説してるページが少しずつ消滅している状況があるとしたら、仮にその理由が「スクリーンセーバなんて今時使うやつ居ねえだろ」という理由だったら、それは良くない流れかもしれないなと…。
とは言うものの。スクリーンセーバってインタラクティブ性があるわけでもないので、実は動画でいいんじゃないの? という気もしていて…。昔は動画をPCで再生するのは荷が重かったから、まだその都度計算してシンプルな映像をリアルタイムに提示していくほうが実現性が高かったのだろうけど。今はむしろ動画を再生しちゃうほうが確実(?)だし。
まあ、今となってはメガデモに近いところもあるのかなあ…。制約が特にないから、メガデモと比べたらなんだかゆるゆるだけど。
思考メモです。オチは無いです。
C/C++でスクリーンセーバを作る方法について色々ググって眺めてたけど、どうもこのあたり、解説ページがどんどん消滅している気がする…。WebArchive に残っていればまだ助かるけれど、残ってない場合もチラホラあって…。
「スクリーンセーバなんて今時使うやつ居ないだろ」という風潮で消えつつあるのだろうか…。ディスプレイがブラウン管から液晶に変わったことで、画面の焼き付き防止というスクリーンセーバの実用性は、たしかにもう求められていないし…。
ただ、スクリーンセーバというものは、まだ実用性があった頃から少しずつ、観賞して楽しむものに変化したジャンルで…。つまるところ、日常生活にちょっとした潤いを与えてくれる、実にさりげないCGアート作品群に変質していた。なのに「実用性」「実用性」って…。
例えば、壁にA5〜B5サイズの額縁に入った絵画がひっそり飾られていたとして。「こんなもん実用性無いだろ。無駄だ無駄」と、君は平気でソレをゴミ箱に突っ込むのかと。実用性があるものはこの世に存在する価値があって、実用性がないものは無価値だからどんどん削除していくべきだと…。0/1だけで考えるのですかと。
そう考えると、スクリーンセーバの作り方について解説してるページが少しずつ消滅している状況があるとしたら、仮にその理由が「スクリーンセーバなんて今時使うやつ居ねえだろ」という理由だったら、それは良くない流れかもしれないなと…。
とは言うものの。スクリーンセーバってインタラクティブ性があるわけでもないので、実は動画でいいんじゃないの? という気もしていて…。昔は動画をPCで再生するのは荷が重かったから、まだその都度計算してシンプルな映像をリアルタイムに提示していくほうが実現性が高かったのだろうけど。今はむしろ動画を再生しちゃうほうが確実(?)だし。
まあ、今となってはメガデモに近いところもあるのかなあ…。制約が特にないから、メガデモと比べたらなんだかゆるゆるだけど。
思考メモです。オチは無いです。
[ ツッコむ ]
#2 [prog] HTML+JavScriptでスクリーンセーバを作れないものか
Windows用のスクリーンセーバを作りたいと思った時、C/C++で書かないといけないというのは、ちょっとシンドイよな…。こういうのって、せめて HTML + JavaScriptで書けたりしないものか…。
例えばだけど。
こんな感じのスクリーンセーバがあれば、実質的に HTML+ JavaScriptでWindows用のスクリーンセーバをいくらでも書けるのではないか、と妄想してみたりして…。
ただ、WebView2 とか Electron とかそのへん全然分からないので、そんなことができるのかどうか…。
ちなみに、HSPでやれないかと少し調べてみたけれど、HSPの場合は IEコンポーネントを表示することしかできないようだなと…。それも、ウインドウ表示ならできるけど、全画面表示ができるかどうかはちょっと分からない感じで…。そもそも表示に ActiveX を使っているようだし…。IEコンポーネントだから、昨今の HTML + JavaScript は動かないんじゃないのか、という不安も…。
例えばだけど。
- /p xxxx が渡された時は、xxxxのウインドウハンドルに何か画像を表示してそのまま終了する。
- /c が渡された時は、設定ダイアログを表示して、html のURLを設定してもらう。
- /s が渡された時は、WebView2 とか Electron とかそういうアレを使ってWebブラウザ画面相当を全画面で表示して、設定されたURLを開いて HTML + JavaScript で何か表示する。マウスを動かしたりキーが何か押されたら終了。
こんな感じのスクリーンセーバがあれば、実質的に HTML+ JavaScriptでWindows用のスクリーンセーバをいくらでも書けるのではないか、と妄想してみたりして…。
ただ、WebView2 とか Electron とかそのへん全然分からないので、そんなことができるのかどうか…。
- スクリーンセーバは多重起動禁止にしないといかんのだけど、Electronで作ったデスクトップアプリってそんなことできるのだろうか。
- HTML + JavaScript を表示している間、マウスやキーボードの情報を別途取得して処理したりできるんだろうか。
ちなみに、HSPでやれないかと少し調べてみたけれど、HSPの場合は IEコンポーネントを表示することしかできないようだなと…。それも、ウインドウ表示ならできるけど、全画面表示ができるかどうかはちょっと分からない感じで…。そもそも表示に ActiveX を使っているようだし…。IEコンポーネントだから、昨今の HTML + JavaScript は動かないんじゃないのか、という不安も…。
[ ツッコむ ]
以上、1 日分です。