powered by simpleCommunicator - 2.0.55     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / FieldOffset + Union, но при этом размер какого-нибудь IntPtr или String может плавать
17 сообщений из 17, страница 1 из 1
FieldOffset + Union, но при этом размер какого-нибудь IntPtr или String может плавать
    #38841147
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Есть структура.
Там Union.
Метод стандартный - в .Net тьфу-тьфу есть такой : <System.Runtime.InteropServices.FieldOffset(4)>
Поясню на конкретном примере.
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
  <StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Unicode)>
  Public Structure DEVMODE
    <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=32)> _
    <System.Runtime.InteropServices.FieldOffset(0)> Dim dmDeviceName As String
    <System.Runtime.InteropServices.FieldOffset(32)> Dim dmSpecVersion As Short
    <System.Runtime.InteropServices.FieldOffset(34)> Dim dmDriverVersion As Short
...юнионы будут дальше


И вижу, что это не работает, а потом понимаю что при SizeConst:=32 и CharSet.Unicode смещение =63 (думаю 32*2-1 байт) а не хрена не 32
А с другой стороны там м.б. CharSet.ANSI или CharSet.Auto то бишь задавая смещение явно, я могу угадать частные случаи, а могу тупо и не попасть.

Аналогично, у меня по дороге до Union могут быть какие-нибудь IntPrt (4 или 8 байт).

Можно ли здесь извернуться универсально, т.е. например задавать смещение не от начала структуры, а от какого то его элемента,
ну хотя бы типа
Код: vbnet
1.
<System.Runtime.InteropServices.FieldOffset(dmDeviceName+2 байта)> Dim dmDriverVersion As Short

?

Простейший вариант, конечно вообще не прописывать Юнионы, а тупо писать "одну из ветвей" Юниона (любую, либо кот. нужна по смыслу задачи). Тогда FieldOffset не нужен.

Но все же...
...
Рейтинг: 0 / 0
FieldOffset + Union, но при этом размер какого-нибудь IntPtr или String может плавать
    #38841149
Фотография Изопропил
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Дмитрий77Можно ли здесь извернуться универсально,
можно
вложить одну структуру в другую
...
Рейтинг: 0 / 0
FieldOffset + Union, но при этом размер какого-нибудь IntPtr или String может плавать
    #38841156
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Изопропил,
не пояснишь кодом. Рука если честно под .Net не очень набита.

