属性を学んでいてなかなかおもしろいなぁと感じたのでメモる。
StructLayoutとFieldOffsetを使用すると便利なモノができるようだ。
StructLayout - クラスまたは構造体のデータ フィールドの物理的なレイアウトを制御できる。
FieldOffset - フィールドの物理的な位置を示す。
StructLayout属性でレイアウトの種類を指定して、FieldOffset属性で先頭からの距離をバイト単位で指定することになる。
下記の例ではbyte型のAlpha、Red、Green、Blueの計4つのフィールド、つまり4バイトの構造体を作成している。
[StructLayout(LayoutKind.Explicit)]
struct ARGBColor
{
[FieldOffset(3)] public byte Alpha;
[FieldOffset(2)] public byte Red;
[FieldOffset(1)] public byte Green;
[FieldOffset(0)] public byte Blue;
[FieldOffset(0)] public uint Argb;
}
Alpha、Red、Green、Blueフィールドでは1バイトのデータにアクセスする。Argbフィールドでは4バイトのデータにアクセスする。Argbに値を設定するとAlpha、Red、Green、Blueのそれぞれに値が設定される。またその逆に
Alpha、Red、Green、Blueのそれぞれに値を設定するとArgb値も当然変化する。すごく便利だ(^-^)
欲を言えば、
public int Rgbとして、Alphaを省いたRGB値も取得できたらもっと良かったのだが、どうもうまくいかない(-_-;)色を16進数で表す場合「ARGB」つまり、「
Alpha、Red、Green、Blue」の順番となるので、FieldOffset属性に設定する値でその順番を間違えないように気を付けたい。Example
ARGBColor color = new ARGBColor();
color.Argb = 0x8033ff;
FieldInfo[] fields = color.GetType()
.GetFields(BindingFlags.Instance | BindingFlags.Public);
Console.WriteLine("{0,-6} {1,12}{2,12}", "Name", "hex", "int");
foreach (FieldInfo field in fields)
{
Console.WriteLine("{0,-6}:{1,12}{2,12}",
field.Name,
Convert.ToString(Convert.ToInt64(field.GetValue(color)), 16),
field.GetValue(color));
}
color.Alpha = 0xff;
color.Red = 0x33;
color.Green = 0x66;
color.Blue = 0x99;
Console.WriteLine("\n{0,-6} {1,12}{2,12}", "Name", "hex", "int");
foreach (FieldInfo field in fields)
{
Console.WriteLine("{0,-6}:{1,12}{2,12}",
field.Name,
Convert.ToString(Convert.ToInt64(field.GetValue(color)), 16),
field.GetValue(color));
}
Output
Name hex int Alpha : 0 0 Red : 80 128 Green : 33 51 Blue : ff 255 Argb : 8033ff 8401919 Name hex int Alpha : ff 255 Red : 33 51 Green : 66 102 Blue : 99 153 Argb : ff336699 4281558681





0 Comments:
コメントを投稿