RECT rcCurrent; ::GetWindowRect ( hwndChild, &rcCurrent );
::MapWindowPoints ( NULL, hWnd, reinterpret_cast<LPPOINT>(&rcCurrent), 2);
このコードが実行しているのは、おそらく親ウィンドウ(hWnd)のクライアント領域に対する子ウィンドウ(hwndChild)の境界矩形(rcCurrent)を取得すること、または子ウィンドウがその親内のどこにあるかを判別することです。
最初の行は、子、境界線、およびすべての完全な長方形を取得しますが、画面座標で返されます。
2行目は、これらのポイントを画面座標(最初のNULLパラメーターで示される)からhWndのクライアント領域を基準にした座標にマップします。
Win32には「親内の場所を取得」呼び出しがないため、これは最も近いラウンドアバウトに相当します。
ここでキャストが行っているのは、Win32 RECTが2つの連続したPOINTとまったく同じメモリレイアウトを持っているという事実を利用しているため、cPoints = 2を指定してMapWindowPointsを呼び出すと、RECT全体が一度にマップされます。この使用法は実際にはMSDNで文書化されており、右から左へのミラーリングモードで特別な処理が行われ、左から右へのレイアウトのデスクトップから右から左へのアプリケーションにマップされたときに長方形全体が適切にマップされるようになっています。およびその逆!(ローカライズされたバージョンのアプリをヘブライ語またはアラビア語で実行できるようにR-to-Lミラーリングを使用する予定がない場合は、これについて心配する必要はありません。)
-
これをC#に変換する正しい方法は、どこから始めて何を達成しようとしているかによって異なります。アプリホールセールをC++からC#に変換していて、親と子のControl派生オブジェクトがある場合は、child.Locationを使用して、親に対する相対的な位置を取得できます。
-
一方、HWNDで記述されたコードを移植していて、C#に移植された場合でもその状態を維持する必要がある場合(たとえば、別のプロセスからのHWNDに対して機能している、またはHWNDの基盤となるフレームワークを知らないため) )、最善の策は、RECTとPOINTのP / Invokeバージョンを定義することです。ここで重要なことは、RECTで機能するMapWindowPointsのP/Invokeバージョンを定義することです。(ここでは、P / Invokeにある程度精通していると思います...)通常、MapWindowPointsは(pinvoke.netから)次のように定義されます。
[DllImport("user32.dll", SetLastError=true)]
public static extern int MapWindowPoints(IntPtr hwndFrom, IntPtr hwndTo, ref POINT lpPoints, [MarshalAs(UnmanagedType.U4)] int cPoints);
...そして、このバージョンを使用して、単一のPOINTをマップできます(常にcPointを1として渡します)。次に、RECTで動作するバージョンを定義することもできます。
[DllImport("user32.dll", SetLastError=true)]
public static extern int MapWindowPoints(IntPtr hwndFrom, IntPtr hwndTo, ref RECT lpPoints, [MarshalAs(UnmanagedType.U4)] int cPoints);
そして、この後者のバージョンを呼び出すときは、常にcPointsを2として渡します。これを呼び出すと、元のC ++ MapWindowPoints呼び出しとまったく同じC#になります。