Вот так бы хотелось в идеале: (места откуда растут ошибки я выделил (32) и (70), Юнионы тоже выделил).
Данный вариант еще не содержит IntPtr.

Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
  <StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Unicode)>
  Public Structure DEVMODE
    <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=CCHDEVICENAME)> _
    <System.Runtime.InteropServices.FieldOffset(0)> Dim dmDeviceName As String
    <System.Runtime.InteropServices.FieldOffset(32)> Dim dmSpecVersion As Short
    <System.Runtime.InteropServices.FieldOffset(34)> Dim dmDriverVersion As Short
    <System.Runtime.InteropServices.FieldOffset(36)> Dim dmSize As Short
    <System.Runtime.InteropServices.FieldOffset(38)> Dim dmDriverExtra As Short
    <System.Runtime.InteropServices.FieldOffset(40)> Dim dmFields As Integer
    <System.Runtime.InteropServices.FieldOffset(44)> Dim dmOrientation As Short
    <System.Runtime.InteropServices.FieldOffset(46)> Dim dmPaperSize As Short
    <System.Runtime.InteropServices.FieldOffset(48)> Dim dmPaperLength As Short
    <System.Runtime.InteropServices.FieldOffset(50)> Dim dmPaperWidth As Short
    <System.Runtime.InteropServices.FieldOffset(52)> Dim dmScale As Short
    <System.Runtime.InteropServices.FieldOffset(54)> Dim dmCopies As Short
    <System.Runtime.InteropServices.FieldOffset(56)> Dim dmDefaultSource As Short
    <System.Runtime.InteropServices.FieldOffset(58)> Dim dmPrintQuality As Short
    <System.Runtime.InteropServices.FieldOffset(44)> Dim dmPosition As POINTL
    <System.Runtime.InteropServices.FieldOffset(52)> Dim dmDisplayOrientation As Integer
    <System.Runtime.InteropServices.FieldOffset(56)> Dim dmDisplayFixedOutput As Integer
    <System.Runtime.InteropServices.FieldOffset(60)> Dim dmColor As Short
    <System.Runtime.InteropServices.FieldOffset(62)> Dim dmDuplex As Short
    <System.Runtime.InteropServices.FieldOffset(64)> Dim dmYResolution As Short
    <System.Runtime.InteropServices.FieldOffset(66)> Dim dmTTOption As Short
    <System.Runtime.InteropServices.FieldOffset(68)> Dim dmCollate As Short
    <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=CCHFORMNAME)> _
    <System.Runtime.InteropServices.FieldOffset(70)> Dim dmFormName As String
    <System.Runtime.InteropServices.FieldOffset(102)> Dim dmLogPixels As Short
    <System.Runtime.InteropServices.FieldOffset(104)> Dim dmBitsPerPel As Integer
    <System.Runtime.InteropServices.FieldOffset(108)> Dim dmPelsWidth As Integer
    <System.Runtime.InteropServices.FieldOffset(112)> Dim dmPelsHeight As Integer
    <System.Runtime.InteropServices.FieldOffset(116)> Dim dmDisplayFlags As Integer
    <System.Runtime.InteropServices.FieldOffset(116)> Dim dmNup As Integer
    <System.Runtime.InteropServices.FieldOffset(120)> Dim dmDisplayFrequency As Integer
    ' The following only appear in Windows 95, 98, 2000 (WINVER >= 0x0400)
    <System.Runtime.InteropServices.FieldOffset(124)> Dim dmICMMethod As Integer
    <System.Runtime.InteropServices.FieldOffset(128)> Dim dmICMIntent As Integer
    <System.Runtime.InteropServices.FieldOffset(132)> Dim dmMediaType As Integer
    <System.Runtime.InteropServices.FieldOffset(136)> Dim dmDitherType As Integer
    <System.Runtime.InteropServices.FieldOffset(140)> Dim dmReserved1 As Integer
    <System.Runtime.InteropServices.FieldOffset(144)> Dim dmReserved2 As Integer
    ' The following only appear in Windows 2000 (WINVER >= 0x0500) || (_WIN32_WINNT >= 0x0400)
    <System.Runtime.InteropServices.FieldOffset(148)> Dim dmPanningWidth As Integer
    <System.Runtime.InteropServices.FieldOffset(152)> Dim dmPanningHeight As Integer
  End Structure


Ну, по идее для моих тек. целей прокатывает упрощенный вариант:
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
  <StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Unicode)>
  Public Structure DEVMODE
    <MarshalAs(UnmanagedType.ByValTStr, Sizeconst:=CCHDEVICENAME)> Dim pDeviceName As String
    Dim dmSpecVersion As Short
    Dim dmDriverVersion As Short
    Dim dmSize As Short
    Dim dmDriverExtra As Short
    Dim dmFields As Integer
    Dim dmOrientation As Short 'Union-начало
    Dim dmPaperSize As Short
    Dim dmPaperLength As Short
    Dim dmPaperWidth As Short
    Dim dmScale As Short
    Dim dmCopies As Short
    Dim dmDefaultSource As Short
    Dim dmPrintQuality As Short 'Union-конец
    Dim dmColor As Short
    Dim dmDuplex As Short
    Dim dmYResolution As Short
    Dim dmTTOption As Short
    Dim dmCollate As Short
    <MarshalAs(UnmanagedType.ByValTStr, Sizeconst:=CCHFORMNAME)> Dim dmFormName As String
    Dim dmLogPixels As Short
    Dim dmBitsPerPel As Integer
    Dim dmPelsWidth As Integer
    Dim dmPelsHeight As Integer
    Dim dmDisplayFlags As Integer 'Union
    Dim dmDisplayFrequency As Integer
    ' The following only appear in Windows 95, 98, 2000 (WINVER >= 0x0400)
    Dim dmICMMethod As Integer
    Dim dmICMIntent As Integer
    Dim dmMediaType As Integer
    Dim dmDitherType As Integer
    Dim dmReserved1 As Integer
    Dim dmReserved2 As Integer
    ' The following only appear in Windows 2000 (WINVER >= 0x0500) || (_WIN32_WINNT >= 0x0400)
    Dim dmPanningWidth As Integer
    Dim dmPanningHeight As Integer
  End Structure


