0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

C#で画面にドットサイトをつける

Last updated at Posted at 2023-05-07

目的

画面中央に点を表示させます。
image.png
こんな感じです。

必要なこと

  • 最前面指定
  • フォーム非表示
  • 画像表示
  • 画面中央配置

以上の4つです。

最前面指定

image.png
TOPMOST を TRUE にする

フォーム非表示

private void Form1_Shown(object sender, EventArgs e)
{
    Visible = false;
}

このイベントををformクラスに入れる

フォームを非表示で子要素を表示することはできそうにない・・・

フォームを透明化+上のバーをなくす

image.png

FormBorderSytleをNoneにすることで、上のバーを無くし
image.png
こんな感じにする

this.TransparencyKey = this.BackColor;

でフォームを透明化する。

画像表示

PictureBoxを使用

ディスプレイのサイズを取得

画像がディスプレイの中心に来るようフォームの位置を調整する。

完了
完成プログラム参照

非アクティブ時にキー入力で終了させる

WindowsAPIの機能を使う

完成したプログラム

image.png

フォルダ内に表示する画像を入れてください。
画像の名前に合わせてプログラムを修正してください。
デフォルトでpキーでソフト終了にしてます。

using System.Diagnostics;
using System.Runtime.InteropServices;

namespace DotSight
{
    public partial class Form1 : Form
    { 

        //キーボードフッククラスのインスタンス生成
        KeyboardHook _hook = new KeyboardHook();
    
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            //ディスプレイの高さ
            int h = System.Windows.Forms.Screen.PrimaryScreen.Bounds.Height;
            //ディスプレイの幅
            int w = System.Windows.Forms.Screen.PrimaryScreen.Bounds.Width;

            //結果表示
            //label1.Text = "ディスプレイの高さ:"+ h.ToString() +"ピクセル";
            //label2.Text = "ディスプレイの幅:" + w.ToString() + "ピクセル";

            Image image = Image.FromFile(@"C:/Users/yellow_site.png");

            pictureBox1.Image = image;

            //画像のサイズを取得する
            int h_png = image.Height;
            int w_png = image.Width;

            //フォームの場所を調整する
            this.Location = new Point((int)((w-w_png)/2),(int)((h-h_png)/2));

            //キーボードが押された時のイベントハンドラを登録 
            _hook.OnKeyDown += ( s , ea) =>
            {
                //イベント発生時の処理
                //Console.WriteLine(ea.Key);

                ea.RetCode = 0; //他のプログラムにキーを転送したくない場合は1を代入,それ以外は0

                
                if (ea.Key.ToString() == "P")
                {
                    //アプリ終了
                    _hook.UnHook();
                    this.Close();
                }

            };
            //キーボードフックの開始
            _hook.Hook();


        }

        private void label1_Click(object sender, EventArgs e)
        {

        }

        private void Form1_Shown(object sender, EventArgs e)
        {
            //this.Visible = false;
            //pictureBox1.Visible = true;
            this.TransparencyKey = this.BackColor;
        }

        private void pictureBox1_Click(object sender, EventArgs e)
        {

        }
    }

    public class KeyboardHook
    {
        private const int WH_KEYBOARD_LL = 0x0D;
        private const int WM_KEYBOARD_DOWN = 0x100;
        private const int WM_KEYBOARD_UP = 0x101;
        private const int WM_SYSKEY_DOWN = 0x104;
        private const int WM_SYSKEY_UP = 0x105;

        //イベントハンドラの定義
        public event EventHandler<KeyboardHookEventArgs> OnKeyDown = delegate { };
        public event EventHandler<KeyboardHookEventArgs> OnKeyUp = delegate { };

        //コールバック関数のdelegate 定義
        private delegate IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam);

        //キーボードフックに必要なDLLのインポート
        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);

        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern IntPtr SetWindowsHookEx(int idHook, HookCallback lpfn, IntPtr hMod, uint dwThreadId);

        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        private static extern bool UnhookWindowsHookEx(IntPtr hhk);

        [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern IntPtr GetModuleHandle(string lpModuleName);

        //フックプロシージャのハンドル
        private static IntPtr _hookHandle = IntPtr.Zero;

        //フック時のコールバック関数
        private static HookCallback _callback;

        /// <summary>
        /// キーボードHook の開始
        /// </summary>
        /// <param name="callback"></param>
        public void Hook()
        {
            _callback = CallbackProc;
            using (Process process = Process.GetCurrentProcess())
            {
                using (ProcessModule module = process.MainModule)
                {
                    _hookHandle = SetWindowsHookEx(
                       WH_KEYBOARD_LL,                                          //フックするイベントの種類
                       _callback, //フック時のコールバック関数
                       GetModuleHandle(module.ModuleName),                      //インスタンスハンドル
                       0                                                        //スレッドID(0:全てのスレッドでフック)
                   );
                }
            }
        }
        /// <summary>
        /// コールバック関数
        /// </summary>
        /// <param name="nCode"></param>
        /// <param name="wParam"></param>
        /// <param name="lParam"></param>
        /// <returns></returns>
        private IntPtr CallbackProc(int nCode, IntPtr wParam, IntPtr lParam)
        {
            var args = new KeyboardHookEventArgs();
            Keys key = (Keys)(short)Marshal.ReadInt32(lParam);
            args.Key = key;

            if ((int)wParam == WM_KEYBOARD_DOWN || (int)wParam == WM_SYSKEY_DOWN) OnKeyDown(this, args);
            if ((int)wParam == WM_KEYBOARD_UP || (int)wParam == WM_SYSKEY_UP) OnKeyUp(this, args);

            return (args.RetCode == 0) ? CallNextHookEx(_hookHandle, nCode, wParam, lParam) : (IntPtr)1;
        }
        /// <summary>
        /// キーボードHockの終了
        /// </summary>
        public void UnHook()
        {
            UnhookWindowsHookEx(_hookHandle);
            _hookHandle = IntPtr.Zero;
        }
    }

    /// <summary>
    /// キーボードフックのイベント引数
    /// </summary>
    public class KeyboardHookEventArgs
    {
        public Keys Key { get; set; }
        public int RetCode { get; set; } = 0;
    }
}

