문제

i want convert this c++ code in C#:

RECT rcCurrent; ::GetWindowRect ( hwndChild, &rcCurrent ); ::MapWindowPoints ( NULL, hWnd, reinterpret_cast<LPPOINT>(&rcCurrent), 2);

But i don't know how transform :

reinterpret_cast<LPPOINT>(&rcCurrent)

How to cast System.Windows.Rect to System.Windows.Point ?

도움이 되었습니까?

해결책

RECT rcCurrent; ::GetWindowRect ( hwndChild, &rcCurrent );
::MapWindowPoints ( NULL, hWnd, reinterpret_cast<LPPOINT>(&rcCurrent), 2);

What this code is doing is getting the bounding rectangle (rcCurrent) of a child window (hwndChild) with respect to the client area of a presumably parent window (hWnd) - or determining where a child window is inside its parent.

The first line gets the full rectangle of the child, borders and all, but it gets returned in screen coordinates.

The second line maps those points from screen coordinates (indicated by the first NULL parameter) to coordinates relative to the client-area of hWnd.

Win32 doesn't have a "get location within parent" call, so this is the nearest roundabout equivalent.

What the cast is doing here is taking advantage of the fact that a Win32 RECT has the exact same memory layout as two back-to-back POINTs, so calling MapWindowPoints with cPoints=2 will map a whole RECT in one go. This usage is actually documented in MSDN, and even gets special treatment in right-to-left mirroring modes to ensure that whole rectangles get mapped properly when mapped from a left-to-right-layout desktop to a right-to-left application, and vice-versa! (If you don't plan on using R-to-L mirroring so that localized versions of your apps can run on Hebrew or Arabic, you don't need to worry about this.)

--

The correct way to translate this to C# depends on where you're starting from and what you're trying to achieve. If you're converting an app wholesale from C++ to C#, and you have Control-derived objects for the parent and the child, you can just use child.Location to get the position relative to the parent.

--

On the other hand, if you are porting code that is written in terms of HWNDs and has to remain that way even when ported to C# (eg. because it's working against HWNDs from another process or doesn't know the underlying framework of the HWNDs), then your best bet would be to define P/Invoke versions of RECT and POINT, and the key thing here is to define a P/Invoke version of MapWindowPoints that will work on RECT. (I'm assuming you're somewhat familiar with P/Invoke here...) Usually MapWindowPoints is defined as (from pinvoke.net):

[DllImport("user32.dll", SetLastError=true)]
public static extern int MapWindowPoints(IntPtr hwndFrom, IntPtr hwndTo, ref POINT lpPoints, [MarshalAs(UnmanagedType.U4)] int cPoints);

...and you can use this version to map a single POINT (always passing in cPoints as 1). You can then also define a version that works with RECT:

[DllImport("user32.dll", SetLastError=true)]
public static extern int MapWindowPoints(IntPtr hwndFrom, IntPtr hwndTo, ref RECT lpPoints, [MarshalAs(UnmanagedType.U4)] int cPoints);

And when calling this latter version, always pass in cPoints as 2. Calling this would then be the exact C# equivalent of the original C++ MapWindowPoints call.

다른 팁

Wow, that's a real abuse of reinterpret_cast! The code is basically saying: take a pointer to a section of memory containing 4 integers, and pretend that it is actually a pointer to a section of memory containing 2 integers. It assumes that the top left hand point coordinates are stored first inside the rectangle, and that both types have compatible memory layouts and byte alignments (a very reasonable assumption, but not guaranteed).

The safest thing to do in C# would be to manually copy the values you want from the Rect to the Point object, e.g.

var point = new Point(rect.x, rect.y);

UPDATE:

A more maintainable option (thanks Sven!):

var point = rect.Location;
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top