И в VB6 я всегда поступал именно так.
Но однажды пришлось писать 10+ структур и 10+ деклараций API вместо одной.
Хочется как бы понять новую технологию с .FieldOffset и м.б. еще какие-инструменты есть.
...
Рейтинг: 0 / 0
FieldOffset + Union, но при этом размер какого-нибудь IntPtr или String может плавать
    #38841160
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Изопропил,

ты предлагаешь Юнионы выносить в отдельные структуры и в этих отдельных задавать .FieldOffset? ДА?

А если и в них какие-нибудь IntPtr-ы будут? Например.
...
Рейтинг: 0 / 0
FieldOffset + Union, но при этом размер какого-нибудь IntPtr или String может плавать
    #38841162
Фотография Где-то в степи
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Дмитрий77,
попробуй так, не ручаюсь C#
...
Рейтинг: 0 / 0
FieldOffset + Union, но при этом размер какого-нибудь IntPtr или String может плавать
    #38841163
Фотография Где-то в степи
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Где-то в степи,
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
 [StructLayout(LayoutKind.Sequential)]
    public struct DEVMODE
    {
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
        public string dmDeviceName;
        public short dmSpecVersion;
        public short dmDriverVersion;
        public short dmSize;
        public short dmDriverExtra;
        public int dmFields;
        public short dmOrientation;
        public short dmPaperSize;
        public short dmPaperLength;
        public short dmPaperWidth;
        public short dmScale;
        public short dmCopies;
        public short dmDefaultSource;
        public short dmPrintQuality;
        public short dmColor;
        public short dmDuplex;
        public short dmYResolution;
        public short dmTTOption;
        public short dmCollate;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = GDI.CCHFORMNAME)]
        public string dmFormName;
        public short dmUnusedPadding;
        public int dmBitsPerPel;
        public int dmPelsWidth;
        public int dmPelsHeight;
        public int dmDisplayFlags;
        public int dmDisplayFrequency;
    }
...
Рейтинг: 0 / 0
FieldOffset + Union, но при этом размер какого-нибудь IntPtr или String может плавать
    #38841164
Фотография Изопропил
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
...
Рейтинг: 0 / 0
FieldOffset + Union, но при этом размер какого-нибудь IntPtr или String может плавать
    #38841165
Фотография Где-то в степи
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
по крайней мере это из валидного кода
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
public class DHelper
    {
        [DllImport("user32.dll", CharSet = CharSet.Ansi)]
        public static extern int EnumDisplaySettings(string deviceName, int modeNumber, ref DEVMODE devMode);
    }

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
    public struct DEVMODE
    {
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
        public string dmDeviceName;

        public short dmSpecVersion;
        public short dmDriverVersion;
        public short dmSize;
        public short dmDriverExtra;
        public int dmFields;
        public int dmPositionX;
        public int dmPositionY;
        public int dmDisplayOrientation;
        public int dmDisplayFixedOutput;
        public short dmColor;
        public short dmDuplex;
        public short dmYResolution;
        public short dmTTOption;
        public short dmCollate;

        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
        public string dmFormName;

        public short dmLogPixels;
        public short dmBitsPerPel;
        public int dmPelsWidth;
        public int dmPelsHeight;
        public int dmDisplayFlags;
        public int dmDisplayFrequency;
        public int dmICMMethod;
        public int dmICMIntent;
        public int dmMediaType;
        public int dmDitherType;
        public int dmReserved1;
        public int dmReserved2;
        public int dmPanningWidth;
        public int dmPanningHeight;
    };
...
Рейтинг: 0 / 0
FieldOffset + Union, но при этом размер какого-нибудь IntPtr или String может плавать
    #38841168
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Где-то в степи,

Ваш код для структуры полностью соответствует моему нижнему варианту.
Мой нижний вариант - рабочий, также как и ваш.
Но он не учитывает:
DEVMODE structure
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
  union {
    struct {
      short dmOrientation;
      short dmPaperSize;
      short dmPaperLength;
      short dmPaperWidth;
      short dmScale;
      short dmCopies;
      short dmDefaultSource;
      short dmPrintQuality;
    };
    struct {
      POINTL dmPosition;
      DWORD  dmDisplayOrientation;
      DWORD  dmDisplayFixedOutput;
    };
  };
