带数组的结构和数组映射如下
[StructLayout(LayoutKind.Explicit, Size = 24)]
public unsafe struct TestData
{
[FieldOffset(0)]
public ushort Data1;
[FieldOffset(2)]
public ushort Data2;
[FieldOffset(4)]
public uint Data3;
[FieldOffset(8)]
public fixed byte Data5[16];
}
//或使用以下方法直接和C语言Data5[1]一样访问
[StructLayout(LayoutKind.Explicit, Size = 24)]
public unsafe class TestData
{
[FieldOffset(0)]
public ushort Data1;
[FieldOffset(2)]
public ushort Data2;
[FieldOffset(4)]
public uint Data3;
[FieldOffset(8)]
private byte _data5;
public byte* Data5
{
get
{
fixed(byte* p = &_data5)
{
return p;
}
}
}
}
数组和类转换,字节对齐,位域和共用体
需要启用不安全代码选项
[StructLayout(LayoutKind.Explicit, Size = 17)]
public class TestClass
{
[FieldOffset(0)]
public ushort Data1;
[FieldOffset(2)]
public ushort Data2;
[FieldOffset(4)]
public uint Data3;
[FieldOffset(8)]
public byte Data5;
//下面模拟位域
[FieldOffset(9)]
private ulong data;
public byte Data6
{
get => (byte)(data);
set
{
data &= (~((ulong)0xFF));
data |= value;
}
}
public ushort Data7
{
get => (ushort)(data >> 8);
set
{
data &= (~((ulong)0xFFFF00));
data |= ((ulong)value << 8);
}
}
public ushort Data8
{
get => (ushort)(data >> 24);
set
{
data &= (~((ulong)0xFFFF000000));
data |= ((ulong)value << 24);
}
}
public uint Data9
{
get => (uint)(data >> 40);
set
{
data &= (ulong)0xFFFFFFFFFF;
data |= ((ulong)value << 40);
}
}
}
/// <summary>
/// 将数组转为对象
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="bytes"></param>
/// <returns></returns>
public static T BytesToStructure<T>(byte[] bytes)
{
unsafe
{
fixed (byte* ptr = &bytes[0])
{
return Marshal.PtrToStructure<T>((IntPtr)ptr);
}
}
}
/// <summary>
/// 将对象转为数组
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="obj"></param>
/// <returns></returns>
public static byte[] StructureToByte<T>(T obj)
{
byte[] data = new byte[Marshal.SizeOf(obj)];
unsafe
{
fixed (byte* ptr = &data[0])
{
Marshal.StructureToPtr<T>(obj, (IntPtr)ptr, false);
return data;
}
}
}
DateTime和Uinx时间戳互转:
//时间戳转DateTime
int tick = 1693967222;
DateTime dateTime = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
dateTime = dateTime.AddSeconds(tick).ToLocalTime();
//转时间戳
TimeSpan t = (DateTime.UtcNow - new DateTime(1970, 1, 1));
int tick = (int)t.TotalSeconds;
数值转字符串:
转16进制显示:
//X表示16进制,8表示固定8位不够补0
lbl.Text = "0x" + _Value.ToString("X8");
转2进制:
//2表示转2进制,32表示固定32位,不够补最后一个参数'0',同样可以使用此方法转16进制
return "0b" + Convert.ToString(_Value, 2).PadLeft(32, '0');
添加路径方法:
拖拽添加:先将TextBox的AllowDrag属性设置为true,然后添加下面两个事件
private void textBox1_DragEnter(object sender, DragEventArgs e)
{
if (e.Data.GetDataPresent(DataFormats.FileDrop))
e.Effect = DragDropEffects.Copy;
else
e.Effect = DragDropEffects.None;
}
private void textBox1_DragDrop(object sender, DragEventArgs e)
{
textBox1.Text = ((Array)e.Data.GetData(DataFormats.FileDrop)).GetValue(0).ToString();
}
点击按钮添加:使用OpenFileDialog
private void btnOpenFile_Click(object sender, EventArgs e)
{
if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
textBox1.Text = openFileDialog1.FileName;
}
}
弹窗提示:
使用MessageBox类,MessageBox.Show(“参数错误”),Show函数有多个重载实现,可以添加按钮和图标。
异步等待超时:
可以用下面方法实现一个等待超时检测
TaskCompletionSource<int> taskCompletion;
private void PortDataRecvThread()//接收线程
{
int dat = port.ReadByte();
if(dat == 0x55)
{
taskCompletion.TrySetResult(0);
}
}
private async Task<int> SendAsync()
{
port.WriteLine("12345");
taskCompletion = new TaskCompletionSource<int>();
using (var cts = new CancellationTokenSource(1000))//1秒后释放
{
cts.Token.Register(state =>
{
((TaskCompletionSource<int>)(state)).TrySetResult(1);
}, taskCompletion);
int result = await taskCompletion.Task;
return result;
}
```}
DataGridView控件:
如果想DataGridView控件的数据源想绑定到List中并且表格中的数据随着List中的数据实时改变,可以使用BindingList代替List,数据类继承INotifyPropertyChanged接口实现接口。
```csharp
private int _Value;
public string Value
{
set
{
if(_Value != value)
{
_Value = value;
NotifyPropertyChanged();
}
}
get
{
return _Value;
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
单元格内自动换行:
设置AutoSizeRowsMode属性为AllCells
设置RowsDefaultCellStyle样式属性中的WrapMode属性为true