🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
C#

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

Windows Forms

Windows Forms(WinForms)はMicrosoft .NET フレームワークに含まれる視覚的なアプリケーションのプログラミングインターフェイス(API)です。WinFormsは管理されているコードの既存のWindowsのAPIをラップすることで元のMicrosoft Windowsのインターフェイスのエレメントにアクセスすることができます。

Q&A

2回答

2516閲覧

C#のWindowsFormアプリケーションでクリックしたウィンドウのプロセス名を取得したい。

hayato456

総合スコア8

C#

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

Windows Forms

Windows Forms(WinForms)はMicrosoft .NET フレームワークに含まれる視覚的なアプリケーションのプログラミングインターフェイス(API)です。WinFormsは管理されているコードの既存のWindowsのAPIをラップすることで元のMicrosoft Windowsのインターフェイスのエレメントにアクセスすることができます。

1グッド

2クリップ

投稿2019/09/18 10:24

編集2019/09/18 11:14

前提・実現したいこと

C#のWindowsFormアプリケーションでクリックしたウィンドウのプロセス名を取得したい。
.NETFramework4.6を使用
Markdownに慣れていない為、わかりにい点が多々有ると思いますが、アドバイスありましたらぜひお願いします。

1.Hogeを起動 2.Hoge内のボタンをクリック 3.Hogeのウィンドウが非アクティブになる 4.Hogeとは別のプログラムのウィンドウをクリック 5.Hogeのウィンドウがアクティブになりテキストボックスに電卓のプロセス名が表示される
arkyu5468👍を押しています

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

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

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

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

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

Zuishin

2019/09/18 11:01 編集

P/Invoke やグローバルフックを使わなくちゃいけないので難しいです。UWP とか入ってくると特に。 どうしてもしなければならないことでなければあきらめた方がいいと思います。 http://mzs184.blogspot.com/2009/03/c.html これをタイマーで定期的に動かせば比較的簡単ですが、UWP には対応していないと思います。(未確認)
hayato456

2019/09/18 11:08

回答ありがとうございます! UWPは使用しないので一度試してみます。
Zuishin

2019/09/18 11:09

電卓が UWP です。
hayato456

2019/09/18 11:13

訂正ありがとうございます。 例に電卓を挙げたんですけれどもchromeやfirefoxを対象にするつもりです 。
Zuishin

2019/09/18 11:18

それなら比較的簡単ですね。やってみてください。 思い通りにできたら、解決法をこの質問に回答して自己解決としてください。
Zuishin

2019/09/18 11:19

もちろん、役に立つ回答がついた場合は、それをベストアンサーにすることもできます。
hayato456

2019/09/18 11:20

拙い文章に丁寧な回答ありがとうございます。
guest

回答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
KOZ6.0

総合スコア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
toki_td

総合スコア2850

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

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

Zuishin

2019/09/19 09:39

質問との関連がよくわかりません。
YAmaGNZ

2019/09/19 09:46

どのウインドウか選択するときに、その瞬間のスクリーンショットを取得し、自前のウインドウで全画面で表示すればグローバルフックを使わずにそのウインドウのある座標が取れる。 その座標で、実際の場所にあるウインドウを取得するということだと思います。
Zuishin

2019/09/19 11:09

runScreenShot という名前なので、スクリーンショットを撮るだけだと思っていました。 よく見ると MouseDown の処理が書いてありましたね。
toki_td

2019/09/19 14:29

YAmaGNZさんの通りです。 確かにまとめて過ぎて意味不明でしたのでちょっと書き換えましたm(_ _)m
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

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

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

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問