...
  union {
    DWORD dmDisplayFlags;
    DWORD dmNup;
  };



Мой верхний код "пытается" это делать через известную технику
Код: vbnet
1.
<System.Runtime.InteropServices.FieldOffset...


Но как вы понимаете ошибается на строчке
Код: vbnet
1.
<System.Runtime.InteropServices.FieldOffset(32)> Dim dmSpecVersion As Short


потому что Dim dmDeviceName As String это не 32 а для Юникода 63.
Здесь я могу конечно подтасовать так:
Код: vbnet
1.
<System.Runtime.InteropServices.FieldOffset(63)> Dim dmSpecVersion As Short


Ну и исправить все что ниже.

Но если б у меня там стоял IntPtr (перед Юнионом ) -к примеру,
то я б так сделать не смог (если я рассчитываю на any CPU или хотя бы на 2 версии exe x86 и x64, ну вы меня поняли).
...
Рейтинг: 0 / 0
FieldOffset + Union, но при этом размер какого-нибудь IntPtr или String может плавать
    #38841174
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ну вот так по идее универсальный вариант.
Вроде работает.
Но только при условии
Код: vbnet
1.
  <StructLayout(LayoutKind.Explicit)>


для вложенных структур.
C .Sequential не хочет заполнять вложенные.

Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
  <StructLayout(LayoutKind.Explicit)>
  Public Structure DEVMODE_U1
    <System.Runtime.InteropServices.FieldOffset(0)> Dim dmOrientation As Short
    <System.Runtime.InteropServices.FieldOffset(2)> Dim dmPaperSize As Short
    <System.Runtime.InteropServices.FieldOffset(4)> Dim dmPaperLength As Short
    <System.Runtime.InteropServices.FieldOffset(6)> Dim dmPaperWidth As Short
    <System.Runtime.InteropServices.FieldOffset(8)> Dim dmScale As Short
    <System.Runtime.InteropServices.FieldOffset(10)> Dim dmCopies As Short
    <System.Runtime.InteropServices.FieldOffset(12)> Dim dmDefaultSource As Short
    <System.Runtime.InteropServices.FieldOffset(14)> Dim dmPrintQuality As Short
    <System.Runtime.InteropServices.FieldOffset(0)> Dim dmPosition As POINTL
    <System.Runtime.InteropServices.FieldOffset(8)> Dim dmDisplayOrientation As Integer
    <System.Runtime.InteropServices.FieldOffset(12)> Dim dmDisplayFixedOutput As Integer
  End Structure

  <StructLayout(LayoutKind.Explicit)>
  Public Structure DEVMODE_U2
    <System.Runtime.InteropServices.FieldOffset(0)> Dim dmDisplayFlags As Integer
    <System.Runtime.InteropServices.FieldOffset(0)> Dim dmNup As Integer
  End Structure

  <StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Unicode)>
  Public Structure DEVMODE
    <MarshalAs(UnmanagedType.ByValTStr, Sizeconst:=CCHDEVICENAME)> Dim pDeviceName As String
    Dim dmSpecVersion As Short
    Dim dmDriverVersion As Short
    Dim dmSize As Short
    Dim dmDriverExtra As Short
    Dim dmFields As Integer
    Dim U1 As DEVMODE_U1
    Dim dmColor As Short
    Dim dmDuplex As Short
    Dim dmYResolution As Short
    Dim dmTTOption As Short
    Dim dmCollate As Short
    <MarshalAs(UnmanagedType.ByValTStr, Sizeconst:=CCHFORMNAME)> Dim dmFormName As String
    Dim dmLogPixels As Short
    Dim dmBitsPerPel As Integer
    Dim dmPelsWidth As Integer
    Dim dmPelsHeight As Integer
    Dim U2 As DEVMODE_U2
    Dim dmDisplayFrequency As Integer
    ' The following only appear in Windows 95, 98, 2000 (WINVER >= 0x0400)
    Dim dmICMMethod As Integer
    Dim dmICMIntent As Integer
    Dim dmMediaType As Integer
    Dim dmDitherType As Integer
    Dim dmReserved1 As Integer
    Dim dmReserved2 As Integer
    ' The following only appear in Windows 2000 (WINVER >= 0x0500) || (_WIN32_WINNT >= 0x0400)
    Dim dmPanningWidth As Integer
    Dim dmPanningHeight As Integer
  End Structure


