前提・実現したいこと
C#のWindowsFormアプリケーションでクリックしたウィンドウのプロセス名を取得したい。
.NETFramework4.6を使用
Markdownに慣れていない為、わかりにい点が多々有ると思いますが、アドバイスありましたらぜひお願いします。
例
1.Hogeを起動 2.Hoge内のボタンをクリック 3.Hogeのウィンドウが非アクティブになる 4.Hogeとは別のプログラムのウィンドウをクリック 5.Hogeのウィンドウがアクティブになりテキストボックスに電卓のプロセス名が表示される
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2019/09/18 11:08
2019/09/18 11:09
2019/09/18 11:13
2019/09/18 11:18
2019/09/18 11:19
2019/09/18 11:20
回答2件
0
(1) グローバルフックを行います。
「C#にてマウスとキーボードを操りし者」
https://qiita.com/exliko/items/3135e4413a6da067b35d
から HouseHook.cs をコピーしてください。
(2) 以下をフォームに貼り付けます。
C#
1using System; 2using System.Diagnostics; 3using System.Drawing; 4using System.Runtime.InteropServices; 5using System.Text; 6using System.Windows.Forms; 7using MMFrame.Windows.GlobalHook; 8 9namespace WindowsFormsApp1 10{ 11 public partial class Form1 : Form 12 { 13 public Form1() { 14 InitializeComponent(); 15 } 16 17 public void MouseHookStart() { 18 if (!MouseHook.IsHooking) { 19 MouseHook.AddEvent(MouseHookEvent); 20 MouseHook.Start(); 21 } 22 } 23 24 private void MouseHookEnd() { 25 if (MouseHook.IsHooking) { 26 MouseHook.RemoveEvent(MouseHookEvent); 27 MouseHook.Stop(); 28 } 29 } 30 31 private void MouseHookEvent(ref MouseHook.StateMouse s) { 32 if (s.Stroke == MouseHook.Stroke.LEFT_DOWN) { 33 IntPtr hwndApp = NativeMethods.GetAppWindow( 34 NativeMethods.WindowFromPoint(new Point(s.X, s.Y))); 35 int processId = NativeMethods.GetProcessIdFromWindow(hwndApp); 36 var process = Process.GetProcessById(processId); 37 textBox1.Text = process.ProcessName; 38 MouseHookEnd(); 39 BeginInvoke((Action)(() => { 40 NativeMethods.Active(Handle); 41 Activate(); 42 })); 43 } 44 } 45 46 protected override void OnFormClosed(FormClosedEventArgs e) { 47 base.OnFormClosed(e); 48 MouseHookEnd(); 49 } 50 51 private void button1_Click(object sender, EventArgs e) { 52 NativeMethods.Deactive(this.Handle); 53 MouseHookStart(); 54 } 55 56 private static class NativeMethods 57 { 58 private enum WindowCmd : uint 59 { 60 First, 61 Last, 62 Next, 63 Previous, 64 Owner, 65 Child, 66 EnablePopup, 67 } 68 69 [DllImport("user32.dll")] 70 private static extern IntPtr GetWindow(IntPtr hWnd, WindowCmd uCmd); 71 72 [DllImport("user32.dll")] 73 private static extern IntPtr GetParent(IntPtr hWnd); 74 75 [DllImport("user32.dll")] 76 private static extern void SwitchToThisWindow(IntPtr hWnd, bool fAltTab); 77 78 [DllImport("user32.dll")] 79 private static extern uint GetWindowThreadProcessId(IntPtr hWnd, out int lpdwProcessId); 80 81 [DllImport("user32.dll", CharSet = CharSet.Auto)] 82 private static extern int GetClassName(IntPtr hWnd, 83 StringBuilder lpClassName, int nMaxCount); 84 85 [DllImport("user32.dll", CharSet = CharSet.Auto)] 86 private static extern int GetWindowText(IntPtr hWnd, 87 StringBuilder lpClassName, int nMaxCount); 88 89 [DllImport("user32.dll")] 90 private static extern int GetWindowTextLength(IntPtr hWnd); 91 92 [DllImport("user32.dll")] 93 public static extern IntPtr WindowFromPoint(Point p); 94 95 [DllImport("user32.dll")] 96 private static extern IntPtr FindWindowEx(IntPtr hwndParent, 97 IntPtr hwndChildAfter, string lpszClass, string lpszWindow); 98 99 private static IntPtr GetTopLevelWindow(IntPtr hwnd) { 100 IntPtr cur = IntPtr.Zero; 101 while (hwnd != IntPtr.Zero) { 102 cur = hwnd; 103 hwnd = GetParent(hwnd); 104 } 105 return cur; 106 } 107 108 private static bool IsUWP(IntPtr hwndTop) { 109 var sb = new StringBuilder(1024); 110 if (GetClassName(hwndTop, sb, sb.Capacity) > 0) { 111 if (sb.ToString() == "ApplicationFrameWindow") { 112 return true; 113 } 114 } 115 return false; 116 } 117 118 private static IntPtr GetCoreWindow(IntPtr hwndTop) { 119 return FindWindowEx(hwndTop, IntPtr.Zero, "Windows.UI.Core.CoreWindow", null); 120 } 121 122 public static IntPtr GetAppWindow(IntPtr hwnd) { 123 IntPtr hwndTop = GetTopLevelWindow(hwnd); 124 if (IsUWP(hwndTop)) { 125 return GetCoreWindow(hwndTop); 126 } 127 return hwndTop; 128 } 129 130 public static int GetProcessIdFromWindow(IntPtr hwnd) { 131 if (GetWindowThreadProcessId(hwnd, out var processId) != 0) { 132 return processId; 133 } 134 return 0; 135 } 136 137 public static string GetWindowText(IntPtr hwnd) { 138 var length = GetWindowTextLength(hwnd); 139 if (length > 0) { 140 var sb = new StringBuilder(length + 1); 141 if (GetWindowText(hwnd, sb, sb.Capacity) > 0) { 142 return sb.ToString(); 143 } 144 } 145 return string.Empty; 146 } 147 148 public static void Deactive(IntPtr hwnd) { 149 SwitchToThisWindow(GetWindow(hwnd, WindowCmd.Next), true); 150 } 151 152 public static void Active(IntPtr hwnd) { 153 SwitchToThisWindow(hwnd, true); 154 } 155 } 156 } 157}
UWP のウインドウ構成は
ApplicationFrameWindow
- ApplicationFrameTitleBarWindow
- Windows.UI.Core.CoreWindow
- ApplicationFrameTitleBarWindow
- ApplicationFrameInputSinkWindow
のようになっており、Windows.UI.Core.CoreWindow のプロセスと他のウインドウのプロセスが違います。
正しいプロセス名を取得するには Windows.UI.Core.CoreWindow のウインドウを取得すれば良いようです。
投稿2019/09/19 09:05
編集2019/09/20 00:15総合スコア2707
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
スクリーンショットを撮る方法なら比較的簡単にできますよ。
マルチスクリーンの場合は各スクリーンに表示したり工夫が必要ですが。
C#
1using System; 2using System.Diagnostics; 3using System.Drawing; 4using System.Runtime.InteropServices; 5using System.Windows.Forms; 6 7namespace ProcessInfo 8{ 9 public partial class Form1 : Form 10 { 11 [DllImport("user32.dll")] 12 static extern IntPtr WindowFromPoint(System.Drawing.Point p); 13 14 [DllImport("user32.dll", SetLastError = true)] 15 static extern uint GetWindowThreadProcessId(IntPtr hWnd, out int lpdwProcessId); 16 17 public Form1() 18 { 19 InitializeComponent(); 20 } 21 22 private void button1_Click(object sender, EventArgs e) 23 { 24 Visible = false; 25 26 // 自身が消えるを待ってからスクリーンショットを撮る 27 var timer = new Timer(); 28 timer.Interval = 250; 29 timer.Tick += (s, a) => { 30 timer.Dispose(); 31 var scr = Screen.FromHandle(Handle); 32 getClickLocation(scr, p => { 33 Visible = true; 34 showProcessOfPoint(p); 35 }); 36 }; 37 timer.Start(); 38 } 39 40 private void getClickLocation(Screen screen, Action<Point> clickHandler) 41 { 42 // スクリーンショットを全画面で表示 43 var screenShotForm = new Form(); 44 screenShotForm.FormBorderStyle = FormBorderStyle.None; 45 screenShotForm.DesktopBounds = screen.Bounds; 46 47 var sc = screenShot(screen); 48 49 screenShotForm.Paint += (s, a) => { 50 a.Graphics.DrawImage(sc, 0, 0); 51 }; 52 53 screenShotForm.MouseDown += (s, a) => { 54 if (a.Button == MouseButtons.Left) { 55 screenShotForm.Close(); 56 clickHandler(a.Location); 57 } 58 }; 59 60 screenShotForm.FormClosed += (s, a) => { 61 screenShotForm.Dispose(); 62 screenShotForm = null; 63 }; 64 65 screenShotForm.Show(); 66 } 67 68 private Image screenShot(Screen screen) 69 { 70 var bounds = screen.Bounds; 71 var image = new Bitmap(bounds.Width, bounds.Height, System.Drawing.Imaging.PixelFormat.Format24bppRgb); 72 73 using (var g = Graphics.FromImage(image)) { 74 g.CopyFromScreen(bounds.X, bounds.Y, 0, 0, new Size(bounds.Width, bounds.Height)); 75 g.CompositingMode = System.Drawing.Drawing2D.CompositingMode.SourceOver; 76 using (var brush = new SolidBrush(Color.FromArgb(128, 255, 255, 255))) { 77 g.FillRectangle(brush, 0, 0, bounds.Width, bounds.Height); 78 } 79 } 80 return image; 81 } 82 83 private void showProcessOfPoint(Point p) 84 { 85 // クリックした位置からウィンドウ -> プロセスID -> プロセスを取得、表示 86 var hwnd = WindowFromPoint(p); 87 88 if (hwnd != IntPtr.Zero) { 89 if (GetWindowThreadProcessId(hwnd, out var processId) != 0) { 90 var process = Process.GetProcessById(processId); 91 MessageBox.Show(process.ProcessName); 92 } 93 } else { 94 MessageBox.Show("No Window"); 95 } 96 } 97 } 98}
投稿2019/09/18 13:50
編集2019/09/19 14:26総合スコア2850
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2019/09/19 09:39
2019/09/19 09:46
2019/09/19 11:09
2019/09/19 14:29
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。