如何修复警告 CA1900:成员 "X" 包含以下不可移植字段

How to fix Warning CA1900: Member "X" contains the following non-portable fields

我的 DevMode 结构的字段 PositionFormName 标有 CA1900 代码分析警告。

这似乎是一个危险的结构,在定义中稍作更改会产生很多问题并停止按预期工作(请参阅上面这些网址中的用户评论),所以我不知道具体如何调整上述字段以在 32 位和 64 位 Windows.

中按预期工作

如何使那些标记的字段可移植?

DevMode 结构(只是对 pinvoke.net 中发布的 C# 代码进行少量改编的翻译):

<DebuggerStepThrough>
<StructLayout(LayoutKind.Explicit)>
Public Structure DevMode

    Public Const CchDeviceName As Integer = 32
    Public Const CchFormName As Integer = 32

    <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=CchDeviceName)>
    <FieldOffset(0)>
    Public DeviceName As String

    <FieldOffset(32)>
    Public SpecVersion As Short

    <FieldOffset(34)>
    Public DriverVersion As Short

    <FieldOffset(36)>
    Public Size As Short

    <FieldOffset(38)>
    Public DriverExtra As Short

    <FieldOffset(40)>
    Public Fields As DeviceModeFields

    <FieldOffset(44)>
    Public Orientation As Short

    <FieldOffset(46)>
    Public PaperSize As Short

    <FieldOffset(48)>
    Public PaperLength As Short

    <FieldOffset(50)>
    Public PaperWidth As Short

    <FieldOffset(52)>
    Public Scale As Short

    <FieldOffset(54)>
    Public Copies As Short

    <FieldOffset(56)>
    Public DefaultSource As Short

    <FieldOffset(58)>
    Public PrintQuality As Short

    <FieldOffset(44)>
    Public Position As Win32.Types.Point

    <FieldOffset(52)>
    Public DisplayOrientation As DeviceModeDisplayOrientation

    <FieldOffset(56)>
    Public DisplayFixedOutput As Integer

    <FieldOffset(60)>
    Public Color As Short

    <FieldOffset(62)>
    Public Duplex As Short

    <FieldOffset(64)>
    Public YResolution As Short

    <FieldOffset(66)>
    Public TTOption As Short

    <FieldOffset(68)>
    Public Collate As Short

    <FieldOffset(72)>
    <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=CchFormName)>
    Public FormName As String

    <FieldOffset(102)>
    Public LogPixels As Short

    <FieldOffset(104)>
    Public BitsPerPixel As Integer

    <FieldOffset(108)>
    Public PixelsWidth As Integer

    <FieldOffset(112)>
    Public PixelsHeight As Integer

    <FieldOffset(116)>
    Public DisplayFlags As Integer

    <FieldOffset(116)>
    Public Nup As Integer

    <FieldOffset(120)>
    Public DisplayFrequency As Integer

End Structure

结构:

<DebuggerStepThrough>
<StructLayout(LayoutKind.Sequential)>
Public Structure Point

    Public X As Integer
    Public Y As Integer

    Public Sub New(ByVal x As Integer, ByVal y As Integer)
        Me.X = x
        Me.Y = y
    End Sub

    Public Sub New(ByVal pt As System.Drawing.Point)
        Me.New(pt.X, pt.Y)
    End Sub

    Public Shared Widening Operator CType(ByVal pt As Point) As System.Drawing.Point
        Return New System.Drawing.Point(pt.X, pt.Y)
    End Operator

    Public Shared Widening Operator CType(ByVal pt As System.Drawing.Point) As Point
        Return New Point(pt.X, pt.Y)
    End Operator

End Structure

更新

这是原来的成员声明:

这是我按照@David Heffernan 的建议尝试过的方法,但是我做错了一些事情,因为当我在某些 winApi 函数中测试它时,该结构不再起作用。

我做错了什么?。如何最终解决这个问题?

<StructLayout(LayoutKind.Sequential)>
Public Structure DevMode

    Private Const CchDeviceName As Integer = 32
    Private Const CchFormName As Integer = 32

    <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=CchDeviceName)> 
    Public DeviceName As String
    Public SpecVersion As Short
    Public DriverVersion As Short
    Public Size As Short
    Public DriverExtra As Short
    Public Fields As DeviceModeFields
    Public test1 As UnionDevMode1
    Public test2 As UnionDevMode2
    Public Color As Short
    Public Duplex As Short
    Public YResolution As Short
    Public TTOption As Short
    Public Collate As Short
    <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=CchFormName)> 
    Public FormName As String
    Public LogPixels As Short
    Public BitsPerPixel As Integer
    Public PixelsWidth As Integer
    Public PixelsHeight As Integer
    Public test3 As UnionDevMode3
    Public DisplayFrequency As Integer
    Public IcmMethod As Integer
    Public IcmIntent As Integer
    Public MediaType As Integer
    Public DitherType As Integer
    Public Reserved1 As Integer
    Public Reserved2 As Integer
    Public PanningWidth As Integer
    Public PanningHeight As Integer

End Structure

<StructLayout(LayoutKind.Explicit)>
Public Structure UnionDevMode1

    <FieldOffset(0)> Public Orientation As Short
    <FieldOffset(0)> Public PaperSize As Short
    <FieldOffset(0)> Public PaperLength As Short
    <FieldOffset(0)> Public PaperWidth As Short
    <FieldOffset(0)> Public Scale As Short
    <FieldOffset(0)> Public Copies As Short
    <FieldOffset(0)> Public DefaultSource As Short
    <FieldOffset(0)> Public PrintQuality As Short