Честно, dm.U1.dmPrintQuality как то не очень смотрится в коде.
Принцип понял, но думаю где на Юнион можно начхать и обойтись без него (зависит от конкретики), и при этом длины типов "плавают" и не разрешают задать offset явно - лучше так и продолжать чхать.
Конкретно с этой структурой мне этот Юнион ни к чему.
...
Рейтинг: 0 / 0
FieldOffset + Union, но при этом размер какого-нибудь IntPtr или String может плавать
    #38841187
Фотография Где-то в степи
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Дмитрий77,
честно сказать удивляет, почему Вы интернетом не пользуетесь, а все постите сюда, и себя убиваете и других
Вам же давали тынцы на это место ранее
http://www.pinvoke.net/default.aspx/Structures/DEVMODE.html
я как дурак, в надежде что там пусто по этой тематике, подпрягся,

Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
 internal class Program
    {
        [DllImport("user32.dll")]
        public static extern bool EnumDisplaySettings(
            string deviceName, int modeNum, ref DEVMODE devMode);

        internal struct POINTL
        {
            public Int32 x;
            public Int32 y;
        }
        [Flags()]
        internal enum DM : int
        {
            Orientation = 0x1,
            PaperSize = 0x2,
            PaperLength = 0x4,
            PaperWidth = 0x8,
            Scale = 0x10,
            Position = 0x20,
            NUP = 0x40,
            DisplayOrientation = 0x80,
            Copies = 0x100,
            DefaultSource = 0x200,
            PrintQuality = 0x400,
            Color = 0x800,
            Duplex = 0x1000,
            YResolution = 0x2000,
            TTOption = 0x4000,
            Collate = 0x8000,
            FormName = 0x10000,
            LogPixels = 0x20000,
            BitsPerPixel = 0x40000,
            PelsWidth = 0x80000,
            PelsHeight = 0x100000,
            DisplayFlags = 0x200000,
            DisplayFrequency = 0x400000,
            ICMMethod = 0x800000,
            ICMIntent = 0x1000000,
            MediaType = 0x2000000,
            DitherType = 0x4000000,
            PanningWidth = 0x8000000,
            PanningHeight = 0x10000000,
            DisplayFixedOutput = 0x20000000
        }


        [StructLayout(LayoutKind.Explicit, CharSet = CharSet.Ansi)]
        public struct DEVMODE
        {
            public const int CCHDEVICENAME = 32;
            public const int CCHFORMNAME = 32;

            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = CCHDEVICENAME)]
            [System.Runtime.InteropServices.FieldOffset(0)]
            public string dmDeviceName;
            [System.Runtime.InteropServices.FieldOffset(32)]
            public Int16 dmSpecVersion;
            [System.Runtime.InteropServices.FieldOffset(34)]
            public Int16 dmDriverVersion;
            [System.Runtime.InteropServices.FieldOffset(36)]
            public Int16 dmSize;
            [System.Runtime.InteropServices.FieldOffset(38)]
            public Int16 dmDriverExtra;
            [System.Runtime.InteropServices.FieldOffset(40)]
            public DM dmFields;

            [System.Runtime.InteropServices.FieldOffset(44)]
            public Int16 dmOrientation;
            [System.Runtime.InteropServices.FieldOffset(46)]
            public Int16 dmPaperSize;
            [System.Runtime.InteropServices.FieldOffset(48)]
            public Int16 dmPaperLength;
            [System.Runtime.InteropServices.FieldOffset(50)]
            public Int16 dmPaperWidth;
            [System.Runtime.InteropServices.FieldOffset(52)]
            public Int16 dmScale;
            [System.Runtime.InteropServices.FieldOffset(54)]
            public Int16 dmCopies;
            [System.Runtime.InteropServices.FieldOffset(56)]
            public Int16 dmDefaultSource;
            [System.Runtime.InteropServices.FieldOffset(58)]
            public Int16 dmPrintQuality;

            [System.Runtime.InteropServices.FieldOffset(44)]
            public POINTL dmPosition;
            [System.Runtime.InteropServices.FieldOffset(52)]
            public Int32 dmDisplayOrientation;
            [System.Runtime.InteropServices.FieldOffset(56)]
            public Int32 dmDisplayFixedOutput;

            [System.Runtime.InteropServices.FieldOffset(60)]
            public short dmColor; // See note below!
            [System.Runtime.InteropServices.FieldOffset(62)]
            public short dmDuplex; // See note below!
            [System.Runtime.InteropServices.FieldOffset(64)]
            public short dmYResolution;
            [System.Runtime.InteropServices.FieldOffset(66)]
            public short dmTTOption;
            [System.Runtime.InteropServices.FieldOffset(68)]
            public short dmCollate; // See note below!
            [System.Runtime.InteropServices.FieldOffset(72)]
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = CCHFORMNAME)]
            public string dmFormName;
            [System.Runtime.InteropServices.FieldOffset(102)]
            public Int16 dmLogPixels;
            [System.Runtime.InteropServices.FieldOffset(104)]
            public Int32 dmBitsPerPel;
            [System.Runtime.InteropServices.FieldOffset(108)]
            public Int32 dmPelsWidth;
            [System.Runtime.InteropServices.FieldOffset(112)]
            public Int32 dmPelsHeight;
            [System.Runtime.InteropServices.FieldOffset(116)]
            public Int32 dmDisplayFlags;
            [System.Runtime.InteropServices.FieldOffset(116)]
            public Int32 dmNup;
            [System.Runtime.InteropServices.FieldOffset(120)]
            public Int32 dmDisplayFrequency;

        }

        private static void Main()
        {
            var vDevMode = new DEVMODE();
            var i = 0;
            while (EnumDisplaySettings(null, i, ref vDevMode))
            {
                Console.WriteLine(vDevMode.dmOrientation);

                i++;
            }
            Console.Read();
        }
    }



