Windows用Matrix風スクリーンセーバー

matrix-saver

今回は、Windows10,8.1,8上で動作するMatrix風スクリーンセーバーのご紹介です。

本スクリーンセーバーの概要

映画Matrixの文字が流れる画面をイメージした「Matrix風」スクリーンセーバーです。あまりシステムに負担を掛けないように作ってはありますので…完全に映画のあれをコピーできてないような気もしますが…まあ、「風」ということでかんべんしてください(笑)。  

matrix-movie

必要条件

 本スクリーンセーバーは、Windowsでのみ動作します。LinuxやMacでは動作しないですのでご注意ください。また、本スクリーンセーバーを動作させるには、.NetFramework4.5.2以上が必要です。.NetFrameworkの導入方法は、同梱の取説に詳しく書いてありますので、参照してください。 マシンスペックは、それほど高くなくても動作します。この場合。PCに負担をかけないように、動作速度を落としてください。動作速度を落とすには、本スクリーンセーバーをWindowsのエクスプローラで右クリックして「構成」を選択するか、エクスプローラの右クリックから「インストール」を選んで表示されるスクリーンセーバのインストール画面で、「設定」を選んだ時に表示される設定画面(オプション設定画面)の「タイマー間隔」を大きな数字にするか、同画面の「高輝度行の最大数」と「通常行の最大数」を少ない数字に設定して、表示される文字の数を減らしてみてください。 また、初期状態ではWindowsに標準で入っているMSゴシックフォントを使うように設定してあるので、Matrixの雰囲気が出ていません。後述するフォントの変更方法を参考に、フォントを「それらしい」フォントに替えてみて下さい。一気にMatrixっぽくなります(笑)。   

ダウンロード方法

本スクリーンセーバーは、下記のVectorのダウンロードサイトよりダウンロードすることができます。 https://www.vector.co.jp/soft/winnt/amuse/se516928.html   

インストール方法

本ソフトウエアはセットアッププログラムが不要です。ダウンロードしたZIPファイルを適当なフォルダに解凍して、中に入っている「MatrixCodeScreenSaver.scr」をエクスプローラから右クリックし、「インストール」を選んでください。  

install

動作が遅い場合の改善策

※Version1.7.0.0からは動作速度を確保するために文字のサイズを自動的に調整する機能を追加しました。この機能の詳細は後述する「いろいろなチューニング」を参照してください。

本プログラムの動作が遅いと感じる場合の改善策です。もしも、お使いのディスプレイがWQXGAなどの超高解像度ディスプレイの場合や、複数のディスプレイを接続している場合、文字が非常にたくさん表示されてしまい、結果として動作速度が遅くなる場合があります。この場合は、スクリーンセーバーの設定画面にある「フォントサイズ」の値を大きくしてみて下さい。これで劇的に速くなることが多いです。 本スクリーンセーバー動作中に「i」キーを押すと、内部情報が表示されますが、この画面の「画面の桁数」が、だいたい70桁前後になるように、フォントサイズを調整すると良いと思います。また、フォントサイズを大きくし過ぎた結果、文字と文字の間隔があいてしまう場合は、後述する「いろいろなチューニング」の章の「文字の間隔を調整したい」を参考にしてみてください。 設定画面の「高輝度行の最大数」と「通常行の最大数」を小さい値にしてみるのも効果があります。表示される行の数が減る代わりに、より高速に動作するようになります。 【下記の設定項目はバージョン1.6.0.0以降で可能です】 さらに高速化する手段としては、本スクリーンセーバーの設定ファイル(MatrixCodeScreenSaver.ini)の中にある「[option_datas]」セクションの、「SwMirrorImage」という項目を「No」に変えてみてください。鏡文字の表示を抑制し、さらに動作が高速になります。   

option-setting

アンインストール方法

本プログラムをアンインストールする場合、まず、Windowsのデスクトップ画面の何もないところを右クリックして、「個人設定」を選択し、次に画面左側のリンクから「ロック画面」を選択し、表示された画面を下へスクロールして、一番下のほうにある「スクリーンセーバー設定」を選んで、適当に別のスクリーンセーバーを選んで、本スクリーンセーバの使用を中止し、そのあとで、本スクリーンセーバーのファイルをフォルダごと削除すれば終了です。 本スクリーンセーバーは、レジストリに設定情報を書き込んでいますが、ごく少量の情報なので、放っておいても問題ありません。しかし、どうしても気持ち悪いと思う人は、次の章で説明する手順で、レジストリの情報を削除してください。   

