Я перехватываю вызовы Win32 API, которые родная dll или exe делает из С#, используя какую-то перехватку. В данном конкретном случае меня интересует DrawText() в user32.dll. В Win32 API это объявлено так:
INT WINAPI DrawTextW(HDC hdc, LPCWSTR str, INT count, LPRECT rect, UINT flags)
Структура LPRECT имеет следующую подпись (также в Win32 API):
typedef struct tagRECT {
LONG left;
LONG top;
LONG right;
LONG bottom;
} RECT LPRECT;
LONG - это typedef для 32-битных целых чисел в 32-битных системах (не знаю о 64-битных системах, на данный момент это не имеет значения, потому что я работаю в 32-битной Windows). Чтобы иметь доступ к членам этой структуры, я объявил ее в своем коде С#...
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct RECT
{
public Int32 left;
public Int32 top;
public Int32 right;
public Int32 bottom;
}
... и написал подпись P/Invoke, используя эту структуру RECT:
[DllImport("user32.dll", CharSet = CharSet.Unicode, SetLastError = true, CallingConvention = CallingConvention.StdCall)]
static extern IntPtr DrawText(IntPtr HDC, String str, Int32 count, ref RECT rect, UInt32 flags, IntPtr dtp);
Поскольку структуры в C# являются типами значений, а не ссылочными типами, как в C/C++, здесь необходим модификатор ref.
Однако, когда я использую rect.top rect.left
и т. д., они почти всегда возвращают 0. Я точно знаю, что это неверно. Но после бесчисленных часов гугления и перепробования множества разных вещей я не смог заставить эту простую вещь работать.
Что я пробовал:
- Использование различных примитивов для элементов RECT (int, long, short, UInt32...). На самом деле довольно очевидно, что это не проблема типа, потому что в любом случае я должен видеть какие-то искаженные числа, а не 0.
- Удаление модификатора ref. Это тоже глупо (отчаянные времена, отчаянные меры), потому что rect.left корректно возвращает указатель на rect вместо его значения.
- Пробовал
unsafe
кодовых блоков. Не сработало, но, возможно, я допустил ошибку в реализации (я не помню, что я сделал). Помимо того, что этот подход обычно зарезервирован для сложных ситуаций с указателем в COM и Win32, в любом случае это излишество для моего случая. - Пробовал добавлять
[MarshallAs]
перед членами RECT. Без разницы. - Поиграл со значениями
Pack
. Нет разницы.
Я совершенно уверен, что мне не хватает чего-то очень простого и простого, но я понятия не имею, что это такое...
Любая помощь приветствуется. Спасибо.