больше никогда ((
...
Рейтинг: 0 / 0
FieldOffset + Union, но при этом размер какого-нибудь IntPtr или String может плавать
    #38841196
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Где-то в степи,

Вы не обижайтесь. Но вы вопроса не поняли. Я простых не задаю.
Интернетом я пользуюсь, эти ссылки давно видел и ими/им подобными воспользовался.

DEVMODE был приведен для примера. Еще раз.
Вопрос был: как задавать OffSet-ы если типы в структуре могут иметь разную длину (в зависимости от...)?

Пример 1.

Так правильно
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
        [StructLayout(LayoutKind.Explicit, CharSet = CharSet.Ansi)]
        public struct DEVMODE
        {
            public const int CCHDEVICENAME = 32;
            public const int CCHFORMNAME = 32;

            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = CCHDEVICENAME)]
            [System.Runtime.InteropServices.FieldOffset(0)]
            public string dmDeviceName;
            [System.Runtime.InteropServices.FieldOffset(32)]



А вот так неправильно:
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
        [StructLayout(LayoutKind.Explicit, CharSet = CharSet.Unicode)]
        public struct DEVMODE
        {
            public const int CCHDEVICENAME = 32;
            public const int CCHFORMNAME = 32;

            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = CCHDEVICENAME)]
            [System.Runtime.InteropServices.FieldOffset(0)]
            public string dmDeviceName;
            [System.Runtime.InteropServices.FieldOffset(32)]



Правильно так:
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
        [StructLayout(LayoutKind.Explicit, CharSet = CharSet.Unicode)]
        public struct DEVMODE
        {
            public const int CCHDEVICENAME = 32;
            public const int CCHFORMNAME = 32;

            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = CCHDEVICENAME)]
            [System.Runtime.InteropServices.FieldOffset(0)]
            public string dmDeviceName;
            [System.Runtime.InteropServices.FieldOffset(63)]



А вот так что будете писать?
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
        [StructLayout(LayoutKind.Explicit, CharSet = CharSet.Auto)]
        public struct DEVMODE
        {
            public const int CCHDEVICENAME = 32;
            public const int CCHFORMNAME = 32;

            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = CCHDEVICENAME)]
            [System.Runtime.InteropServices.FieldOffset(0)]
            public string dmDeviceName;
            [System.Runtime.InteropServices.FieldOffset(32?63)]



