属性を学んでいてなかなかおもしろいなぁと感じたのでメモる。
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:
コメントを投稿