質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

Q&A

0回答

656閲覧

グローバルフックコーディングについて

mamonPro

総合スコア38

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

0グッド

1クリップ

投稿2018/07/30 07:20

編集2022/01/12 10:55

イメージ説明
やりたいこと:
特定のキー入力を認識した際、あらかじめ指定しておいた個所(上記画像のstartX,startYもしくはEndX,EndY)をクリックするツールを作りたいと思いC#で作成しています。
リアルタイムにポインタの座標を取得し、その場所をTextboxに入れて
対象となるキーが入力された際にクリックイベントを実施するという工程は
普通にできたのですが、
別のアプリケーションのボタンをクリックするイベントの為、
アプリにフォーカスしなくなると、イベントも起きなくなります。

そこで、低レベルの【グローバルフック】を用いると
フォーカスに依存せず、実装が出来ることがおよそわかり
色々調べてパジャマdeブロッガー(myugaruのヲタ日記)さんの記事を見ながら
WindowsFormビューを作成し
Program.csにほぼコピペし、実行したところ
出力には正常に結果が反映されたところまではたどり着けました。
しかしグローバルフック自体難易度が高く、参照先のコードの意味も理解できておりません。
Form1.csでコーディングをする画面で
グローバルフックを用いてコーディングをしたいのですが
その方法がわかりません。

解決策や、細かく解説されている情報源などありましたら教えてください。

具体的には
上記画像でエスケープキーのキー入力が認識された際にstartX,startYの座標を
クリックしたいと考えています。

C#

