CでWin9xのスクリーンセーバーを作ってみる 

 自前で作るのはめんどくさそ…… 

 スクリーンセーバーを簡単に作る方法はいろいろ あるだろうけれど、とりあえず、Cを使って作る場合 の取っ掛かりについて(スクリーンセーバー自体の出来とかは 問わないで……自分自身のwinプログラミングの練習のためだから:-)。

 (Windowsでの)スクリーンセーバーはドライバーみたいな 特殊なもんでなくWindowsアプリケーション。 ただ、ちょっと満たすべきことがあって、

タイトルや枠線無しで最大化して常に手前表示で、 多重起動できないくて、 キーやマウス入力があれば終了し、 起動時オプションとして、
   /s スクリーンセーバーの実行
   /c 設定ウインドウの表示
   /p [xxx] プレビュー
   /a [xxx] パスワード
 が必要。 拡張子を.scr にし、 c:\windows\system にいれれば画面のプロパティでの選択肢に現れる。

と、いうものらしい(まだ条件ぬけてるかも)。

 ちょっとめんどいなあ、ってしろものだけれども、MS の Visual C++ には scrnsave.lib というライブラリがあって、これを使えば簡単に スクリーンセーバーが作れるようだ。


 scrnsave.lib 

 しかし、どうもこの scrnsave.lib は Win標準ではなくVC用で、 他の BCC や Watcom 等では scrnsave.lib がついて来ないので 自前で何とかしないと駄目なよう・・・

[2001-12追記]
 が、 LCC-Win32MinGW には scrnsave.lib がついてくるようだ。
とくに MinGW の win32apiライブラリはソースが公開されているようで 他のコンパイラでも使えるみたい(ライセンス的にも?)。

 ためしに下記のサンプルを bcc でもコンパイルするために win32apiライブラリソースから scrnsave.lib の分を抜き出してみたのが これ

 ということで、下記サンプルは vc, bcc, lcc でコンパイルできそ (MinGW はリソースのコンパイルで怒られてしまったので、挫折^^;)。
bccで行うときは各サンプルと同じディレクトリに scrnsave.h とscrnsave.libをコピーしてから mk_bcc.batを実行してください。 逆に他のコンパイラでコンパイルするときは入れちゃ駄目。


 スクリーンセーバーの作り方(のページ) 

 で、scrnsave.libを利用した作り方に関してだけれど、 以下のページに解説があるので、 それを参照のこと(って、これで充分かも)。

http://www2s.biglobe.ne.jp/~maekawa/dev/vc/scrnsave/index.html

上記Webページからすると、ユーザーは以下の

  ScreenSaverConfigureDialog() 引数 /c または無しで起動されたとき用。
                 ユーザが設定するオプション画面など。
  ScreenSaverProc( )      スクリーンセーバー本体処理. 
                 (/s指定起動時).
  RegisterDialogClasses( )   特殊な用途用(?). 
                 普通は真を返すだけでよい模様.

の3つの関数(実質2つ)を作製するのみで、ウィンドウの初期化や 起動時引数の処理はまかせられるようだ。
 あとは,普通のWin用ゲーム(アプリケーション)を作るのと要領は同じ (キー操作や途中の画面サイズ変更などがありえないので、ずっと楽)。

※上記 URL のサンプルプログラムは実行すると、c:\windows に UserStrSS.INI という設定保存ファイルを作る……のでいらなくなったら 自分で消す、と.


 自分なりのサンプル、その1 

[scrnsvr1.lzh]

 先のURL に十分なサンプルがあるけれど、理解のために別パターンとして サンプルを(いくつか)作ってみた. どちらかというと、自力描画のサンプルなのかもしれないけれど。

□動作
 画面いっぱいに、約1/60秒ごとに 約8000個の点を 適当な色でランダムに表示する。
 設定画面での設定は無し。

ソース
 参照元にあったユーザー設定画面は不要なので取っ払った。

 自力描画のサンプルでもあるので、GDIの描画でなく 仮想バッファをとってそこに書き込んだものを最後に 表示するスタイルになっている。

 約 1/60秒ごとにタイマーは設定しているがあまり精度 はよくないし、画面が広いと処理落ちもかなりある。 (32ビット色モードなのでメモリ食い、でもあろう)。

 また、スクリーンセーバーという前提なので、Window サイズ変更などの面倒を考えなくてすむので、シングル バッファであったりと、いろいろ端折っている。

 VisualStudio上でデバッグすると、デバッグのための キー操作でスクリーンセーバーが終わってしまうことが あって、なかなか不便だった。  リモートデバッグするのも手なんだろうけど、それは それで面倒なので、ルート通過チェックのためのルーチン (printf系)を用意して今回はしのいだ(その時のソースが main_dbg.c)。


 自分なりのサンプル、その2 

[scrnsvr2.lzh]

□動作
 640x480の画面で 一定時間ごとに 点や線、箱を10個づつ 適当に上書きしていく。  設定画面で、真中の640x480 で表示するか、画面イッパイに拡大して表示するか を選べる。

□ユーザー設定
 レジストリでなく、いわゆるiniファイル方式 (単に参照元と同様なだけ、と)。  設定画面(ScrnSvr.scr を直接実行など)のダイアログで OK すると  ユーザー設定項目のセーブファイルとして c:\windows\ScrnSvr.tmp が作られる。  不要になったら直接消してください。

ソース
 scrnsvr1.c を改造。
 自力描画としては、点以外に線、箱線、箱塗を追加。  また、とりあえず、1ピクセルの色数は 16 or 32ビット色 どちらかソース中で指定できるようにした。

 設定では 1/60秒間隔にしているけれど、処理落ちやら精度やら でもっと開いてそう……  画面全体を毎フレーム転送するので遅い。特に拡大表示は ビデオカードの性能が頼りで、このままでは余り実用的でないような。


 自分なりのサンプル、その4 

(素材の都合により その3は欠番)
[scrnsvr4.lzh]

□動作
 先のサンプルでは、いったん画面をクリアした状態(真っ暗)になるけれど、 これはデスクトップが表示されたままの画面の上に点をイッパイ 打って埋め尽くし、最初は明るく、後、画面を暗くして消してしまう。
 ユーザ設定画面の項目はなし。

ソース
 デスクトップ画面の取得の必要から内部の仮想VRAMの管理を変更。 やはし基本はdibにしなきゃ不便なのだなあ。 今回は使っていないけれど scrnsvr2 の線やら箱やらのルーチンも 混ざったままになっている。
 画面を消さずにすます方法はお札ばらばら ソース を参照しました。


 scrnsave.lib を使わない方法(へのヒント) 

 とりあえず MinGWwin32apiライブラリを流用すれば scrnsave.lib の機能が 使えるし、そのソースをみれば何やってるかもわかるのだろうけれど、 とりあえず、
  「スクリーンセーバ工作室」 (ホーム)
というページで、APIのみで作る手順の説明と、C++Builder専用の 作成例があるんで、参考になると思います。

 ちなみに VC 付属のサンプル中にも、scrnsave.lib の元ネタのような サンプルがあったと思います(リコンパイルすると scrnsave.lib ができる…… ちゃんと試してないのでよくわかんないけれど)。あと英語だけど MSDN に スクリーンセーバ/ScrnSave作成の解説頁があるみたい。


2000-05-28
2000-09-25 参考リンク切れ対策
2001-12-16 lcc-win32, bccでコンパイルできるように修整 (scrnsave.libの用意)



[back]