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

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

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

Microsoft Visual Basic .NETのことで、Microsoft Visual Basic(VB6)の後継。 .NET環境向けのプログラムを開発することができます。 現在のVB.NETでは、.NET Frameworkを利用して開発を行うことが可能です。

Q&A

解決済

2回答

3617閲覧

GetWindowRectやDwmGetWindowAttributeでフォームの座標やサイズが取得できないことがある

coffeeumee

総合スコア19

VB.NET

Microsoft Visual Basic .NETのことで、Microsoft Visual Basic(VB6)の後継。 .NET環境向けのプログラムを開発することができます。 現在のVB.NETでは、.NET Frameworkを利用して開発を行うことが可能です。

0グッド

0クリップ

投稿2019/06/07 22:46

編集2019/06/07 23:05

前提・実現したいこと

環境:Windows10Home、VisualStudio2017(VB.NET)
以下のソースで、通常であればrect1とrect2にそれぞれ座標と画面サイズが入るのですが、一部のソフト(TeraPad)において取得値が座標が-100、サイズが0となります。
正しく取得できない原因または取得方法について教えてください。

該当のソースコード

VB.NET

1'はじめの宣言 2Public Class Form1 3 Inherits Form 4 5 Enum DWMWINDOWATTRIBUTE As UInteger 6 NCRenderingEnabled = 1 7 NCRenderingPolicy 8 TransitionsForceDisabled 9 AllowNCPaint 10 CaptionButtonBounds 11 NonClientRtlLayout 12 ForceIconicRepresentation 13 Flip3DPolicy 14 ExtendedFrameBounds 15 HasIconicBitmap 16 DisallowPeek 17 ExcludedFromPeek 18 Cloak 19 Cloaked 20 FreezeRepresentation 21 End Enum 22 23 <StructLayout(LayoutKind.Sequential)> 24 Private Structure RECT 25 Public left As Integer 26 Public top As Integer 27 Public right As Integer 28 Public bottom As Integer 29 End Structure 30 31 Private Declare Function GetWindowRect Lib "user32.dll" (ByVal hwnd As IntPtr, ByRef lpRect As RECT) As Boolean 32 Private Declare Function DwmGetWindowAttribute Lib "dwmapi.dll" (ByVal hwnd As IntPtr, ByVal dwAttribute As DWMWINDOWATTRIBUTE, ByRef pvAttribute As RECT, ByVal cbAttribute As Integer) As Integer 33 34 35'該当箇所 36System.Diagnostics.Process() 37Dim p As System.Diagnostics.Process 38For Each p In System.Diagnostics.Process.GetProcesses() 39 Dim rect1 = New RECT 40 Form1.GetWindowRect(p.MainWindowHandle, rect1) 41 Dim rect2 = New RECT 42 Form1.DwmGetWindowAttribute(p.MainWindowHandle, DWMWINDOWATTRIBUTE.ExtendedFrameBounds, rect2, Marshal.SizeOf(rect2)) 43 'ここで何かやる 44Next

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

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

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

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

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

guest

回答2

0

ベストアンサー

ほかのソフトでうまく動いているとしたら、コードに問題はないということだと思います。どうなっているのか Spy++ で調べてみてください。

投稿2019/06/07 23:22

Zuishin

総合スコア28656

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

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

Zuishin

2019/06/07 23:24

もしかしたら、TeraPad のメインウィンドウは不可視で、見えているのはサブウィンドウなのかもしれません。
coffeeumee

2019/06/08 02:49

確認したところ、SPY++で確認できる実態は別のプロセスで動いていました。 残念ながらSystem.Diagnostics.Process.GetProcesses()で取得できる一覧にはMainWindowHandleでチェックした限りでは実態プロセスは見つけられませんでした。 その後不可視プロセスを辿ってみましたがやはり座標は取得できませんでした。 このままだと同じ仕組みのソフトでも同様の現象が起きそうで気持ち悪いのですが、とりあえず現状では取得できないということで諦めます。ありがとうございました。 参考にした資料 http://pinvoke.net/default.aspx/user32/EnumChildWindows.html https://knowledge.reontosanta.com/archives/990
guest

0

GetProcesses()でウィンドウタイトルを取得し、それに対してFindWindow()を使うことで取得できました。

Visual

1Private Declare Function GetWindowRect Lib "user32.dll" (ByVal hwnd As IntPtr, ByRef lpRect As RECT) As Boolean 2Private Declare Function FindWindow Lib "user32.dll" (ByVal lpClassName As String, ByVal lpWindowName As String) As Integer 3 4Private Structure RECT 5 Public Left As Integer 6 Public Top As Integer 7 Public Right As Integer 8 Public Bottom As Integer 9End Structure 10 11 12 13Private Sub GetRectangle() 14 15 '全てのプロセスを列挙し、ウィンドウタイトルを取得する。 16 Dim p As System.Diagnostics.Process 17 18 For Each p In System.Diagnostics.Process.GetProcesses() 19 If p.MainWindowTitle.Length <> 0 Then 20 21 Dim results As String = p.MainWindowTitle 22 list_title.Items.Add(results) 23 24 25 End If 26 27 28 Next 29 30 31 32 'ウィンドウタイトルからハンドルを取得し、ウィンドウ位置、サイズを取得する。 33 Dim hwnd As IntPtr = FindWindow(vbNullString, list_title.SelectedItem) 34 Dim lpRect As RECT 35 36 GetWindowRect(hwnd, lpRect) 37 38 Console.WriteLine("PosX:{0}, PosY:{1}, SizeX:{2}, SizeY:{3}", lpRect.Left, lpRect.Top, lpRect.Right - lpRect.Left, lpRect.Bottom - lpRect.Top) 39 40 41End Sub

TeraPadにおいて、p.MainWindowHandleで得たハンドルと上記コード(使っていたものから抜粋/整形しただけなので動くかは未検証です)で得たハンドルが異なっていました。原因は分かりませんが…

投稿2019/06/09 15:26

lemongrass

総合スコア18

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

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

Zuishin

2019/06/09 15:36

TeraPad を Wikipedia で調べると Delphi で作られていると書かれていますが、Delphi の場合、メインウィンドウはデフォルトで非表示です。 https://support.embarcadero.com/article/35956/ > TApplication は、Delphi アプリケーションのベースです。メインフォームは、TApplication の MainForm プロパティによって示され、これは Run メソッドによって表示されます。実際このフォームは、非表示のアプリケーションウィンドウの子フォームです。アプリケーションウィンドウは、Windows95 ならばタスクバーに表示されるアイコンです。 なので、普通の作り方をしているなら、ハンドルが違うのは仕様です。
lemongrass

2019/06/09 16:11 編集

メインウィンドウが非表示…たしかにそれだとハンドルは違う値になりますね。 子フォームということはFindWindowExやEnumChildWindowsで取れるのかもしれませんね。 (追記) …と思ったらEnumChildWindowsは検証済みでしたか…こちらでだめだと厳しそうです。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問