1Program.cs 2 3using System; 4using System.Windows.Forms; 5using System.Runtime.InteropServices; 6using System.ComponentModel; 7using System.Runtime.InteropServices; 8 9namespace garu.Testhook 10{ 11 static class TestHook 12 { 13 [STAThread] 14 static void Main(string[] args) 15 { 16 Application.Run(new Form1()); 17 } 18 } 19 20 class Form1 : Form 21 { 22 // 23 // DELEGATE for Hook 24 // 25 public delegate int HookHandler( 26 int code, WM message, IntPtr state); 27 28 // 29 // SetWindowsHookEx 30 // 31 [DllImport("user32.dll", SetLastError = true)] 32 public static extern IntPtr SetWindowsHookEx( 33 WH hookType, HookHandler hookDelegate, IntPtr module, uint threadId); 34 35 // 36 // HookType 37 // 38 public enum WH 39 { 40 KEYBOARD_LL = 13, 41 MOUSE_LL = 14, 42 } 43 44 // 45 // UnhookWindowsHookEx 46 // 47 [DllImport("user32.dll", SetLastError = true)] 48 public static extern bool UnhookWindowsHookEx(IntPtr hook); 49 50 // 51 // CallNextHookEx 52 // 53 [DllImport("user32.dll")] 54 public static extern int CallNextHookEx( 55 IntPtr hook, int code, WM message, IntPtr state); 56 57 [DllImport("USER32.dll", CallingConvention = CallingConvention.StdCall)] 58 static extern void SetCursorPos(int X, int Y); 59 60 [DllImport("USER32.dll", CallingConvention = CallingConvention.StdCall)] 61 static extern void mouse_event(int dwFlags, int dx, int dy, int cButtons, int dwExtraInfo); 62 63 private const int MOUSEEVENTF_LEFTDOWN = 0x2; 64 private const int MOUSEEVENTF_LEFTUP = 0x4; 65 66 // 67 // Win32 Message 68 // 69 public enum WM 70 { 71 KEYDOWN = 0x0100, 72 KEYUP = 0x0101, 73 SYSKEYDOWN = 0x0104, 74 SYSKEYUP = 0x0105, 75 MOUSEMOVE = 0x0200, 76 LBUTTONDOWN = 0x0201, 77 LBUTTONUP = 0x0202, 78 LBUTTONDBLCLK = 0x0203, 79 RBUTTONDOWN = 0x0204, 80 RBUTTONUP = 0x0205, 81 RBUTTONDBLCLK = 0x0206, 82 MBUTTONDOWN = 0x0207, 83 MBUTTONUP = 0x0208, 84 MBUTTONDBLCLK = 0x0209, 85 MOUSEWHEEL = 0x020A, 86 XBUTTONDOWN = 0x020B, 87 XBUTTONUP = 0x020C, 88 XBUTTONDBLCLK = 0x020D, 89 MOUSEHWHEEL = 0x020E, 90 } 91 92 // 93 // (private) Field 94 // 95 HookHandler hookDelegate; 96 IntPtr hook; 97 98 public Form1() 99 { 100 WH hookType = WH.KEYBOARD_LL; 101 hookDelegate = new HookHandler(OnHook); 102 IntPtr hMod = Marshal.GetHINSTANCE( 103 System.Reflection.Assembly. 104 GetExecutingAssembly().GetModules()[0]); 105 hook = SetWindowsHookEx(hookType, hookDelegate, hMod, 0); 106 if (hook == IntPtr.Zero) 107 { 108 int errorCode = Marshal.GetLastWin32Error(); 109 throw new Win32Exception(errorCode); 110 } 111 } 112 113 protected override void OnClosing(CancelEventArgs e) 114 { 115 base.OnClosing(e); 116 if (hook != IntPtr.Zero) 117 { 118 UnhookWindowsHookEx(hook); 119 } 120 } 121 122 int OnHook(int code, WM message, IntPtr state) 123 { 124 SetCursorPos(1846, 260); //対象の座標をここで代入 125 mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0); 126 mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0); 127 mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0); 128 mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0); 129 130 Console.WriteLine("message={0}", message); 131 return CallNextHookEx(hook, code, message, state); 132 } 133 } 134} 135

別プロジェクトで

c#

1添付画像のプロジェクト 2Form1cs 3 4using System; 5using System.Collections.Generic; 6using System.ComponentModel; 7using System.Data; 8using System.Drawing; 9using System.Linq; 10using System.Text; 11using System.Threading.Tasks; 12using System.Windows.Forms; 13using System.Runtime.InteropServices; 14using System.Threading; 15 16namespace test0630 17{ 18 public partial class Form1 : Form 19 { 20 [DllImport("USER32.dll", CallingConvention = CallingConvention.StdCall)] 21 static extern void SetCursorPos(int X, int Y); 22 [DllImport("USER32.dll", CallingConvention = CallingConvention.StdCall)] 23 static extern void mouse_event(int dwFlags, int dx, int dy, int cButtons, int dwExtraInfo); 24 25 private const int MOUSEEVENTF_LEFTDOWN = 0x2; 26 private const int MOUSEEVENTF_LEFTUP = 0x4; 27 int startX; 28 int startY; 29 int endX; 30 int endY; 31 32 public Form1() 33 { 34 InitializeComponent(); 35 timer1.Start(); 36 } 37 38 private void timer1_Tick(object sender, EventArgs e) 39 { 40 valueX.Text = (System.Windows.Forms.Cursor.Position.X).ToString(); 41 valueY.Text = (System.Windows.Forms.Cursor.Position.Y).ToString(); 42 } 43 44 private void Form1_KeyDown(object sender, KeyEventArgs e) 45 { 46 if (e.KeyData == Keys.Escape) 47 { 48 startX = int.Parse(connectS_X.Text); 49 startY = int.Parse(connectS_Y.Text); 50 endX = int.Parse(connectE_X.Text); 51 endY = int.Parse(connectE_Y.Text); 52 SetCursorPos(startX, startY); 53 mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0); 54 mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0); 55 mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0); 56 System.Threading.Thread.Sleep(300); 57 mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0); 58 SetCursorPos(50, 50); 59 mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0); 60 mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0); 61 } 62 else if (e.KeyData == Keys.F1) 63 { 64 startX = int.Parse(connectS_X.Text); 65 startY = int.Parse(connectS_Y.Text); 66 endX = int.Parse(connectE_X.Text); 67 endY = int.Parse(connectE_Y.Text); 68 SetCursorPos(endX, endY); 69 mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0); 70 mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0); 71 mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0); 72 System.Threading.Thread.Sleep(300); 73 mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0); 74 SetCursorPos(50, 50); 75 mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0); 76 mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0); 77 } 78 } 79 80 private void textBox1_KeyDown(object sender, KeyEventArgs e) 81 { 82 if (e.KeyData == Keys.Escape) 83 { 84 startX = int.Parse(connectS_X.Text); 85 startY = int.Parse(connectS_Y.Text); 86 endX = int.Parse(connectE_X.Text); 87 endY = int.Parse(connectE_Y.Text); 88 SetCursorPos(startX, startY); 89 mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0); 90 mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0); 91 mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0); 92 System.Threading.Thread.Sleep(300); 93 mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0); 94 SetCursorPos(50, 50); 95 mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0); 96 mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0); 97 } 98 else if (e.KeyData == Keys.F1) 99 { 100 startX = int.Parse(connectS_X.Text); 101 startY = int.Parse(connectS_Y.Text); 102 endX = int.Parse(connectE_X.Text); 103 endY = int.Parse(connectE_Y.Text); 104 SetCursorPos(endX, endY); 105 mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0); 106 mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0); 107 mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0); 108 System.Threading.Thread.Sleep(300); 109 mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0); 110 SetCursorPos(50, 50); 111 mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0); 112 mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0); 113 } 114 } 115 116~~文字数の関係で省いてます~~ 117 } 118} 119 120

これを1つに取りまとめたいというのが
やりたいことになりますが、その他不足情報がありましたら
指示ください。

開発環境
Win7 64bit
Visual Studio2017

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

y_waiwai

2018/07/30 07:39

具体的になにをどうしたいのか説明してください。また、どういうコードで実行させてるのかも提示してください
kikukiku

2018/07/31 04:52

質問文の「しかしグローバルフック自体難易度が高く、 Form1.csのデザインと連携していないようで、 上記の画像のようにフォームを組んで、パラメータを取得、設定したりする方法がわかりません。 」の部分が具体的ではなく、いったい何をしたいのかわかりませんでした。
mamonPro

2018/07/31 05:47

Form1.csでコーディングする際にグローバルフックを取り入れたいという意味ですが、その言葉の表現ですと、不適切でしょうか。すみません、どのように言い表せばいいのか、わかりませんでした。
sh_akira

2018/07/31 08:18

良く分かりませんが上のclass Form1 : Formの内容をしたの public partial class Form1 : Formにコピーして、被った関数は中身を合体させて動くか見てますか?
mamonPro

2018/08/07 01:24

回答が遅くなりすみません。そのあたりいろいろと試してみたりしましたが、エラーが発生したりしてうまくいきませんでした。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだ回答がついていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問