解決後のコード
変更したやつだけ置いておきます。
C#
1namespace hoge 2{ 3 class NativeCodes 4 { 5 [StructLayout(LayoutKind.Sequential)] 6 public struct RECT 7 { 8 public int Left; // x position of upper-left corner 9 public int Top; // y position of upper-left corner 10 public int Right; // x position of lower-right corner 11 public int Bottom; // y position of lower-right corner 12 } 13 14 [DllImport("user32.dll")] 15 public static extern IntPtr FindWindow(String lpClassName,String lpWindowName); 16 17 [DllImport("user32.dll")] 18 [return:MarshalAs(UnmanagedType.Bool)] 19 private static extern bool GetWindowRect(HandleRef hWnd, out IntPtr lpRect); 20 } 21 class Fuga 22 { 23 private IntPtr _hwnd; 24 private System.Drawing.Rectangle _rect; 25 26 public Fuga(string className, string windowName) 27 { 28 _hwnd = NativeCodes.FindWindow(className, windowName); 29 30 NativeCodes.GetWindowRect(new HandleRef(this, _hwnd), out _rect); 31 32 } 33 } 34} 35
ちなみにFindWindow()
の戻り値の型をHandleRef
にしたら烈火のごとく怒られました。
アンマネージコードがウィンドウハンドルとして返してくれる値はあくまでIntPtr
に過ぎないようです。
new HandleRef()
の第一引数にはthis
をあげてますが、実際に ベストアンサー者の @takabosoft 様が補足してくださっているのでベストアンサーを確認してください。this
がプラットフォーム呼び出しが返されるまで終了しないマネージド オブジェクト。なのかは謎です。
GetWindoRect()
とかMoveWindow()
の処理が終わるまでの間に破棄されるオブジェクトでないという意味なら確かにそうかもしれないけどよく分かりません。動けば官軍ということにします。
よろしくお願いいたします。
前提・実現したいこと
C#でGetWindoRect()
でウィンドウの位置情報を取得したい。
ウィンドウハンドル自体はIntPtr
型変数に格納できているはずです。
ですがウィンドウの位置情報を取得する部分で例外が発生しています。
発生している問題・エラーメッセージ
VisualStudio上で表示されたエラー
AccessViolationExceptionはハンドルされませんでした。
型 'System.AccessViolationException' のハンドルされていない例外が System.Windows.Forms.dll で発生しました
追加情報:保護されているメモリに読み取りまたは書き込み操作を行おうとしました。他のメモリが壊れていることが考えられます。
該当のソースコード
C#
1 2namespace hoge 3{ 4 class NativeCodes 5 { 6 [DllImport("user32.dll")] 7 public static extern IntPtr FindWindow(String lpClassName,String lpWindowName); 8 9 [DllImport("user32.dll")] 10 [return:MarshalAs(UnmanagedType.Bool)] 11 private static extern bool GetWindowRect(IntPtr hWnd, out IntPtr lpRect); 12 /// <summary> 13 /// Win32APIのGetWindowRect()をC#コードで実行するためのヘルパー 14 /// </summary> 15 /// <param name="hWnd">ウィンドウハンドル</param> 16 /// <param name="rect">ウィンドウの位置情報</param> 17 /// <returns>実行結果</returns> 18 public static bool GetWindowRect(IntPtr hWnd, out System.Drawing.Rectangle rect) 19 { 20 var windowRect = new System.Drawing.Rectangle(); 21 // 結果を格納する領域確保 22 IntPtr pRect = new IntPtr(); 23 pRect = Marshal.AllocHGlobal(Marshal.SizeOf(windowRect)); 24 25 bool apiResult = GetWindowRect(hWnd, out pRect); 26 windowRect = (System.Drawing.Rectangle)Marshal.PtrToStructure(pRect, (windowRect).GetType()); 27 // ↑で例外が発生します 28 // 呼び出し側を続きに書きますが、呼び出しでTry-Catchしても例外を捕捉出来ません。 29 // この例はFormアプリで、Application.Run(new Form1())する部分でVisualStudioが例外を表示してくれています。 30 31 // 結果を格納する領域解放 32 Marshal.FreeCoTaskMem(pRect); 33 // 結果を受け渡し 34 rect = windowRect; 35 36 return apiResult; 37 } 38 } 39 class Fuga 40 { 41 private IntPtr _hwnd; 42 private System.Drawing.Rectangle _rect; 43 44 public Fuga(string className, string windowName) 45 { 46 _hwnd = NativeCodes.FindWindow(className, windowName); 47 48 NativeCodes.GetWindowRect(_hwnd, out _rect); 49 50 } 51 } 52}
C#
1namespace hoge 2{ 3 public partial class Form1 : Form 4 { 5 private void button1_Click(object sender, EventArgs e) 6 { 7 string msg = "ok!"; 8 9 try 10 { 11 Fuga aui = new Fuga("Notepad", "無題 - メモ帳"); 12 } 13 catch( Exception ex) 14 // ここではcatchできません 15 { 16 MessageBox.Show(ex.StackTrace, ex.Message); 17 return; 18 } 19 20 MessageBox.Show(msg); 21 } 22 } 23}
なお、RECTを
c#
1[StructLayout(LayoutKind.Sequential)] 2struct RECT 3{ 4 long left, bottom, right, top; 5}
などと定義せずSystem.Drawing.Rectangle
を使用しているのは一度試してみて駄目だったためで、
この質問の回答を参考にしているからです。
補足情報(FW/ツールのバージョンなど)
- Visual Studio 2015 SP1
- Windows 7 64bit

回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
退会済みユーザー
2019/05/10 08:21
2019/05/10 08:40
退会済みユーザー
2019/05/13 06:51