uninstall

レジストリのクリア方法

レジストリは、間違った操作をすると、システムを故障させる原因になります。レジストリに関して十分な知識がある方で、システム管理者権限のあるアカウントユーザーでパソコンを操作できる方のみ自己責任において実施してください。繰り返しになりますが、本スクリーンセーバーがレジストリ領域に保存する情報はごく少量ですので、放っておいてもまったく問題ありません。

本スクリーンセーバーが使用しているレジストリ領域を消去するには、画面下のWindowsマークを右クリック、「ファイル名を指定して実行」を選んで、「regedit」と入力。「このアプリがデバイスに変更を与えることを許可しますか?」というダイアログが表示されたら「はい」を選択してレジストリエディタを開きます。次に、「HKEY_CURRENT_USERSoftwareMatrixCode_ScreenSaver」を探します。みつけたらこれを右クリックし、「削除」を選択すれば完了です。くれぐれも別のアプリの情報を削除したりしないように気を付けてください。   

clean-registry

より雰囲気のあるフォントへの変更方法

本スクリーンセーバをダウンロードしたまま使用すると、動作を保証するためにWindowsパソコンなら必ず入っているフォントの「MSゴシック」を選択するようになっています。このままでも、まあすこしはMatrix風かもしれませんが、まあ普通の文字が落ちてくるスクリーンセーバーになってしまいます。ですので、無料で入手できて、それなりにMatrix的な雰囲気が出るフォントを入れたほうがより雰囲気が増すので、ここでそういったフォントの入手先をご紹介します。 ここのサイトにある無料フォントの、「白舟古印体教漢」や、「白舟行書Pro教漢」などが結構良い感じにMatrixの雰囲気を出してくれているような気がします。白舟古印体教漢ならば、フォントサイズ16~18、太字(Bold)ではなくRegularで使用。白舟行書Pro教漢ならば、やはりフォントサイズ16~18で、Regularではなく太字で使用すると、結構良いように思います。 

matrix-compare

 フォントをパソコンにインストールするには、フォントをダウンロードして適当なフォルダに保存したら、エクスプローラで右クリックして「インストール」を選択すればOKです。その後、本スクリーンセーバーの設定画面を開いて、インストールしたフォントを選択し、サイズとスタイルを指定すれば完了です。 使用できるフォントに関しては、アルファベット、数字、カタカナが表示できるフォントであれば、たいていなんでもOKです。漢字が収録されていないようなサンプルのようなフォントでも大丈夫です。そもそもスクリーンセーバー上の文字に漢字を使っていないので問題なく使うことができます。   

font-select-howto

キーボードコマンド

本スクリーンセーバーには、キーボードを押下すると様々な表示をさせることができる仕組みが組み込まれています。このことを、キーボードコマンドと呼んでいます。キーボードコマンドは、構成情報が保存されているiniファイル内で定義できます。まず、iniファイルをテキストエディタで開くことができるように、拡張子の関連付けをしておいてください。つぎに、本スクリーンセーバーの設定画面を開き、右下の「構成ファイル」ボタンを押下します。すると、設定が保存してあるiniファイルを編集できるようになります。これは、本スクリーンセーバーの「MatrixCodeScreenSaver.scr」が置いてある同じフォルダにある「MatrixCodeScreenSaver.ini」をテキストエディタで開いても同じです。 次に、このiniファイルの下のほうにある「[keybd_values]」セクションを見つけてください。KeyPreXXValue, KeyPreXXMessg,KeyPreXXCommdという3つの設定条項が1つのペアになっており、XXの部分には、01から10までの数字が入ります。つまり、この3つのペア(キーボードコマンド)を10こまで定義できるという事になります。

keybcmd
設定項目の説明
KeyPreXXValue キーボードの文字(1文字)。このキーが押されたときに動作する
KeyPreXXMessg 表示するメッセージ
KeyPreXXCommd キーボードコマンド

では次に、キーボードコマンドとして使えるコマンドを説明します。

