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

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

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

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

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

Windows Forms

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

Q&A

解決済

1回答

7647閲覧

C#でC++のGetWindowRect()を実行したい

退会済みユーザー

退会済みユーザー

総合スコア0

C#

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

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

Windows Forms

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

0グッド

0クリップ

投稿2019/05/10 07:32

編集2019/05/14 00:28

解決後のコード

変更したやつだけ置いておきます。

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をあげてますが、実際にthisプラットフォーム呼び出しが返されるまで終了しないマネージド オブジェクト。なのかは謎です。
GetWindoRect()とかMoveWindow()の処理が終わるまでの間に破棄されるオブジェクトでないという意味なら確かにそうかもしれないけどよく分かりません。動けば官軍ということにします。
ベストアンサー者の @takabosoft 様が補足してくださっているのでベストアンサーを確認してください。


よろしくお願いいたします。

前提・実現したいこと

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

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

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

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

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

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

guest

回答1

0

ベストアンサー

p/invokeの型がおかしいです。

https://pinvoke.net/default.aspx/user32/GetWindowRect.html

を参考にしてください。
RECT構造体とセットでコピペすると良いかと思います。

投稿2019/05/10 07:37

takabosoft

総合スコア8356

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

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

退会済みユーザー

退会済みユーザー

2019/05/10 08:21

提示していただいたソースをコピペしてみたらうまくいきました。 GetWindoRectの第一引数をnew HandleRef(object, IntPtr)で objectに何を与えるべきか分からず少し悩みましたが とりあえずでthisを与えてみたところ動いてくれたので頭を抱えています MoveWindow()などにもhWndの代わりにHandleRefを使ったら実行可能だったので アンマネージの関数からウィンドウハンドルを取得するときはIntPtrで受け アンマネージの関数にウィンドウハンドルを与えるときはnew HandleRef(this, [IntPtr型の何か])を与えればよいようですね。 ありがとうございました。
退会済みユーザー

退会済みユーザー

2019/05/13 06:51

解説ありがとうございます。大変助かります。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問