Пример 2.
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
  HXX x; 
  union {
    struct {
      HYY y;
    };
    struct {
      HZZ z;
    };
  };



Как будете выкручиваться?
Так?
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
[StructLayout(LayoutKind.Explicit]
public struct MYSTRUCT
 [System.Runtime.InteropServices.FieldOffset(0)]
 public IntPtr x;
 [System.Runtime.InteropServices.FieldOffset(4)]
 public IntPtr y;
 [System.Runtime.InteropServices.FieldOffset(4)]
 public IntPtr z;


Или так?
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
[StructLayout(LayoutKind.Explicit]
public struct MYSTRUCT
 [System.Runtime.InteropServices.FieldOffset(0)]
 public IntPtr x;
 [System.Runtime.InteropServices.FieldOffset(8)]
 public IntPtr y;
 [System.Runtime.InteropServices.FieldOffset(8)]
 public IntPtr z;



Один из вариантов так (Изопропил предложил, если правильно его понял):
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
[StructLayout(LayoutKind.Explicit]
public struct MYSTRUCT_U1
 [System.Runtime.InteropServices.FieldOffset(0)]
 public IntPtr y;
 [System.Runtime.InteropServices.FieldOffset(0)]
 public IntPtr z;
...
[StructLayout(LayoutKind.Sequential]
public struct MYSTRUCT
 public IntPtr x;
 public MYSTRUCT_U1 u1;



Но не универсален.
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
  HXX x; //IntPtr
  union {
    struct {
      HYY y; //IntPtr
      HAA a; //IntPtr <<--  здесь наступаем на те же грабли 
   };
    struct {
      HZZ z; //IntPtr
      HBB b; //IntPtr <<--  здесь наступаем на те же грабли 
   };
  };
...
Рейтинг: 0 / 0
FieldOffset + Union, но при этом размер какого-нибудь IntPtr или String может плавать
    #38841306
Фотография Изопропил
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Дмитрий77,

CharSet = CharSet.Auto - не используйте не по назначению
...
Рейтинг: 0 / 0
FieldOffset + Union, но при этом размер какого-нибудь IntPtr или String может плавать
    #38841366
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Изопропил,

Ну, я сейчас придерживаюсь принципа
CharSet = CharSet.Unicode
Declare Unicode Function fun Alias "funW"
хотя в VB6 всегда делал "funA"
ANSI в обязательном порядке требует спецнастройки компа на язык программы, это неудобно.

А вот с Ptr надо предусматривать всегда оба варианта, поэтому это я проверяю четко.
...
Рейтинг: 0 / 0
FieldOffset + Union, но при этом размер какого-нибудь IntPtr или String может плавать
    #38841823
Ilya81
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Если уж использовать FieldOffsetAttribute, наверно лучше LayoutKind ставить не Sequential, а Explicit, а ещё задать размер всей структуры. Смещение не от начала, а от последнего элемента - не находил такого способа.
...
Рейтинг: 0 / 0
FieldOffset + Union, но при этом размер какого-нибудь IntPtr или String может плавать
    #38842112
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ilya81Если уж использовать FieldOffsetAttribute, наверно лучше LayoutKind ставить не Sequential, а Explicit, .
Насколько я понял, для вложенной c FieldOffset Explicit обязательно, иначе она не заполняется данными при PtrToStructure.
Ilya81а ещё задать размер всей структуры.
Это как делается?
...
Рейтинг: 0 / 0
FieldOffset + Union, но при этом размер какого-нибудь IntPtr или String может плавать
    #38842595
Ilya81
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Дмитрий77Насколько я понял, для вложенной c FieldOffset Explicit обязательно, иначе она не заполняется данными при PtrToStructure.
Вот и я о том же.
Дмитрий77Это как делается?
Всё в том ж StructLayoutAttribute параметр Size. Тоже для варианта LayoutKind.Explicit.
...
Рейтинг: 0 / 0
17 сообщений из 17, страница 1 из 1
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / FieldOffset + Union, но при этом размер какого-нибудь IntPtr или String может плавать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]