End Structure

<StructLayout(LayoutKind.Explicit)>
Public Structure UnionDevMode2

    <FieldOffset(0)> Public Position As Win32.Types.Point
    <FieldOffset(0)> Public DisplayOrientation As DeviceModeDisplayOrientation
    <FieldOffset(0)> Public DisplayFixedOutput As Integer

End Structure

<StructLayout(LayoutKind.Explicit)>
Public Structure UnionDevMode3

    <FieldOffset(0)> Public DisplayFlags As Integer
    <FieldOffset(0)> Public Nup As Integer

End Structure

更新2

只是我尝试过的其他方式没有成功...

<StructLayout(LayoutKind.Sequential)>
Public Structure DevMode

    Private Const CchDeviceName As Integer = 32
    Private Const CchFormName As Integer = 32

    <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=CchDeviceName)>
    Public DeviceName As String
    Public SpecVersion As Short
    Public DriverVersion As Short
    Public Size As Short
    Public DriverExtra As Short
    Public Fields As DeviceModeFields
    Public test1 As UnionDevMode1
    Public Color As Short
    Public Duplex As Short
    Public YResolution As Short
    Public TTOption As Short
    Public Collate As Short
    <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=CchFormName)>
    Public FormName As String
    Public LogPixels As Short
    Public BitsPerPixel As Integer
    Public PixelsWidth As Integer
    Public PixelsHeight As Integer
    Public test3 As UnionDevMode3
    Public DisplayFrequency As Integer
    Public IcmMethod As Integer
    Public IcmIntent As Integer
    Public MediaType As Integer
    Public DitherType As Integer
    Public Reserved1 As Integer
    Public Reserved2 As Integer
    Public PanningWidth As Integer
    Public PanningHeight As Integer

End Structure

<StructLayout(LayoutKind.Explicit)>
Public Structure UnionDevMode1

    <FieldOffset(0)>
    Public subUnion1 As SubUnionDevMode1

    <FieldOffset(0)>
    Public subUnion2 As SubUnionDevMode2

End Structure

<StructLayout(LayoutKind.Sequential)>
Public Structure SubUnionDevMode1

    Public Orientation As Short
    Public PaperSize As Short
    Public PaperLength As Short
    Public PaperWidth As Short
    Public Scale As Short
    Public Copies As Short
    Public DefaultSource As Short
    Public PrintQuality As Short

End Structure

<StructLayout(LayoutKind.Sequential)>
Public Structure SubUnionDevMode2

    Public Position As Win32.Types.Point
    Public DisplayOrientation As DeviceModeDisplayOrientation
    Public DisplayFixedOutput As Integer

End Structure

<StructLayout(LayoutKind.Explicit)>
Public Structure UnionDevMode3

    <FieldOffset(0)> Public DisplayFlags As Integer
    <FieldOffset(0)> Public Nup As Integer

End Structure

终于解决了,感谢@David Heffernan 和公司的帮助...

我发现(幸运的是)让我疯狂地让结构工作的一件事是,如果 CharSet 属性设置为 Auto 然后结构停止工作,因为无论什么原因。

在使用 DEVMODE 结构的函数中,也应设置 Ansi 字符集(如 EnumDisplaySettingsChangeDisplaySettingsEx 等),否则该结构在我的情况下将不起作用,不仅仅是得到错误的字符,我的意思是其他字段也会出错。

下面是工作代码,或者至少它似乎按预期工作。所有偏移量都是等效的,结构的大小与原始大小一样为 156,至少在我的 Windows.

中是这样
<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Ansi)>
Public Structure DevMode

    <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=32)>
    Public DeviceName As String
    Public SpecVersion As Short
    Public DriverVersion As Short
    Public Size As Short
    Public DriverExtra As Short
    Public Fields As Integer
    Public Mode As DeviceMode
    Public Color As Short
    Public Duplex As Short
    Public YResolution As Short
    Public TTOption As Short
    Public Collate As Short
    <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=32)>
    Public FormName As String
    Public LogPixels As Short
    Public BitsPerPixel As Integer
    Public PixelsWidth As Integer
    Public PixelsHeight As Integer
    Public Flags As DeviceFlags
    Public DisplayFrequency As Integer
    Public IcmMethod As Integer
    Public IcmIntent As Integer
    Public MediaType As Integer
    Public DitherType As Integer
    Public Reserved1 As Integer
    Public Reserved2 As Integer
    Public PanningWidth As Integer
    Public PanningHeight As Integer

End Structure

<StructLayout(LayoutKind.Explicit)>
Public Structure DeviceMode

    <FieldOffset(0)> Public PrinterDevMode As PrinterDevMode
    <FieldOffset(0)> Public DisplayDevMode As DisplayDevMode

End Structure

<StructLayout(LayoutKind.Explicit)>
Public Structure DeviceFlags

    <FieldOffset(0)> Public DisplayFlags As Integer
    <FieldOffset(0)> Public Nup As Integer

End Structure

<StructLayout(LayoutKind.Sequential)>
Public Structure PrinterDevMode

    Public Orientation As Short
    Public PaperSize As Short
    Public PaperLength As Short
    Public PaperWidth As Short
    Public Scale As Short
    Public Copies As Short
    Public DefaultSource As Short
    Public PrintQuality As Short

End Structure

<StructLayout(LayoutKind.Sequential)>
Public Structure DisplayDevMode

    Public Position As Win32.Types.Point ' 8 bytes.
    Public DisplayOrientation As Integer
    Public DisplayFixedOutput As Integer

End Structure