動機
前回、マウスロガーを作成しましたが、マウス位置情報のダミーを Windows 側に送ることで、スクリーンセーバーを無効化できることがわかりました。
(マウスのダミー位置情報を提供するだけで、実際のマウス操作には影響ありませんでした。)
そこで、今回はスクリーンセーバを C# アプリで無効化するアプリのプロトタイプを作成しました。
なお、本アプリは WindowsFormsApp で作成しました。
過去の記事(WpfApp)
参考 1:ノートパソコンの画面の明るさをボタン一つで変更する【C#】
参考 2:ノートパソコンの画面の音量をボタン一つで変更する【C#】
参考 3:ノートパソコンの画面のバッテリー状況をボタン一つで取得する【C#】
参考 4:ノートパソコンの画面の通信料状況をボタン一つで取得する【C#】
参考 5:ノートパソコンで現在使用中のアプリをボタン一つで把握する【C#】
参考 6: ノートパソコンで現在使用中のオーディオ機器情報をボタン一つで取得する【C#】
参考 7:パソコンのユーザー情報取得やアプリ起動・終了、ディスプレイ画面の切替などを、ボタンを作って動かす【C#】
過去の記事(WindowsFormsApp)
参考 1:パソコンに接続しているディスプレイ情報をボタン一つで取得する【C#】
参考 2:パソコンに入力されたキーを表示する【C#】
参考 3:パソコンに入力されたマウスの位置を表示する【C#】
イメージ画像
今回の UI は非常にシンプルで、無くても良いぐらいでした。
ただ、UI をなくしてしまうとアプリが起動中か個人的に分からなくなってしまうので、非常に小さい UI を作成しました。
なお、このアプリが起動中は、特にマウス操作・キーボード動作をしなくてもスクリーンセーバーは起動しなくなります。
ソース
Form1.Designer.cs
namespace WindowsFormsApp1
{
partial class Form1
{
/// <summary>
/// 必要なデザイナー変数です。
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// 使用中のリソースをすべてクリーンアップします。
/// </summary>
/// <param name="disposing">マネージド リソースを破棄する場合は true を指定し、その他の場合は false を指定します。</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows フォーム デザイナーで生成されたコード
/// <summary>
/// デザイナー サポートに必要なメソッドです。このメソッドの内容を
/// コード エディターで変更しないでください。
/// </summary>
private void InitializeComponent()
{
this.label1 = new System.Windows.Forms.Label();
this.SuspendLayout();
//
// label1
//
this.label1.AutoSize = true;
this.label1.Font = new System.Drawing.Font("MS UI Gothic", 18F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(128)));
this.label1.Location = new System.Drawing.Point(0, 3);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(280, 30);
this.label1.TabIndex = 0;
this.label1.Text = "スクリーンセーバー起動なし";
this.label1.Click += new System.EventHandler(this.label1_Click);
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(232, 33);
this.Controls.Add(this.label1);
this.Name = "Form1";
this.Text = "Activator";
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.Label label1;
}
}
Form1.cs
using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace WindowsFormsApp1
{
public partial class Form1 : Form
{
Timer Timer = new Timer();
public Form1()
{
InitializeComponent();
Timer.Interval = 30 * 1000;
Timer.Tick += Timer_Tick;
Timer.Start();
}
private void Timer_Tick(object sender, EventArgs e)
{
PreventScreenSaverFromStarting();
}
[StructLayout(LayoutKind.Sequential)]
struct MOUSEINPUT
{
public int dx;
public int dy;
public uint mouseData;
public uint dwFlags;
public uint time;
public IntPtr dwExtraInfo;
}
[StructLayout(LayoutKind.Sequential)]
struct KEYBDINPUT
{
ushort wVk;
ushort wScan;
uint dwFlags;
uint time;
IntPtr dwExtraInfo;
}
[StructLayout(LayoutKind.Sequential)]
struct HARDWAREINPUT
{
uint uMsg;
ushort wParamL;
ushort wParamH;
}
[StructLayout(LayoutKind.Explicit)]
struct INPUT
{
[FieldOffset(0)]
public int type;
[FieldOffset(4)] //*
public MOUSEINPUT mi;
[FieldOffset(4)] //*
public KEYBDINPUT ki;
[FieldOffset(4)] //*
public HARDWAREINPUT hi;
}
const int INPUT_MOUSE = 0;
[DllImport("user32.dll", SetLastError = true)]
static extern uint SendInput(uint nInputs, ref INPUT pInputs, int cbSize);
void PreventScreenSaverFromStarting()
{
INPUT input = new INPUT();
input.type = INPUT_MOUSE;
input.mi = new MOUSEINPUT();
input.mi.dwExtraInfo = IntPtr.Zero;
input.mi.dx = 0;
input.mi.dy = 0;
input.mi.time = 0;
input.mi.mouseData = 0;
input.mi.dwFlags = 0x0001; // MOVE (RELATIVE)
int cbSize = Marshal.SizeOf(typeof(INPUT));
uint r = SendInput(1, ref input, cbSize);
}
private void label1_Click(object sender, EventArgs e)
{
}
}
}
おわりに
個人的にデスクトップアプリ側で、スクリーンセーバーの制御(主にスクリーンセーバーを表示させなくすること)ができればいいなと思っていたのですが、このようにマウスのダミー位置情報を与えれ上げればスクリーンセーバを表示させなくすることができると知れたので、大きな収穫でした。