フォームデザイン

namespace DotSight
{
    partial class Form1
    {
        /// <summary>
        ///  Required designer variable.
        /// </summary>
        private System.ComponentModel.IContainer components = null;

        /// <summary>
        ///  Clean up any resources being used.
        /// </summary>
        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        #region Windows Form Designer generated code

        /// <summary>
        ///  Required method for Designer support - do not modify
        ///  the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
            this.pictureBox1 = new System.Windows.Forms.PictureBox();
            ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit();
            this.SuspendLayout();
            // 
            // pictureBox1
            // 
            this.pictureBox1.Location = new System.Drawing.Point(0, 0);
            this.pictureBox1.Name = "pictureBox1";
            this.pictureBox1.Size = new System.Drawing.Size(130, 113);
            this.pictureBox1.TabIndex = 2;
            this.pictureBox1.TabStop = false;
            this.pictureBox1.Click += new System.EventHandler(this.pictureBox1_Click);
            // 
            // Form1
            // 
            this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.ClientSize = new System.Drawing.Size(214, 250);
            this.Controls.Add(this.pictureBox1);
            this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
            this.Name = "Form1";
            this.Text = "Form1";
            this.TopMost = true;
            this.Load += new System.EventHandler(this.Form1_Load);
            this.Shown += new System.EventHandler(this.Form1_Shown);
            ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit();
            this.ResumeLayout(false);

        }

        #endregion
        private PictureBox pictureBox1;
    }
}

追記

キー入力イベントクラス

作成者様ありがとうございます。

すぐ使えるように、自分用にメモを残します。

form_load内部
//キーボードが押された時のイベントハンドラを登録 
_hook.OnKeyDown += (s, ea) =>
{
    //イベント発生時の処理
    //Console.WriteLine(ea.Key);

    ea.RetCode = 0; //他のプログラムにキーを転送したくない場合は1を代入,それ以外は0

    textBox1.Text = ea.Key.ToString();

    if (ea.Key.ToString() == "P")
    {
        //アプリ終了
        _hook.UnHook();
        this.Close();
    }

    if (ea.Key.ToString() == "Right")
    {
        screen_shot();
    }

};
//キーボードフックの開始
_hook.Hook();

クラス、namespaceに追加
public class KeyboardHook
    {
        private const int WH_KEYBOARD_LL = 0x0D;
        private const int WM_KEYBOARD_DOWN = 0x100;
        private const int WM_KEYBOARD_UP = 0x101;
        private const int WM_SYSKEY_DOWN = 0x104;
        private const int WM_SYSKEY_UP = 0x105;

        //イベントハンドラの定義
        public event EventHandler<KeyboardHookEventArgs> OnKeyDown = delegate { };
        public event EventHandler<KeyboardHookEventArgs> OnKeyUp = delegate { };

        //コールバック関数のdelegate 定義
        private delegate IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam);

        //キーボードフックに必要なDLLのインポート
        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);

        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern IntPtr SetWindowsHookEx(int idHook, HookCallback lpfn, IntPtr hMod, uint dwThreadId);

        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        private static extern bool UnhookWindowsHookEx(IntPtr hhk);

        [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern IntPtr GetModuleHandle(string lpModuleName);

        //フックプロシージャのハンドル
        private static IntPtr _hookHandle = IntPtr.Zero;

        //フック時のコールバック関数
        private static HookCallback _callback;

        /// <summary>
        /// キーボードHook の開始
        /// </summary>
        /// <param name="callback"></param>
        public void Hook()
        {
            _callback = CallbackProc;
            using (Process process = Process.GetCurrentProcess())
            {
                using (ProcessModule module = process.MainModule)
                {
                    _hookHandle = SetWindowsHookEx(
                       WH_KEYBOARD_LL,                                          //フックするイベントの種類
                       _callback, //フック時のコールバック関数
                       GetModuleHandle(module.ModuleName),                      //インスタンスハンドル
                       0                                                        //スレッドID(0:全てのスレッドでフック)
                   );
                }
            }
        }
        /// <summary>
        /// コールバック関数
        /// </summary>
        /// <param name="nCode"></param>
        /// <param name="wParam"></param>
        /// <param name="lParam"></param>
        /// <returns></returns>
        private IntPtr CallbackProc(int nCode, IntPtr wParam, IntPtr lParam)
        {
            var args = new KeyboardHookEventArgs();
            Keys key = (Keys)(short)Marshal.ReadInt32(lParam);
            args.Key = key;

            if ((int)wParam == WM_KEYBOARD_DOWN || (int)wParam == WM_SYSKEY_DOWN) OnKeyDown(this, args);
            if ((int)wParam == WM_KEYBOARD_UP || (int)wParam == WM_SYSKEY_UP) OnKeyUp(this, args);

            return (args.RetCode == 0) ? CallNextHookEx(_hookHandle, nCode, wParam, lParam) : (IntPtr)1;
        }
        /// <summary>
        /// キーボードHockの終了
        /// </summary>
        public void UnHook()
        {
            UnhookWindowsHookEx(_hookHandle);
            _hookHandle = IntPtr.Zero;
        }
    }

    /// <summary>
    /// キーボードフックのイベント引数
    /// </summary>
    public class KeyboardHookEventArgs
    {
        public Keys Key { get; set; }
        public int RetCode { get; set; } = 0;
    }
0
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?