static RawKeyboardState() { _objectsFormat = new ObjectDataFormat[256]; for (int i = 0; i < _objectsFormat.Length; i++) { _objectsFormat[i] = new ObjectDataFormat(ObjectGuid.Key, i, DeviceObjectTypeFlags.PushButton | DeviceObjectTypeFlags.ToggleButton | DeviceObjectTypeFlags.Optional, ObjectDataFormatFlags.None, i) { Name = "Key" + i }; } }
private unsafe DataFormat GetDataFormat <TRaw>() where TRaw : unmanaged { if (_dataFormat == null) { // Build DataFormat from IDataFormatProvider if (typeof(IDataFormatProvider).IsAssignableFrom(typeof(TRaw))) { var provider = (IDataFormatProvider)(new TRaw()); _dataFormat = new DataFormat(provider.Flags) { DataSize = sizeof(TRaw), ObjectsFormat = provider.ObjectsFormat }; } else { // Build DataFormat from DataFormat and DataObjectFormat attributes IEnumerable <DataFormatAttribute> dataFormatAttributes = typeof(TRaw).GetCustomAttributes <DataFormatAttribute>(false); if (dataFormatAttributes.Count() != 1) { throw new InvalidOperationException( string.Format(System.Globalization.CultureInfo.InvariantCulture, "The structure [{0}] must be marked with DataFormatAttribute or provide a IDataFormatProvider", typeof(TRaw).FullName)); } _dataFormat = new DataFormat(((DataFormatAttribute)dataFormatAttributes.First()).Flags) { DataSize = sizeof(TRaw) }; var dataObjects = new List <ObjectDataFormat>(); IEnumerable <FieldInfo> fields = typeof(TRaw).GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); // Iterates on fields foreach (var field in fields) { IEnumerable <DataObjectFormatAttribute> dataObjectAttributes = field.GetCustomAttributes <DataObjectFormatAttribute>(false); if (dataObjectAttributes.Count() > 0) { int fieldOffset = Marshal.OffsetOf(typeof(TRaw), field.Name).ToInt32(); int totalSizeOfField = Marshal.SizeOf(field.FieldType); int offset = fieldOffset; int numberOfDataObjects = 0; // Count the number of effective sub-field for a field // A field that contains a fixed array should have sub-field for (int i = 0; i < dataObjectAttributes.Count(); i++) { var attr = dataObjectAttributes.ElementAt(i); numberOfDataObjects += attr.ArrayCount == 0 ? 1 : attr.ArrayCount; } // Check that the size of the field is compatible with the number of sub-field // For a simple field without any array element, sub-field = field int sizeOfField = totalSizeOfField / numberOfDataObjects; if ((sizeOfField * numberOfDataObjects) != totalSizeOfField) { throw new InvalidOperationException(string.Format(System.Globalization.CultureInfo.InvariantCulture, "Field [{0}] has incompatible size [{1}] and number of DataObjectAttributes [{2}]", field.Name, (double)totalSizeOfField / numberOfDataObjects, numberOfDataObjects)); } int subFieldIndex = 0; // Iterates on attributes for (int i = 0; i < dataObjectAttributes.Count(); i++) { var attr = dataObjectAttributes.ElementAt(i); numberOfDataObjects = attr.ArrayCount == 0 ? 1 : attr.ArrayCount; // Add DataObjectFormat for (int j = 0; j < numberOfDataObjects; j++) { var dataObject = new ObjectDataFormat( string.IsNullOrEmpty(attr.Guid) ? Guid.Empty : new Guid(attr.Guid), offset, attr.TypeFlags, attr.Flags, attr.InstanceNumber); // Use attribute name or fallback to field's name string name = (string.IsNullOrEmpty(attr.Name)) ? field.Name : attr.Name; name = numberOfDataObjects == 1 ? name : name + subFieldIndex; dataObject.Name = name; dataObjects.Add(dataObject); offset += sizeOfField; subFieldIndex++; } } } } _dataFormat.ObjectsFormat = dataObjects.ToArray(); } for (int i = 0; i < _dataFormat.ObjectsFormat.Length; i++) { var dataObject = _dataFormat.ObjectsFormat[i]; // Map field name to object if (_mapNameToObjectFormat.ContainsKey(dataObject.Name)) { throw new InvalidOperationException(string.Format(System.Globalization.CultureInfo.InvariantCulture, "Incorrect field name [{0}]. Field name must be unique", dataObject.Name)); } _mapNameToObjectFormat.Add(dataObject.Name, dataObject); } // DumpDataFormat(_dataFormat); } return(_dataFormat); }