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

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

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

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

PowerShell

Windows PowerShellはコマンドラインインターフェースであり、システム管理を含むWindowsタスク自動化のためのスクリプト言語です。

Q&A

解決済

1回答

3624閲覧

別プロセスのそれぞれのメインウィンドウのZオーダーを比較したい

kamikazelight

総合スコア305

C#

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

PowerShell

Windows PowerShellはコマンドラインインターフェースであり、システム管理を含むWindowsタスク自動化のためのスクリプト言語です。

0グッド

0クリップ

投稿2018/10/19 02:18

前提・実現したいこと

複数のExcelプロセスの中で一番Zオーダーが高い
ウィンドウがどれか特定したいです。

特定したウィンドウのブックに対して操作をしたいです。

プロセスが同じならcomつかってActiveWorkbook確認すればいいのですが
プロセスが分かれているのでZオーダで確認するしかないと思うのですがどうしたら出来るのかわかりません。

教えてください。

試したこと、現状

最初にGet-Processを使ってExcelが起動しているか確認します。
見つかれば
C#を使ってモニカから全てのExcelブックのcomオブジェクトを取得し、それぞれのブックの
ウィンドウハンドルを取得します。
次にC#をつかってWin32 APIを使いフォアグラウンドのウィンドウを取得しウィンドウハンドルを確認してExcelブックか確認取ります。
Excelブックだったら変数に最前面だったExcelのcomオブジェクトを保存します。

そんな感じで最後に最前面になったExcelブックのcomオブジェクトをキープしておいて 操作しているのですが
最初に一度Excelウィンドウをアクティブにしないと操作できないですし、
最前面のブックを閉じる度にまたExcelウィンドウをアクティブにしないと操作できないのです。

補足情報(FW/ツールのバージョンなど)

win10

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

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

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

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

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

guest

回答1

0

ベストアンサー

トップレベルウィンドウのハンドルを Z オーダー順に列挙します。

Ps1

1Add-Type -TypeDefinition @" 2using System; 3using System.Runtime.InteropServices; 4 5public class Platform 6{ 7 [DllImport("user32.dll", SetLastError = true)] 8 public static extern IntPtr GetWindow(IntPtr hwnd, GetWindowType uCmd); 9 10 [DllImport("user32.dll", SetLastError = true)] 11 public static extern IntPtr GetDesktopWindow(); 12} 13 14public enum GetWindowType : uint 15{ 16 First = 0, 17 Last = 1, 18 Next = 2, 19 Prev = 3, 20 Owner = 4, 21 Child = 5, 22 EnabledPopup = 6 23} 24"@ 25$window = [Platform]::GetWindow([Platform]::GetDesktopWindow(), [GetWindowType]::Child) 26while ($window -ne [IntPtr]::Zero) 27{ 28 $window 29 $window = [Platform]::GetWindow($window, [GetWindowType]::Next) 30}

#追記

上記スクリプトを少し変更し、一番手前の Excel のウィンドウが最前面に出ることを確認しました。

ps1

1Add-Type -TypeDefinition @" 2using System; 3using System.Runtime.InteropServices; 4 5public class Platform 6{ 7 [DllImport("user32.dll", SetLastError = true)] 8 public static extern IntPtr GetWindow(IntPtr hwnd, GetWindowType uCmd); 9 10 [DllImport("user32.dll", SetLastError = true)] 11 public static extern IntPtr GetDesktopWindow(); 12 13 [DllImport("kernel32.dll")] 14 public static extern uint GetLastError(); 15 16 [DllImport("user32.dll")] 17 [return: MarshalAs(UnmanagedType.Bool)] 18 public static extern bool SetForegroundWindow(IntPtr hwnd); 19} 20 21public enum GetWindowType : uint 22{ 23 First = 0, 24 Last = 1, 25 Next = 2, 26 Prev = 3, 27 Owner = 4, 28 Child = 5, 29 EnabledPopup = 6 30} 31"@ 32function EnumerateWindows 33{ 34 $window = [Platform]::GetWindow([Platform]::GetDesktopWindow(), [GetWindowType]::Child) 35 while ($window -ne [IntPtr]::Zero) 36 { 37 $window 38 $window = [Platform]::GetWindow($window, [GetWindowType]::Next) 39 } 40} 41$handles = @(Get-Process | Where-Object { $_.Name -eq 'Excel' } | Foreach-Object { $_.MainWindowHandle }) 42if ($handles -eq $null) { 43 return 44} 45$handle = EnumerateWindows | Where-Object { $handles.Contains($_) } | Select-Object -First 1 46[Platform]::SetForegroundWindow($handle)

投稿2018/10/19 09:12

編集2018/10/19 10:49
Zuishin

総合スコア28662

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

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

kamikazelight

2018/10/19 10:08

ありがとうございます。 早速確認してみます。
kamikazelight

2018/10/19 14:17

質問内容以外もいろいろ勉強になりました。 検証に夢中になってベストアンサーつけるの遅くなりました。 ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.37%

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

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

質問する

関連した質問