Приведение System.Windows.Rect к System.Windows.Point - PullRequest
2 голосов
/ 29 февраля 2012

Я хочу преобразовать этот код C ++ в C #:

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

Но я не знаю, как преобразовать:

reinterpret_cast<LPPOINT>(&rcCurrent)

Как преобразовать System.Windows.Rect в System.Windows.Point?

Ответы [ 2 ]

5 голосов
/ 29 февраля 2012

Ого, это настоящее злоупотребление reinterpret_cast!Код в основном говорит: возьмите указатель на раздел памяти, содержащий 4 целых числа, и представьте, что это фактически указатель на раздел памяти, содержащий 2 целых числа.Предполагается, что координаты верхней левой точки сохраняются первыми внутри прямоугольника и что оба типа имеют совместимые макеты памяти и байтовые выравнивания (очень разумное предположение, но не гарантируется).

Самое безопасное, что можно сделать вC # будет вручную копировать нужные значения из Rect в объект Point, например,

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

ОБНОВЛЕНИЕ:

Более поддерживаемый вариант(спасибо Свен!):

var point = rect.Location;
3 голосов
/ 29 февраля 2012
RECT rcCurrent; ::GetWindowRect ( hwndChild, &rcCurrent );
::MapWindowPoints ( NULL, hWnd, reinterpret_cast<LPPOINT>(&rcCurrent), 2);

Что этот код делает, так это получает ограничивающий прямоугольник (rcCurrent) дочернего окна (hwndChild) относительно клиентской области предположительно родительского окна (hWnd) - или определяет, где дочернее окно находится внутри егородитель.

Первая строка получает полный прямоугольник дочернего элемента, границ и всего, но возвращается в экранных координатах.

Вторая строка отображает эти точки из экранных координат (обозначается первой NULLПараметр) к координатам относительно клиентской области hWnd.

У Win32 нет вызова «получить местоположение внутри родителя», поэтому это ближайший окольный эквивалент.

Что такое приведениездесь используется преимущество того факта, что Win32 RECT имеет точную ту же схему памяти, что и два параллельных POINT, поэтому вызов MapWindowPoints с cPoints = 2 отобразит целый RECT за один раз.Это использование на самом деле задокументировано в MSDN , и даже получает специальную обработку в режимах зеркального отображения справа налево, чтобы гарантировать, что целые прямоугольники отображаются правильно при сопоставлении с рабочего стола слева направо с правым расположением.-второе приложение, и наоборот!(Если вы не планируете использовать зеркальное отображение R-to-L, чтобы локализованные версии ваших приложений могли работать на иврите или арабском языке, вам не нужно об этом беспокоиться.)

-

Правильный способ перевести это на C # зависит от того, откуда вы начинаете и чего пытаетесь достичь.Если вы конвертируете приложение оптом из C ++ в C #, и у вас есть производные от Control объекты для родителя и потомка, вы можете просто использовать child.Location , чтобы получить позицию относительно родителя.

-

С другой стороны, если вы переносите код, который написан в терминах HWND и должен оставаться таким даже при переносе в C # (например, потому что он работает против HWND издругой процесс или не знает, что лежит в основе HWND), тогда лучше всего было бы определить версии RECT и POINT для P / Invoke, а главное здесь - определить версию MapWindowPoints для P / Invoke, которая будет работатьна RECT.(Я предполагаю, что вы немного знакомы с 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 (всегда передавая cPoints как 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 #исходного вызова C ++ MapWindowPoints.

...