Serializando um ícone

Madrugada de sexta-feira, 04:35am.

Posso ouvir os despertadores tocando nos apartamentos vizinhos e as pessoas saindo para trabalhar e eu me pergunto: O que diabos eu estou fazendo acordado?!?

A Resposta é simples, como todo bom nerd, quando colocamos alguma coisa na cabeça não descansamos até que ela esteja funcionando (a coisa, não a cabeça).
Pois bem a mais ou menos a umas 5 horas atrás eu resolvi que uma maldita classe minha teria propriedade do tipo System.Drawing.Icon. Isso mesmo, uma simples figurinha, inofensiva aos olhos dos descuidados mas alguém ai já tentou serializar esse ícone para um XML? Isso é mais difícil do que pensei, e antes que alguém me chame de burro deixe eu explicar a situação.

Eu não queria apenas serializar o ícone, queria faze-lo sem perda de qualidade e mais importante do que isso, sem perder a transparência da figura... e meus amigos, eu consegui Há.

Funciona da seguinte maneira, imagine a seguinte classe

   1:  [Serializable()]


   2:  class Person


   3:  {


   4:     private string _name;


   5:     private Icon _icon;


   6:   


   7:     public string Nome { get; set; }


   8:     public Icon PersonIcon { get; set; }


   9:  }




1. Marque a sua propriedade PersonIcon com o atributo [XmlIgnoreAttribute()] dessa forma ela não será serializada;



2. Crie uma nova propriedade chamada IconByteArray, esta sim será serializada;



    public byte[] IconByteArray { get; set; }



Implementando agora o Get da propriedade:




   1:  if (!object.ReferenceEquals(this._icon, null))


   2:  {


   3:      //Converto pra Bitmap primeiro...


   4:      TypeConverter converter = TypeDescriptor.GetConverter(typeof(Icon));


   5:      if (converter.CanConvertTo(typeof(Bitmap)))


   6:      {


   7:          Bitmap b = (Bitmap)converter.ConvertTo(this._icon, typeof(Bitmap));


   8:   


   9:          // Criamos um MemoryStram para guardar os bytes


  10:          using (MemoryStream ms = new MemoryStream())


  11:          {


  12:   


  13:              // Salvando os bytes no stream e IMPORTANTE


  14:              // marcando o formato como PNG assim garantimos a transparencia do icone


  15:              b.Save(ms, ImageFormat.Png);


  16:              return ms.ToArray();


  17:          }


  18:      }


  19:      else


  20:          return new byte[] { };


  21:  }


  22:  else


  23:      return new byte[]{};



E por fim, implementamos o Set da propriedade IconByteArray:




   1:  if (!object.ReferenceEquals(value, null))


   2:  {


   3:      // Lendo os bytes do XML e criando o Bitmap denovo.


   4:      Bitmap b = (Bitmap)Image.FromStream(


   5:          new MemoryStream(value),true,true);


   6:   


   7:      // Pegamos o ponteiro (handle) para o Bitmap que acabamos de criar


   8:      IntPtr HIcon = b.GetHicon();


   9:   


  10:      // Com base no handle criamos nosso icone e clonamos ele


  11:      // IMPORTANTE - Clonamos o icone para não ficarmos presos ao handle e para


  12:      //podermos libera-lo sem problemas pro SO


  13:      this._icon = (Icon)Icon.FromHandle(HIcon).Clone();


  14:   


  15:      // Liberando o Handle para o sistema operacioal...


  16:      SysImageList.DestroyIcon(HIcon);


  17:  }




 


Lembrando que para poder usar a função DestryIcon(IntPtr) precisamos importar uma API do Windows, para isso basta declarar no seu código:




   1:  [DllImport("user32.dll")]


   2:  public static extern int DestroyIcon(IntPtr hIcon); 




E agora eu posso ir dormir sussegado ;)


0  :

Postar um comentário