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

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

詳細はこちら
.NET

.NETとは、主に.NET Frameworkと呼ばれるアプリケーションまたは開発環境を指します。CLR(共通言語ランタイム)を搭載し、入力された言語をCIL(共通中間言語)に変換・実行することが可能です。そのため、C#やPythonなど複数の言語を用いることができます。

C#

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

Win32 API

Win32 APIはMicrosoft Windowsの32bitプロセッサのOSで動作するAPIです。

Q&A

解決済

1回答

4032閲覧

C#でWindowが最前面に固定されているのかを知りたい。

nanagami

総合スコア16

.NET

.NETとは、主に.NET Frameworkと呼ばれるアプリケーションまたは開発環境を指します。CLR(共通言語ランタイム)を搭載し、入力された言語をCIL(共通中間言語)に変換・実行することが可能です。そのため、C#やPythonなど複数の言語を用いることができます。

C#

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

Win32 API

Win32 APIはMicrosoft Windowsの32bitプロセッサのOSで動作するAPIです。

0グッド

0クリップ

投稿2021/02/15 12:43

前提・実現したいこと

現在このようなアプリケーションを開発中です。
Windowを任意のキーボードショートカットで最前面に固定をする。
逆にWindowが最前面に固定されていた場合は最前面で固定を解除する。

発生している問題

そのなかで、Windowが最前面に固定されているのかの情報を取得する方法がわかりません。
Windows APIのどの関数を叩けば、調べられるのかを教えて欲しいです。

現在、SetWindowPos関数を叩けば最前面に固定と解除が出来る事と、自分が最前面に固定したいWindowのハンドルの取得方法が、わかっています。

該当のソースコード

WIndowAPIにアクセスするクラス

csharp

1 public static class WindowManager 2 { 3 private static readonly IntPtr HWND_TOPMOST = new IntPtr(-1); 4 private static readonly IntPtr HWND_NOTOPMOST = new IntPtr(-2); 5 private const int SWP_SHOWWINDOW = 0x0040; 6 private const uint SWP_NOSIZE = 0x0001; 7 private const uint SWP_NOMOVE = 0x0002; 8 9 // (x, y), (cx, cy)を無視するようにする. 10 private const uint TOPMOST_FLAGS = (SWP_NOSIZE | SWP_NOMOVE); 11 private const uint NOTOPMOST_FLAGS = (SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW); 12 13 public static bool SetAtTheFront(IntPtr handle) 14 => NativeMethods.SetWindowPos(handle, HWND_TOPMOST, 0, 0, 0, 0, TOPMOST_FLAGS); 15 16 public static bool UnSetAtTheFront(IntPtr handle) 17 => NativeMethods.SetWindowPos(handle, HWND_NOTOPMOST, 0, 0, 0, 0, NOTOPMOST_FLAGS); 18 19 public static IntPtr GetForegroundWindow() => NativeMethods.GetForegroundWindow(); 20 21 private static class NativeMethods 22 { 23 [DllImport("user32.dll")] 24 public static extern IntPtr GetForegroundWindow(); 25 26 [DllImport("user32.dll")] 27 [return: MarshalAs(UnmanagedType.Bool)] 28 public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int x, int y, int cx, int cy, uint flags); 29 } 30 } 31

最終的に書きたいコード

csharp

1 IntPtr handle = WindowManager.GetForegroundWindow(); 2 var isAtTheTop = Windowが最前面に固定されているかを調べる関数(handle) 3 if (isAtTheTop) 4 { 5 WindowManager.UnSetAtTheFront(handle); 6 } 7 else 8 { 9 WindowManager.SetAtTheFront(handle); 10 }

試したこと

GetWindowInfo関数のリファレンスを読む - 関係しそうなものは見つけられず
GetWindowRect関数のリファレンスを読む - 関係しそうなものは見つけられず
GetWindowPlacement関数のリファレンスを読む - 関係しそうなものは見つけられず

自分が見逃しているだけかもしれませんが、全然わかりません。
助けて頂けないでしょうか?

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

  • Visual Studio 2019
  • C# 9
  • .NET 5

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

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

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

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

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

guest

回答1

0

自己解決

Windows FormにWindowが、最前面に固定されているか判定するTopMostプロパティがあったので、内部実装を調べたらわかりました。

下のコードのIsAtTheFront関数が今回、Windowが、最前面に固定されているか調べる関数になります。

GetWindowInfo関数で取得した、Extended Window Stylesのフラグを見たらわかりました。

csharp

1public static class WindowManager 2{ 3 // 今回作成したWindowが、最前面に固定化されているか調べる関数 4 public static bool IsAtTheFront(IntPtr handle) 5 { 6 const int TopMostFlag = 0x00000008; 7 NativeMethods.GetWindowInfo(handle,out var windowInfo) 8 return 0 != (windowInfo.dwExStyle & TopMostFlag); 9 } 10 11 [StructLayout(LayoutKind.Sequential)] 12 public struct RECT 13 { 14 public int Left; 15 public int Top; 16 public int Right; 17 public int Bottom; 18 } 19 20 21 [StructLayout(LayoutKind.Sequential)] 22 public struct WINDOWINFO 23 { 24 public uint cbSize; 25 public RECT rcWindow; 26 public RECT rcClient; 27 public uint dwStyle; 28 public uint dwExStyle; 29 public uint dwWindowStatus; 30 public uint cxWindowBorders; 31 public uint cyWindowBorders; 32 public ushort atomWindowType; 33 public ushort wCreatorVersion; 34 } 35 36 private static class NativeMethods 37 { 38 [DllImport("user32.dll", SetLastError = true)] 39 public static extern int GetWindowInfo(IntPtr hwnd, out WINDOWINFO pwi); 40 } 41}

投稿2021/02/15 13:31

編集2021/02/15 13:36
nanagami

総合スコア16

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問