キーボードコマンドの説明
EndScreenSaver 指定されたメッセージを表示した後で動作を終了する
DisplaySystemVersion 指定されたメッセージとシステムバージョンを表示する
DynamicMessage 指定されたメッセージを動作を止めずに表示する
Message 指定されたメッセージを動作を停止して表示する
DisplayDateTime 指定されたメッセージと日時を表示する
DisplayInnerInfo 現在の設定値のサマリーを表示する

本スクリーンセーバは、最初にいくつかのキーボードコマンドがプリセットされています。以下に、どのキーになにが割り当てられているか記述します。

プリセット済みキーボードコマンド
キーボード  コマンド      メッセージ
o     EndScreenSaver     Follow the White rabbits …
v     DisplaySystemVersion  System Version
y     DynamicMessage     This is Dynamic Message System
d     DisplayDateTime     時刻表示
i      DisplayInnerInfo     内部情報表示

いろいろなチューニング

ではここで、本スクリーンセーバーのチューニングのヒントを書きたいと思います。

自動文字サイズ調整を変更したい

 Version1.7.0.0以降では、動作速度の確保のために、文字サイズを自動的に調整する機能が追加されています(デフォルトでONになっています)。この機能は、iniファイルの「[option_datas]」セクションにある「AutoCharSizes」を「No」にすることで機能を停止できます。自分で文字サイズを修正したい場合などはこのオプションをNoに変更してください。文字サイズを小さくしすぎて一度にたくさんの文字を表示させようとすると、CPUに負荷がかかり、極端に動作スピードが遅くなりますのでご注意ください。また、この機能を使用している場合は、設定情報の画面の「フォントサイズ」の項目と、iniファイルの「[option_datas]」セクションにある「GapInsertions」の値が修正されます。フォントサイズは情報が書き換わり、GapInsertionsはiniファイルの設定値とは違う修正後の値が使用され、iniファイルは更新されません。

マウスを動かした時にスクリーンセーバを終了したい

 本スクリーンセーバーは、デフォルトではマウスボタンのクリックか、キーボードの押下でしかスクリーンセーバーを終了させませんが、マウスを少し動かしたときにスクリーンセーバーを終了させることもできます。 iniファイルの「[option_datas]」セクションにある「EndOnMuseMove」を「Yes」にすることで、マウスを動かしたときにスクリーンセーバーを終了させることができます。

複数のディスプレイを接続している場合

 複数のディスプレイを接続している場合、スクリーンセーバーの画面が複数枚表示されることになるため、処理が非常に重くなる場合があります。このような場合、前述の「動作が遅い場合の改善策」を参考に、動作速度の改善を試してみてください。

文字のちらつきを少なくしたい/止めたい

本スクリーンセーバーは、故意に特定の行の文字をランダムに変更して「文字のちらつき」を表現せています。しかし、この文字のちらつきが気になる人は、iniファイルの「[random_numbs]」セクションにある2種類の設定情報を調整してみると良いかもしれません。 「LineChrChBase」と「LineChrChRand」のペアは、文字がちらつく行を発生させる乱数を作るためにあり、「rnd.Next(ColChangeBase) > ColChangeRand」が成り立つときに、ちらつきが発生します。規定値では、LineChrChBaseが1000に、LineChrChRandが950に設定されていますので、「rnd.Next(1000) > 950」となり、0~1000の間の任意の数字が950より大きくなった時にちらつきの行が出るという設定になっています。これを、たとえば、ColChangeRandの値を1100くらいに設定すると、この式が常に成り立たなくなるため、ちらつき行は発生しなくなります。ColChangeRandの値を小さい値にすると、今より多くのちらつき行ができることになります。 次に、「ChrChangeBase」と「ChrChangeRand」ですが、これは、ちらつき行のなかで、文字をちらつかせる確立を定義しています。ですので、ChrChangeRandの値を小さくすれば、より多くの文字でちらつきが発生し、逆に大きくすると、あまり文字がちらつかなくなります。そして、ChrChangeRandをChrChangeBaseより大きな値にすると、文字がちらつかなくなります。

画面に表示される文字に別の色を使いたい

 最初の設定では、緑色がベースとなるように設定されていますので、画面には緑色系の文字色が表示されます。しかし、これを赤や青などの他の色にしたい場合もあるかもしれません。そのようなときは、本スクリーンセーバーの設定画面(オプション設定画面)で変更できます。 設定画面の「ベースカラー」の項目を変更すると、画面に表示される色を変えることができます。たとえば、赤を100、緑を0、青を0にして、「赤を規定値にする」にチェックを入れると、画面が赤の文字で埋められます。

