スクリーンセーバーを起動しないようにするには
では起動しているあいだスクリーンセーバーを起動しないようにしました。今回は特定のアプリケーションが起動しているときのみスクリーンセーバーの起動を抑止します。
フォーム上に「Target」と書かれたイメージがあります。これを他のアプリケーションのウィンドウにドラッグするとテキストボックスにプロセス名が表示されます。追加をクリックするとそのアプリが起動しているときはスクリーンセーバーが起動しなくなります。逆に「除去」をクリックすると登録を解除することもできます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
public partial class Form1 : Form { Timer Timer1 = new Timer(); // 「Target」と書かれたビットマップイメージ Bitmap TargetBitmap = null; // パネル上に表示されるビットマップイメージ Bitmap PanelImage = null; // このリストに格納されているプロセス名と同じプロセスが実行されている場合、スクリーンセーバー起動を抑止する List<string> ProcessNames = new List<string>(); public Form1() { InitializeComponent(); Timer1.Interval = 30 * 1000; Timer1.Tick += Timer1_Tick; Timer1.Start(); // 「Target」のビットマップイメージ Bitmap bitmap = Properties.Resources.target; bitmap.MakeTransparent(Color.White); TargetBitmap = bitmap; PanelImage = TargetBitmap; // イベントハンドラ panel1.Paint += Panel1_Paint; panel1.MouseDown += Panel1_MouseDown; panel1.MouseUp += Panel1_MouseUp; listBox1.SelectedIndexChanged += ListBox1_SelectedIndexChanged; } } |
マウスがクリックされたらカーソルを変更します。カーソルはTargetBitmapからつくります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
public partial class Form1 : Form { private void Panel1_MouseDown(object sender, MouseEventArgs e) { PanelImage = null; panel1.Invalidate(); panel1.Capture = true; Cursor cur = BitmapToCursor.CreateCursor(TargetBitmap, 64, 64); Cursor.Current = cur; } private void Panel1_Paint(object sender, PaintEventArgs e) { if(PanelImage != null) e.Graphics.DrawImage(PanelImage, new Point(0, 0)); } } |
ビットマップイメージからカーソルをつくるクラスです。CreateCursorメソッドでカーソルを生成します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
public class BitmapToCursor { public static Cursor CreateCursor(Bitmap bmp, int xHotSpot, int yHotSpot) { IntPtr ptr = bmp.GetHicon(); IconInfo tmp = new IconInfo(); GetIconInfo(ptr, ref tmp); tmp.xHotspot = xHotSpot; tmp.yHotspot = yHotSpot; tmp.fIcon = false; ptr = CreateIconIndirect(ref tmp); return new Cursor(ptr); } [DllImport("user32.dll")] [return: MarshalAs(UnmanagedType.Bool)] static extern bool GetIconInfo(IntPtr hIcon, ref IconInfo pIconInfo); [DllImport("user32.dll")] static extern IntPtr CreateIconIndirect(ref IconInfo icon); struct IconInfo { public bool fIcon; // アイコンの場合 true, カーソルの場合 false public int xHotspot; // カーソルのホットスポットの X 座標 public int yHotspot; // カーソルのホットスポットの Y 座標 public IntPtr hbmMask; // 透過用のビットマップハンドル public IntPtr hbmColor; // 画像用のビットマップハンドル } } |
マウスが離されたらProcessNameFromPointクラスを利用して、マウスポインタが乗っているウィンドウのプロセス名を取得します。取得したプロセス名をテキストボックスに表示します。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
public partial class Form1 : Form { private void Panel1_MouseUp(object sender, MouseEventArgs e) { Cursor.Current = Cursors.Default; PanelImage = TargetBitmap; panel1.Invalidate(); string processName = ProcessNameFromPoint.GetProcessNameFromPoint(MousePosition); textBox1.Text = processName; } } |
ProcessNameFromPointクラスは以下のとおりです。マウスポインタの座標からウィンドウハンドルを取得します。そしてウィンドウハンドルからプロセスIDを取得してプロセスIDからプロセス名を取得します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
public class ProcessNameFromPoint { public static string GetProcessNameFromPoint(Point pt) { IntPtr hWnd = GetRootWindowHandle(pt); int processId = GetProcessID(hWnd); return GetProcessName(processId); } [StructLayout(LayoutKind.Sequential)] struct POINT { public int x; public int y; } [DllImport("user32.dll", SetLastError = true)] static extern IntPtr WindowFromPoint(POINT point); [DllImport("user32.dll", SetLastError = true)] static extern IntPtr GetAncestor(IntPtr hWnd, uint gaFlags); const uint GA_ROOT = 2; static IntPtr GetRootWindowHandle(Point mousePos) { POINT pt = new POINT(); pt.x = mousePos.X; pt.y = mousePos.Y; IntPtr hWnd = WindowFromPoint(pt); return GetAncestor(hWnd, GA_ROOT); } [DllImport("user32")] private static extern int GetWindowThreadProcessId(IntPtr hWnd, out int lpdwProcessId); static int GetProcessID(IntPtr hWnd) { int processId; GetWindowThreadProcessId(hWnd, out processId); return processId; } static string GetProcessName(int processId) { System.Diagnostics.Process p = System.Diagnostics.Process.GetProcessById(processId); return p.ProcessName.ToString(); } } |
追加ボタンが押されたらProcessNames(プロセス名と同じプロセスが実行されている場合、スクリーンセーバー起動を抑止する)にプロセス名を格納します(すでに同じプロセス名が格納されている場合はなにもしない)。そしてリストボックスにもプロセス名一覧を表示させます。
さらにこのとき現在実行されているプロセス名をすべて調べて新しく追加されたプロセス名のものが実行されているのであれば、スクリーンセーバーの起動を抑止している旨を表示させます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
public partial class Form1 : Form { private void buttonAdd_Click(object sender, EventArgs e) { string str1 = textBox1.Text; if(str1 == "") return; if(!ProcessNames.Any(x1 => x1 == str1)) { ProcessNames.Add(str1); ProcessNames = ProcessNames.OrderBy(x => x).ToList(); listBox1.Items.Clear(); foreach(string str2 in ProcessNames) { listBox1.Items.Add(str2); } int index = listBox1.Items.IndexOf(str1); listBox1.SelectedIndex = index; } if(GetProcessNames().Any(x2 => x2 == str1)) ShowState(true); } } |
除去がクリックされたらテキストボックスに表示されているプロセス名をProcessNamesから削除します。そしてリストボックスのアイテムからも削除します。
このとき現在実行されているプロセス名をすべて調べてリストボックス内に存在するプロセス名のものが実行されていないのであれば、スクリーンセーバーの起動が抑止されていない旨を表示させます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
public partial class Form1 : Form { private void buttonRemove_Click(object sender, EventArgs e) { string str = textBox1.Text; if(str == "") return; ProcessNames.Remove(str); listBox1.Items.Remove(str); if(!GetProcessNames().Intersect(ProcessNames).Any()) ShowState(false); } List<string> GetProcessNames() { List<string> vs = new List<string>(); System.Diagnostics.Process[] ps = System.Diagnostics.Process.GetProcesses(); foreach(System.Diagnostics.Process p in ps) { try { vs.Add(p.ProcessName); } catch(Exception ex) { Console.WriteLine("エラー: {0}", ex.Message); } } return vs; } void ShowState(bool isStop) { if(isStop) { label1.ForeColor = Color.Red; label1.Text = "スクリーンセーバーの起動は抑止されています"; } else { label1.ForeColor = Color.Black; label1.Text = "スクリーンセーバーの起動は抑止されていません"; } } } |
タイマーをセットして1分以内に1回 Tickイベントを発生させます。このとき実行されているプロセスの名前のなかにリストボックス内に存在するプロセス名のものがあれば、スクリーンセーバーの起動を抑止します。
またスクリーンセーバーの起動を抑止されているとき、されていない場合はその旨を表示します(TickイベントとTickイベントのあいだにリストボックス内に存在する名前のプロセスが終了されることがある。その場合、抑止されていない旨が表示されるまでタイムラグが存在するのだが、まあいいんじゃないかな?)。
自作メソッド PreventScreenSaverFromStartingの内容は
を参照してください。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
public partial class Form1 : Form { private void Timer1_Tick(object sender, EventArgs e) { // 必要ならスクリーンセーバーの起動を抑止する if(GetProcessNames().Intersect(ProcessNames).Any()) { PreventScreenSaverFromStarting(); ShowState(true); } else ShowState(false); } } |
リストボックスで選択されているアイテムが変更されると、選択されているアイテムがテキストボックスに表示されます。このとき「除去」をクリックすると、選択されていたプロセス名をスクリーンセーバーの起動を抑止するリストから除去することができます。
1 2 3 4 5 6 7 8 9 10 11 |
public partial class Form1 : Form { private void ListBox1_SelectedIndexChanged(object sender, EventArgs e) { int index = listBox1.SelectedIndex; if(index != -1) { textBox1.Text = ProcessNames[index]; } } } |