Доступ к элементам структуры Win32 C / C++ из C#

Я перехватываю вызовы Win32 API, которые выполняет собственная dll или exe из C#, используя какой-то перехват. В данном конкретном случае меня интересует 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). Чтобы иметь доступ к членам этой структуры, я объявил это в моем коде C# ...

[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. Я точно знаю, что это неверно. Но после бесчисленных часов поиска в Google и множества разных вещей я не смог заставить эту простую вещь работать.

Вещи, которые я пробовал:

  • Использование разных примитивов для членов RECT (int, long, short, UInt32 ...). На самом деле очевидно, что это не проблема типа, потому что в любом случае я должен видеть некоторые искаженные числа, а не 0.
  • Удаление модификатора ref. Это также глупо (отчаянные времена, отчаянные меры), потому что rect.left правильно возвращает указатель на rect вместо его значения.
  • Пробовал блоки кода unsafe. Не сработало, но, возможно, я ошибся в реализации (не помню, что сделал). Кроме того, этот подход обычно зарезервирован для сложных ситуаций с указателями в COM и Win32, в любом случае для меня это излишний.
  • Пытался добавить [MarshallAs] перед участниками RECT. Без разницы.
  • Поигрался со значениями Pack. Нет разницы.

Я почти уверен, что мне не хватает чего-то очень простого и понятного, но я понятия не имею, что это такое ...

Любая помощь приветствуется. Спасибо.

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
5
0
6 058
3

Ответы 3

Я заметил, что вы сказали, что пробовали [MarshallAs], но пробовали ли вы [MarshalAs(UnmanagedType.Struct)]?

Частично проблема заключается в использовании String там, где следует использовать StringBuilder.

Попробуйте эту подпись (создана с помощью Помощник по взаимодействию PInvoke)


[System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
public struct tagRECT {

    /// LONG->int
    public int left;

    /// LONG->int
    public int top;

    /// LONG->int
    public int right;

    /// LONG->int
    public int bottom;
}

public partial class NativeMethods {

    /// Return Type: int
    ///hdc: HDC->HDC__*
    ///lpchText: LPCWSTR->WCHAR*
    ///cchText: int
    ///lprc: LPRECT->tagRECT*
    ///format: UINT->unsigned int
    [System.Runtime.InteropServices.DllImportAttribute("user32.dll", EntryPoint = "DrawTextW")]
public static extern  int DrawTextW([System.Runtime.InteropServices.InAttribute()] System.IntPtr hdc, [System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.LPWStr)] System.Text.StringBuilder lpchText, int cchText, ref tagRECT lprc, uint format) ;

}

Почему PInvoke Interop Assistant называет struct tagRECT, а не ust RECT?

xx77aBs 17.11.2013 17:04

Другие вопросы по теме