文字の間隔を調整したい

 指定するフォントによっては、文字と文字の間が詰まりすぎてしまったり、逆に間が空きすぎてしまったりします。そのような場合、iniファイルの「[option_datas]」セクションの「GapInsertions」の値を調整する必要があります。この値を大きくすると、文字と文字の間隔が狭くなり、逆に小さくすると、文字と文字の間隔が開きます。この値が0のときに、システムが計算した文字の大きさで文字を描画するようになります。ただし、その場合、たいていは文字と文字の間隔が大きく空きすぎることになります。しかし、この値を小さくしすぎると鏡文字を表示させるときに、文字の中心線がずれてしまい、直線的に行を描画できなくなってしまうという副作用があります。設定を変えながら、スクリーンセーバーをエクスプローラの右クリックから「Test」を選択してテスト表示させ、ベストな設定値を見つけ出してみて下さい。

スクリーンセーバーの技術的な課題

ここで、今回、Matrix風スクリーンセーバーを開発するにあたって直面した技術的な問題点や開発の課程で知り得た情報などを共有したいと思います。

Windowsでスクリーンセーバーを開発する際のヒント

 Windows用のスクリーンセーバーをC#で作成するにあたっては、下記のサイトがすごく参考になりました。スクリーンセーバーをC#で作るのに必要なすべての情報が網羅されています。非常によくまとめてあってわかりやすい内容になっていました。筆者の方は、アメリカのミシシッピー州の大学の先生みたいですね…。 https://www.harding.edu/fmccown/screensaver/screensaver.html ここに、その先生の顔写真も載ってますね…。 https://www.harding.edu/fmccown/ フランク先生に敬意を表して Thank You very much Dr.Frank McCown. Your Tutorial was just excellent. it helped me a lot to make my Matrix Screen Saver.

1文字の表示上の実サイズを得る

 これも、大事な情報でした。Windowsで文字を描画する場合、フォントの作りなどによって、実際にどれくらいの大きさで描かれるのか、予め知る手段がありません。フォントサイズを10としても、実際に10ピクセルになるとは限らないからです…。なので、決め打ちで文字サイズを決めてしまうと、実際に表示する段になっていろいろ不都合なことが起きます。これを最大限抑制するためには、一度実際に描いてみて、どれくらいの大きさになったかを予め計っておく必要があるのです。実際には、この関数を表示するすべての文字にそれぞれ適用して、表示上のサイズの一番大きいものを文字サイズとして考慮するようにしています。

/// 
/// 文字の実際の幅を計算する
/// 
/// グラフィックス
/// 文字
/// フォント
/// 文字の幅
public int CalculateDisplayStringWidth(Graphics graphics, string text, Font font)
{
    StringFormat format = new System.Drawing.StringFormat();
    RectangleF rect = new System.Drawing.RectangleF(0, 0, 1000, 1000);
    CharacterRange[] range = { new System.Drawing.CharacterRange(0, text.Length) };
    Region[] regions = new System.Drawing.Region[1];

    format.SetMeasurableCharacterRanges(range);

    regions = graphics.MeasureCharacterRanges(text, font, rect, format);
    rect = regions[0].GetBounds(graphics);

    return (int)rect.Right;
}

鏡文字

 今回一番面倒だったのは、普通のテキストを使って、鏡文字を表示させるところです。これは、結局どうやって実現したかというと、1文字分の小さなBitmapを作成し、その中に普通に文字を描いて、そのBitmapを180度反転させることで鏡文字を作りました。この時に大事なのは、1文字の正確な表示上のサイズが分かっていないと、鏡文字と普通の文字の中心線がずれてしまい、一直線の行にならなくなってしまうという事でした。なので先述の文字サイズを測る関数が重宝しました。出来てしまえば小さなコードですが、これにたどり着くまでが大変だった………汗。

/// 
/// 鏡文字を表示
/// 
/// フォント
/// 文字
/// ブラシ
/// 1文字の幅
/// 1文字の高さ
/// 鏡文字のBitmap
private Image DrawMirrorImage(Font font, string chars, SolidBrush brush, int cx, int cy)
{
    Image image01 = new Bitmap(cx, cy);
    Graphics g = Graphics.FromImage(image01);
    g.DrawString(chars, font, brush, new Point(0, 0));
    image01.RotateFlip(RotateFlipType.Rotate180FlipY);
    g.Dispose();
    return image01;
}

