[VC2005] スクリーンセーバーを作る方法
◆概要
この資料は、Microsoft(R) Visual C# 2010で スクリーンセーバーを作る方法について記述しています。
スクリーンセーバーとは、標準的なexe拡張子の代わりにscrの拡張子をもつ標準的なWidnowsの実行可能ファイルです。つまり、Formアプリケーションを作成後、拡張子をexeからscrへ変更したものです。
Windowsはスクリーンセーバーを実行するとき、特定の引数を渡すことになります。その引数とは、"/s"(スクリーンセーバーを表示する)、"/P"(画面のプロパティダイアログボックスのスクリーンセーバータブに表示される小さなモニターの中に表示されるプレビュー)、"/c"(スクリーンセーバーのオプション表示したり構成する)です。WindowsはスクリーンセーバーのMainメソッドでこれらの引数を読み取り、それに応じてスクリーンセーバーを表示したり、オプション画面を表示したりします。
スクリーンセーバーは通常、全画面で実行されます。従って、キーが押されたか、マウスが移動したかでスクリーンセーバーを終了させることが必要です。
また、スクリーンセーバーは、他のすべてのウィンドウの上で表示され、かつ、マウスカーソルは非表示にする必要があります。
▼ページトップへ
引数を読み取る
C#アプリケーションに引数を読み込むことができる唯一の場所は、自動的に作成される Main()メソッドです。
ソリューションエクスプローラーで、"Program.cs"と表示されているコードファイルがあるはずです。コードエディタで開くと、次のようになっていると思います。
using System; using System.Collections.Generic; using System.Linq; using System.Windows.Forms; namespace MyscreenSaver { static class Program { /// <summary> /// アプリケーションのメイン エントリ ポイントです。 /// </summary> [STAThread] static void Main() { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new Form1()); } } }
既定ではMainメソッドは、引数がありません。それを編集して引数"string[] args"を受け取るようにします。そうすることで、アプリケーションに渡される引数を読み込むことができるようになります
static void Main(string[] args) { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new Form1()); }
argsパラメータはアプリケーションに渡されるすべての引数を保持します。さて、それらの引数を解釈して引数を一つだけ、スクリーンセーバーに渡されるようにする必要があります。次のようにすると単純なifステートメントで容易に引数を読み取ることができます。
if (args[0].ToLower().Trim().Substring(0, 2) == "/s") //show { // スクリーンセーバーを表示 } else if (args[0].ToLower().Trim().Substring(0, 2) == "/p") //preview { // プレビュー画面を表示 } else if (args[0].ToLower().Trim().Substring(0, 2) == "/c") //configure { // スクリーンセーバーのオプション表示 }
しかし、引数なしがスクリーンセーバーに渡される可能性があります。したがって、他のif文を追加します。
if (args.Length > 0) { if (args[0].ToLower().Trim().Substring(0, 2) == "/s") //show { // スクリーンセーバーを表示 } else if (args[0].ToLower().Trim().Substring(0, 2) == "/p") //preview { // プレビュー画面を表示 } else if (args[0].ToLower().Trim().Substring(0, 2) == "/c") //configure { // スクリーンセーバーのオプション表示 } } else { // 引数なしの場合。これはユーザーがファイルを右クリックして //「構成」を選んだときに発生します。通常はオプションフォームを表示します。 }この段階で、Mainメソッドは次のようになっていると思います。
static void Main(string[] args) { if (args.Length > 0) { if (args[0].ToLower().Trim().Substring(0, 2) == "/s") //show { // スクリーンセーバーを表示 } else if (args[0].ToLower().Trim().Substring(0, 2) == "/p") //preview { // プレビュー画面を表示 } else if (args[0].ToLower().Trim().Substring(0, 2) == "/c") //configure { // スクリーンセーバーのオプション表示 } } else { // 引数なしの場合。これはユーザーがファイルを右クリックして //「構成」を選んだときに発生します。通常はオプションフォームを表示します。 } }
▼ページトップへ
二重起動を防止する
一般にプログラムの二重起動を防止するには、Mutexクラスを利用します。Mainメソッドに次のコードを追加します。
static void Main(string[] args) { //Mutexクラスの作成 System.Threading.Mutex mutex = new System.Threading.Mutex(false, Application.ProductName); //ミューテックスの所有権を要求する if (mutex.WaitOne(0, false) == false) { //すでに起動していると判断して終了 return; } // GC.KeepAlive メソッドが呼び出されるまで、ガベージ コレクション対象から除外される GC.KeepAlive(mutex); // Mutex を閉じる mutex.Close();
▼ページトップへ
スクリーンセーバーを設定する
ここで、アプリーションを実行するとコンソールアプリケーションを実行したような状態になります。MainメソッドでApplication.Runを呼び出していないからです。
さて、複数のモニタをサポートするために使用する構造を説明します。
複数のモニタをサポートするためには、すべての画面上の別のメインフォームが表示されますので、代わりに、単に、メインフォームを作り、すべての画面を埋めるために、それを伸ばし、スクリーンセーバーを作成します。
これを行うには、System.Windows.Forms.Screenクラスが便利です。このコードを見てみましょう
foreach (Screen screen in Screen.AllScreens) { MainForm screensaver = new MainForm(screen.Bounds); screensaver.Show(); }
foreachループでは、現在のコンピュータ上のすべての画面(モニタ)をループして参照しています。しかし、引数をメインフォームに渡すコンストラクタメソッドがないため、うまく動作しません。メインフォームにコンストラクタを追加します。
public MainForm(Rectangle Bounds) { InitializeComponent(); this.Bounds = Bounds; Cursor.Hide(); }
見てわかるように、それは、(境界とは何かということ)System.Drawing.Rectangleの引数を取るコンストラクタでは、コンストラクタに渡されたいずれかのフォームの境界を設定します。また、スクリーンセーバーでカーソルを隠すには、Curor.Hide()を使います。
なので、スクリーンセーバーを実行するには、次のようにメソッドを作成することができます
static void ShowScreenSaver() { foreach (Screen screen in Screen.AllScreens) { MainForm screensaver = new MainForm(screen.Bounds); screensaver.Show(); } }
これは通常、スクリーンセーバーを表示するためのメソッドなので(Program)に記述します。Programのクラスは、次のようになります。
using System; using System.Windows.Forms; namespace MyscreenSaver { static class Program { /// <summary> /// アプリケーションのメイン エントリ ポイントです。 /// </summary> [STAThread] static void Main(string[] args) { //Mutexクラスの作成 System.Threading.Mutex mutex = new System.Threading.Mutex(false, Application.ProductName); //ミューテックスの所有権を要求する if (mutex.WaitOne(0, false) == false) { //すでに起動していると判断して終了 return; } // GC.KeepAlive メソッドが呼び出されるまで、ガベージ コレクション対象から除外される GC.KeepAlive(mutex); // Mutex を閉じる mutex.Close(); if (args.Length > 0) { if (args[0].ToLower().Trim().Substring(0, 2) == "/s") // 表示 { // スクリーンセーバーを実行 Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); ShowScreenSaver(); // Application.Run(); } else if (args[0].ToLower().Trim().Substring(0, 2) == "/p") // プレビュー { // プレビュー画面を表示 } else if (args[0].ToLower().Trim().Substring(0, 2) == "/c") // 設定 { // スクリーンセーバーのオプション表示 } } else// 引数なしの場合 { // 渡される引数がない場合、これはユーザーがファイルを右クリックして //「構成」を選んだときに発生します。通常はオプションフォームを表示します。 } } // スクリーンセーバーを表示 static void ShowScreenSaver() { // コンピューター上のすべてのスクリーン(モニター)をループ foreach (Screen screen in Screen.AllScreens) { MainForm screensaver = new MainForm(screen.Bounds); screensaver.Show(); } } } }
注意:Programクラスの中に ShowScreenSaver() メソッドを記載するときは、staticクラスにする必要があります。
さて、アプリケーションが、/ sを渡された場合、または何も渡されなかった場合、実際にそのメソッドを使用するようにMain()メソッドを変更してみましょう。
if (args.Length > 0) { if (args[0].ToLower().Trim().Substring(0, 2) == "/s") //表示 { // スクリーンセーバーを表示 Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); ShowScreenSaver(); // Application.Run(); } else if (args[0].ToLower().Trim().Substring(0, 2) == "/p") //プレビュー { // プレビュー画面を表示 } else if (args[0].ToLower().Trim().Substring(0, 2) == "/c") //設定 { // スクリーンセーバーのオプション表示 } } else { // 引数なしの場合。これはユーザーがファイルを右クリックして //「構成」を選んだときに発生します。通常はオプションフォームを表示します。 // ここでは、スクリーンセーバーを表示しています。 Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); ShowScreenSaver(); // Application.Run(); }
一応、スクリーンセーバーができましたが完全ではありません。Main()メソッドに /p と /cのためのコードを作成する必要があります。さて/c(設定)引数のための設定ですが、ユーザーに設定オプションを選択できるようにしたいですか?その場合は、単に設定のためのフォームを作成し、それを表示するようにします。そのフォームでiniファイルかレジストリに設定を保存するようにします。次の例は、プロジェクトに新しいフォーム「ConfigureForm」を追加してから記述します。
else if (args[0].ToLower().Trim().Substring(0, 2) == "/c") // 設定 { // スクリーンセーバーのオプション表示 Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new ConfigureForm()); // }
一方、ユーザーが設定することができる任意のオプションを持っていないなら、次のようにメッセージを表示するようにします。
else if (args[0].ToLower().Trim().Substring(0, 2) == "/c") // 設定 { // スクリーンセーバーのオプション表示 MessageBox.Show("オプションなし" + "\nこのスクリーンセーバーには、設定できるオプションはありません。", "My Screen Saver", MessageBoxButtons.OK, MessageBoxIcon.Information); }
上記のコードでは、スクリーンセーバーは設定可能なオプションを持っていないとユーザーに示すメッセージが表示されます。そこでアプリケーションは終了します。
さて、/ p(プレビュー)の引数を処理しましょう。プレビューは、Windowsスクリーンセーバーのダイアログに表示される小さなモニターの中にスクリーンセーバーを表示したい場合の処理です。プレビューを必要としない場合は、プレビューを処理するセクションに任意のコードを必要としません。
プレビューをするようにするにはどうするのか?その方法を説明します。
▼ページトップへ
プレビューの設定
これは少しトリッキーです。これにはいくつかのAPIを使用します。Windowsが自動的にプレビューウィンドウで表示してくれないので、アプリケーションの中にコードを記述する必要があります。Windowsは、/ pコマンドを受け取ると、それはまた別の引数を渡します。 スクリーンセーバー]ダイアログボックス上のプレビューウィンドウへのハンドルを返します。プレビューウィンドウをスクリーンセーバーのメインフォームの親とするためにいくつかのAPIを使用します。これを実現するためには次のようにします。
- 最初の引数/pを見て、2番目の引数はプレビューウィンドウへのハンドルを感知します。
- Application.Run()を使用してメインフォームとしてのMainFormを使用してアプリケーションを実行します。また、プレビューウィンドウへのハンドルをメインフォームに渡します。
- メインフォームは、プレビューウィンドウ内に表示されます。
では、その実装を開始しましょう。まず、メインルーチンのセクションを更新します。
else if (args[0].ToLower().Trim().Substring(0, 2) == "/p") // プレビュー { // プレビュー画面を表示 }
次のように編集します。
else if (args[0].ToLower().Trim().Substring(0, 2) == "/p") // プレビュー { // プレビュー画面を表示 Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); //args[1] はプレビューウィンドウのハンドル Application.Run(new MainForm(new IntPtr(long.Parse(args[1])))); }
次の行に注目してください。
Application.Run(new MainForm(new IntPtr(long.Parse(args[1]))));
IntPtrの形式でプレビューウィンドウへのハンドルをMainFormに渡しています。しかし、IntPtrを受け入れることをフォームのコンストラクタを持っていないので、次のコードを使用します。
//このコンストラクタはスクリーンセーバーの設定ダイアログボックスのハンドル //プレビューモード (/p)で使用される public MainForm(IntPtr PreviewHandle) { InitializeComponent(); //このウィンドウの親ウィンドウを設定する SetParent(this.Handle, PreviewHandle); //この子ウィンドウを作成する //スクリーンセーバーの設定ダイアログボックスが閉じられると終了する SetWindowLong(this.Handle, -16, new IntPtr(GetWindowLong(this.Handle, -16) | 0x40000000)); //親ウィンドウのサイズに設定する Rectangle ParentRect; GetClientRect(PreviewHandle, out ParentRect); this.Size = ParentRect.Size; //ロケーションを設定 this.Location = new Point(0, 0); IsPreviewMode = true; }
この段階ではエラーが表示されると思います。4つのAPIを記述する必要があります。
まず、APIを使用するためusingディレクティブに次のコードを追加します。
using System.Runtime.InteropServices;
次にAPIを追加します。
#region Preview API's [DllImport("user32.dll")] static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent); [DllImport("user32.dll")] static extern int SetWindowLong(IntPtr hWnd, int nIndex, IntPtr dwNewLong); [DllImport("user32.dll", SetLastError = true)] static extern int GetWindowLong(IntPtr hWnd, int nIndex); [DllImport("user32.dll")] static extern bool GetClientRect(IntPtr hWnd, out Rectangle lpRect); #endregion
コンストラクタ内の変数は、IsPreviewModeです。アプリケーションが実行されているときに、それがプレビューモードかどうかをアプリケーションに知らせます。スクリーンセーバーを作成するときには、IsPreviewModeと呼ぶBoolearn型のグローバル変数を作成します。プレビューモードになっているときに、マウスイベントやキーイベントを無効にするためにそのような変数が必要になります。アプリケーション内にそれを終了させるキーダウンイベントコードを持っているときには、アプリケーションがプレビューモードではないことを確認するために、ifステートメントを入れてください。
なぜって?「スクリーンセーバーの設定」ダイアログボックス上のプレビューウィンドウでプレビューしている際、プレビューウィンドウの上にマウスを移動させキーを押すか、クリックするしたとき、別のプレビューを選択したときにその前のプレビューの予防策を講じない場合は、前のスクリーンセーバーのプレビューが表示されることがあるからです。
また、特定のコードは、プレビューモードで実行されないようにIsPreviewMode変数を使用することができます。そして、特定のコードは表示ユンモードでは実行されず、プレビューモードで実行されます。それは非常に便利です。
すべてをまとめる
Program.csファイルは、この時点で次のようになります。
using System; using System.Windows.Forms; namespace MyscreenSaver { static class Program { /// <summary> /// アプリケーションのメイン エントリ ポイントです。 /// </summary> [STAThread] static void Main(string[] args) { //Mutexクラスの作成 System.Threading.Mutex mutex = new System.Threading.Mutex(false, Application.ProductName); //ミューテックスの所有権を要求する if (mutex.WaitOne(0, false) == false) { //すでに起動していると判断して終了 return; } // GC.KeepAlive メソッドが呼び出されるまで、ガベージ コレクション対象から除外される GC.KeepAlive(mutex); // Mutex を閉じる mutex.Close(); if (args.Length > 0) { if (args[0].ToLower().Trim().Substring(0, 2) == "/s") // 表示 { // スクリーンセーバーを実行 Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); ShowScreenSaver(); // Application.Run(); } else if (args[0].ToLower().Trim().Substring(0, 2) == "/p") // プレビュー { // プレビュー画面を表示 Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); //args[1] はプレビューウィンドウのハンドル Application.Run(new MainForm(new IntPtr(long.Parse(args[1])))); } else if (args[0].ToLower().Trim().Substring(0, 2) == "/c") // 設定 { // スクリーンセーバーのオプション表示 MessageBox.Show("オプションなし" + "\nこのスクリーンセーバーには、設定できるオプションはありません。", "My Screen Saver", MessageBoxButtons.OK, MessageBoxIcon.Information); } else // 引数が渡されたが、それが /s, /p,/c // でなかった場合 { // 常にスクリーンセーバーを表示 Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); ShowScreenSaver(); Application.Run(); } } else// 引数なしの場合 { // 渡される引数がない場合、これはユーザーがファイルを右クリックして //「構成」を選んだときに発生します。通常はオプションフォームを表示します。 // このプロジェクトでは設定フォームを準備していないため、 // スクリーンセーバーを実行しています。 Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); ShowScreenSaver(); // Application.Run(); } } // スクリーンセーバーを表示 static void ShowScreenSaver() { // コンピューター上のすべてのスクリーン(モニター)をループ foreach (Screen screen in Screen.AllScreens) { MainForm screensaver = new MainForm(screen.Bounds); screensaver.Show(); } } } }
MainFormの中に2つの新しいコンストラクタを追加します(これはプレビューを選択しなかった場合にのみ一番上になります)。
bool IsPreviewMode = false; #region Constructors public MainForm() { InitializeComponent(); } // このコンストラクタは、フォームを全画面で表示する // ノーマルモードで使用される public MainForm(Rectangle Bounds) { InitializeComponent(); //フォームのバックカラーを黒に設定 this.BackColor = Color.Black; //コントロールボックスを表示しないように //FormBorderStyleをNoneに設定 this.FormBorderStyle = FormBorderStyle.None; this.Bounds = Bounds; //フォームを最前面に設定 TopMost = true; // マウスカーソルを非表示にする Cursor.Hide(); } // このコンストラクタは、スクリーンセーバーの選択ダイアログボックスの小窓で使用される。 // プレビューモードで使用される (/p) public MainForm(IntPtr PreviewHandle) { InitializeComponent(); // このウィンドの親ウィンドウにプレビューウィンドを設定 SetParent(this.Handle, PreviewHandle); // この子ウィンドウをスクリーンセーバーの選択ダイアログボックスが閉じられたとき SetWindowLong(this.Handle, -16, new IntPtr(GetWindowLong(this.Handle, -16) | 0x40000000)); //ウィンドウサイズを親ウィンドウのサイズに設定する Rectangle ParentRect; GetClientRect(PreviewHandle, out ParentRect); this.Size = ParentRect.Size; // ロケーションを(0, 0)に設定 this.Location = new Point(0, 0); IsPreviewMode = true; } #endregion
さて、もう一つしなければならないことがあります。キーが押されたときやマウスが動いたときにスクリーンセーバーを終了させるFimctionを実装します。次のようなります。MainFormに記述してください。
#region User Input private void MainForm_KeyDown(object sender, KeyEventArgs e) { //** プレビューを実行していないとき if (!IsPreviewMode) // プレビュー画面用に無効にする { System.Environment.Exit(0); } } private void MainForm_Click(object sender, EventArgs e) { //** レビューを実行していないとき if (!IsPreviewMode) // プレビュー画面用に無効にする { System.Environment.Exit(0); } } // XとY int.MaxValueのとOriginalLoctionを始める // カーソルがその位置にすることは不可能なので。 // この変数がまだ設定されている場合 Point OriginalLocation = new Point(int.MaxValue, int.MaxValue); private void MainForm_MouseMove(object sender, MouseEventArgs e) { //** プレビューを行っていない場合は、このif文を取り出す if (!IsPreviewMode) // プレビューのとき終了関数を無効にする { //originallocationが設定されているかどうかを確認 if (OriginalLocation.X == int.MaxValue & OriginalLocation.Y == int.MaxValue) { OriginalLocation = e.Location; } // マウスが20 pixels 以上動いたかどうかを監視 // 動いた場合はアプリケーションを終了 if (Math.Abs(e.X - OriginalLocation.X) > 20 | Math.Abs(e.Y - OriginalLocation.Y) > 20) { System.Environment.Exit(0); } } } #endregion
this.close()を使わずに、System.Environment.Exit(0)を使用していることに注意してください。
MainFormを閉じてもアプリケーションはまだ実行されているからです。それを解決するためには、System.Environment.Exit(0)を使用する必要があります。なお、System.Environment.Exit(0)の代わりにApplication.Exit() でもOKですが、System.Environment.Exit(0)がおススメです。
最後に残っているのは、アプリケションの拡張子をexeからscrにして、スクリーンセーバーとして利用するときには、Widnowsのsystem32フォルダにコピーしてください。
▼ページトップへ
コード全文
これで完成ですので、コードの全文を掲載しておきます。スクリーンセーバーのひな形として利用できます。
MainFormのClikイベントハンドラはMainForm_Clickに、KeyDownイベントハンドラはMainForm_KeyDown、MouseDownとMouseMoveはOnMouseMoveに割り当ててください。
なお、不要なusingディレクティブは削除してあります。
using System; using System.Windows.Forms; namespace MyscreenSaver { static class Program { /// <summary> /// アプリケーションのメイン エントリ ポイントです。 /// </summary> [STAThread] static void Main(string[] args) { //Mutexクラスの作成 System.Threading.Mutex mutex = new System.Threading.Mutex(false, Application.ProductName); //ミューテックスの所有権を要求する if (mutex.WaitOne(0, false) == false) { //すでに起動していると判断して終了 return; } // GC.KeepAlive メソッドが呼び出されるまで、ガベージ コレクション対象から除外される GC.KeepAlive(mutex); // Mutex を閉じる mutex.Close(); if (args.Length > 0) { if (args[0].ToLower().Trim().Substring(0, 2) == "/s") // 表示 { // スクリーンセーバーを実行 Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); ShowScreenSaver(); // Application.Run(); } else if (args[0].ToLower().Trim().Substring(0, 2) == "/p") // プレビュー { // プレビュー画面を表示 Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); //args[1] はプレビューウィンドウのハンドル Application.Run(new MainForm(new IntPtr(long.Parse(args[1])))); } else if (args[0].ToLower().Trim().Substring(0, 2) == "/c") // 設定 { // スクリーンセーバーのオプション表示 MessageBox.Show("オプションなし" + "\nこのスクリーンセーバーには、設定できるオプションはありません。", "My Screen Saver", MessageBoxButtons.OK, MessageBoxIcon.Information); } else // 引数が渡されたが、それが /s, /p,/c // でなかった場合 { // 常にスクリーンセーバーを表示 Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); ShowScreenSaver(); Application.Run(); } } else// 引数なしの場合 { // 渡される引数がない場合、これはユーザーがファイルを右クリックして //「構成」を選んだときに発生します。通常はオプションフォームを表示します。 // このプロジェクトでは設定フォームを準備していないため、 // スクリーンセーバーを実行しています。 Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); ShowScreenSaver(); // Application.Run(); } } // スクリーンセーバーを表示 static void ShowScreenSaver() { // コンピューター上のすべてのスクリーン(モニター)をループ foreach (Screen screen in Screen.AllScreens) { MainForm screensaver = new MainForm(screen.Bounds); screensaver.Show(); } } } }MainForm.cs
using System; using System.Drawing; using System.Windows.Forms; using System.Runtime.InteropServices; namespace MyscreenSaver { public partial class MainForm : Form { #region Preview API's [DllImport("user32.dll")] static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent); [DllImport("user32.dll")] static extern int SetWindowLong(IntPtr hWnd, int nIndex, IntPtr dwNewLong); [DllImport("user32.dll", SetLastError = true)] static extern int GetWindowLong(IntPtr hWnd, int nIndex); [DllImport("user32.dll")] static extern bool GetClientRect(IntPtr hWnd, out Rectangle lpRect); #endregion bool IsPreviewMode = false; #region Constructors public MainForm() { InitializeComponent(); } // このコンストラクタは、フォームを全画面で表示する // ノーマルモードで使用される public MainForm(Rectangle Bounds) { InitializeComponent(); //フォームのバックカラーを黒に設定 this.BackColor = Color.Black; //コントロールボックスを表示しないように //FormBorderStyleをNoneに設定 this.FormBorderStyle = FormBorderStyle.None; this.Bounds = Bounds; //フォームを最前面に設定 TopMost = true; // マウスカーソルを非表示にする Cursor.Hide(); } // このコンストラクタは、スクリーンセーバーの選択ダイアログボックスの小窓で使用される。 // プレビューモードで使用される (/p) public MainForm(IntPtr PreviewHandle) { InitializeComponent(); // このウィンドの親ウィンドウにプレビューウィンドを設定 SetParent(this.Handle, PreviewHandle); // この子ウィンドウをスクリーンセーバーの選択ダイアログボックスが閉じられたとき SetWindowLong(this.Handle, -16, new IntPtr(GetWindowLong(this.Handle, -16) | 0x40000000)); //ウィンドウサイズを親ウィンドウのサイズに設定する Rectangle ParentRect; GetClientRect(PreviewHandle, out ParentRect); this.Size = ParentRect.Size; // ロケーションを(0, 0)に設定 this.Location = new Point(0, 0); IsPreviewMode = true; } #endregion #region User Input private void MainForm_KeyDown(object sender, KeyEventArgs e) { System.Environment.Exit(0); } private void MainForm_Click(object sender, EventArgs e) { //** レビューを実行していないとき if (!IsPreviewMode) // プレビュー画面用に無効にする { System.Environment.Exit(0); } } // XとY int.MaxValueのとOriginalLoctionを始める // カーソルがその位置にすることは不可能なので。 // この変数がまだ設定されている場合 Point OriginalLocation = new Point(int.MaxValue, int.MaxValue); private void OnMouseMove(object sender, MouseEventArgs e) { //** プレビューを行っていない場合は、このif文を取り出す if (!IsPreviewMode) // プレビューのとき終了関数を無効にする { //originallocationが設定されているかどうかを確認 if (OriginalLocation.X == int.MaxValue & OriginalLocation.Y == int.MaxValue) { OriginalLocation = e.Location; } // マウスが20 pixels 以上動いたかどうかを監視 // 動いた場合はアプリケーションを終了 if (Math.Abs(e.X - OriginalLocation.X) > 20 | Math.Abs(e.Y - OriginalLocation.Y) > 20) { System.Environment.Exit(0); } } } #endregion } }動作確認:WindowsXp Professional/Windows 7 64bit
必要なもの:.NET Framework 3.5
◆ダウンロード
ダウンロードmyscreensaver.zip(48KB)
画面のプロパティでは次のように表示されます。
ここでは、プレビュー画面がきちんと表示されることを示すために、Formのプロパティをあえて設定していません。
実際にスクリーンセーバーを作成するときには、最初にFormのプロパティでBackColorを黒、FormBorderStyleをNoneに設定します。
その場合は、public MainForm(Rectangle Bounds)にある次の行を削除します。
//フォームのバックカラーを黒に設定 this.BackColor = Color.Black; //コントロールボックスを表示しないように //FormBorderStyleをNoneに設定 this.FormBorderStyle = FormBorderStyle.None;
◆スクリーンセーバーのテストを行う方法
- [プロジェクト]メニューの[MyScreenSaverのプロパティ]をクリックします。
- [MyScreenSaverのプロパティ]ダイアログボックスで、[デバッグ]タブをクリックし、開始オプション-コマンドライン引数(N)に/sと入力し、F5キーを押します。
▼ページトップへ