画面のちらつきを抑える

 Windowsでグラフィックを描画する場合、一番オーソドックスなやり方は、FormなどのPaintイベントを拾って、その中で描画関数を呼んで、描くという方法です。本スクリーンセーバーも基本的にはそのやり方を踏襲しています。画面に文字を描画し、一度画面を消去してから新しい位置に文字を描くということを繰り返すことで、文字が動いているように見えるわけです。ただ、今回のように、全画面にわたって非常にたくさんのオブジェクトの動きのあるものを描画しようとした場合、画面がちらついてしまい、かなり見にくくなってしまうという欠点があります。 これを打開するためには、ダブルバッファリングというテクニックを使います。裏で描画処理をしておいて、描画が終わったら、一気に画面に表示するという方法です。また、本スクリーンセーバーでは、画面と同じサイズのBitmap画像に文字を描画しておいて、FormのPaintのタイミングで一気に画面にその画像を張り込む事で、さらに描画の遅延をなくし、一瞬で描画を終了させることで、画面のちらつきを抑える工夫をしています。ダブルバッファリングをONにするには、Form.csで「this.DoubleBuffered = true;」とするだけです。

/// 
/// ペイントイベント
/// 
private void FormMain_Paint(object sender, PaintEventArgs e)
{
    e.Graphics.DrawImageUnscaled(this.BmpScreen, 0, 0, e.ClipRectangle.Width, e.ClipRectangle.Height);
}

複数のディスプレイ

 複数のディスプレイが接続されたPCの場合、すべてのディスプレイにスクリーンセーバーを表示させなければなりません。このとき、いちばん厄介なのが、どの画面がマウスやキーボードのイベントを受け取っているかということを把握できるようにしておかなければならない点です。というのも、例えばノートPCに外部モニターがつながっているような場合、ノートPCの画面で常にイベントを拾って、パスワード入力画面など入力を伴う画面を表示しないと、ノートPCのキーボードを押したのに、入力画面は外部モニターのほうに表示されてしまったりして、非常に違和感のあるものになってしまいます。そこで、登場するのが、「Screen.AllScreens」という情報で、これがコンピュータにつながれているすべてのモニターの情報を保持していると同時に、どの画面がプライマリ画面なのかを示すフラグ「Primary」を持っていますので、この情報を頼りに、プライマリモニタでなるべくイベントを処理するようにしています。 なるべくというのは、複数枚あるスクリーンセーバーのFormが、何らかの原因でプライマリモニタ以外のモニタ上のFormにフォーカスが移ってしまうような場合が想定できてしまうからで、このようなことが起こった場合でも、最後にフォーカスが当たった画面で正しく情報を表示させるように工夫する必要がありました。 また、今回は、キーボードコマンドで任意のメッセージなどを表示できるようにしていますので、どこかの画面でキーボード入力を検知したら、表示中のすべてのFormでそのイベントを共有し、すべての画面に同じようにメッセージを表示する仕組みを取り入れる必要がありました。 この問題は、C#のイベント機能と、非同期デリゲートを使用することで解決しています。Program.csが、すべてのディスプレイ用にFormを生成して表示を行いますが、このとき、Formからイベントを受け取れるようにしておき、イベントを受信したら、非同期デリゲートを使ってすべてのFormにそのイベントの内容を配信するようにしてあります。こうすることで、すべてのFormがキーボードコマンドを正しく処理(イベントを実際に受信した画面だけがパスワード入力画面や、内部情報表示画面を出し、それ以外のコマンドは全てのFormが同じように処理する)を行わせることができるようになっています。   

最後に

 最後になりましたが、なんでイマサラMatrixなの!?と思っている方…すいません、大意はありません…。ただなんとなくC#でなにか作ろうかなぁと思い立って、作ってみたら、最近の若い人は映画のMatrixを知らない人もいて、最初このスクリーンセーバーを見せたときに、「この文字列にはなにか意味があるんですか??」なんて人もいて、NetflixでMatrixの映画のオープニングシーンを見せたら大うけしたりして、いろいろ楽しかったので、それならばということで、Vectorに登録してみたという次第です…。 

タイトルとURLをコピーしました