Anda di halaman 1dari 8

Colabora.

NET: Botones Personalizados

http://www.elguille.info/colabora/NET2005/ewing_boton_personalizad...

el Guille, la Web del Visual Basic, C#, .NET y ms...


Lo+ - WinFX - .NET - ADO.NET - ASP.NET - Cmo... - Colabora - VB6 - API - HTML Vista - Links - Foros

[Formas con diseo avanzado]


Fecha: 24/May/2005 (17-Mayo-2005) Autor: Ewing Morales (ewingmarx@yahoo.com)

Las ofertas del Guille para alojamiento (hosting) de sitios web, seguramente los mejores precios del

Seguramente alguna vez has intentado darle un toque personal a tus aplicaciones con botones personalizados ya sea con imgenes o solo dndoles una forma no convencional, pero claro, te has topado con la restricciones de Windows para estos casos, y al final has escogi alguna de las opciones mas comunes, a un botn le agregas una imagen o creas tu propio botn en base a imgenes superpuestas, pero ambas aunque no quieras aceptarlo tienen el mismo problema, el rea activa siempre es RECTANGULAR. Pero el reinado de las formas rectangulares ha llegado a su fin, y ahora podrs agregar botones de cualquier forma a tus formularios. Pero no solo es apariencia, la respuesta a los eventos del mouse solamente ocurren dentro la forma del botn, no en la clsica rea rectangular. Clsica? Claro, si tienes algn tema de Win XP comprueba acercando cuidadosamente tu mouse a alguno de los botones de Windows e identifica el rea por ti mismo. Por si no lo sabes, esta es la segunda parte de la entrega de interfaces avanzadas: La primera les mostrara como hacer que las aplicaciones se vean como uno quiere y no como Windows puede (chcalo ac). La segunda mostrara como hacer un botn realmente personalizado por medio de una imagen.

[Segunda Parte] Botones personalizados


Les quiero mostrar una aplicacin final que utiliza estos botones, en la imagen, algunos ejemplos de botones que se pueden crear no estn atenuados:

1 de 8

19/06/2012 8:31

Colabora.NET: Botones Personalizados

http://www.elguille.info/colabora/NET2005/ewing_boton_personalizad...

Muy bien, pero como hacerlo? Primero que nada vamos a ver como crear un control personal (por si aun no sabes crearlo) y en paralelo estaremos aprendiendo como hacerlo personalizado.

Descripcin de componentes
1) Primero necesitamos definir un botn predeterminado que se va a pintar por omisin cuando agregues este control a un formulario. Aunque aqu se muestran como una sola imagen, la idea es crear cuatro imgenes del mismo tamao que permitan presentar al botn en sus tres estados (cuando el mouse esta fuera de el, cuando esta sobre el y cuando se le presiona), la cuarta imagen define una mascara que define el rea activa del botn, es decir, solo se colectarn eventos del botn cuando el mouse se encuentre sobre esta rea activa.

2) Necesitamos crear un proyecto de tipo "Librera de Control de Windows". Y el tamao de la forma del control la definiremos en 150 por 150 pxeles, es raro pensar en botones muy grandes en el formulario, de cualquier manera el tamao no esta limitado en este proyecto.

3) Necesitamos agregar ahora cuatro controles Picture box para cada una de las imgenes de estados del botn. Es preferible que si quieren que su imagen se vea como ustedes la disean debe ser almacenada en formato PNG y con un fondo transparente. Tambin es importante que la imagen destinada a la mascara tenga fondo blanco y la mascara en si misma sea dibujada en color negro. Al final, vamos a dejar nuestra forma del control de la siguiente manera.

2 de 8

19/06/2012 8:31

Colabora.NET: Botones Personalizados

http://www.elguille.info/colabora/NET2005/ewing_boton_personalizad...

Nuestras imgenes son de 24 x 24 pxeles, y los picture box tendrn la propiedad SizeMode configurada como AutoSize, la posicin del primer picture box ser en las coordenadas 0,0 y el nombre de este lo definiremos como botn. Agregamos los botones tal como se muestra en la imagen anterior tomando en cuenta la imagen de acuerdo al nombre del control picture box. 4) Ahora ya esta hecho todo lo que debes hacer en la interfaz grfica, ahora trabajaremos con la parte lgica, as que echemos un vistazo al cdigo. Este esta compuesto de cuatro regiones: la regin del cdigo generado por el Visual Studio para los controles, una regin en la que se definen las variables y funciones para que nuestro botn responda correctamente, una regin en la que se definen las acciones de los objetos de nuestro control y por ultimo una regin en la que definimos mtodos y propiedades de este botn personalizado. Propiedades y mtodos de un control personalizado El siguiente cdigo muestra como puedes asignar una funcin que definas a un mtodo del control personalizado, adems cuatro propiedades bsicas del control. Como puedes notar, las palabras Category y Description te permiten categorizar en la ventana de propiedades y eventos las que tu defines en el control. #region private private private private private Metodos, propiedades y variables Image imgMask; Image imgOut; Image imgIn; Image imgClick; TimeSpan timeToWaitAfterClick = new TimeSpan(0,0,0,0,100);

public delegate void ClickEventHandler(object sender, System.EventArgs e); [Category("Action")] [Description("Occurs when the shaped button is clicked.")] public event ClickEventHandler shapedButtonClick; private void boton_Click(object sender, System.EventArgs e) { if ( shapedButtonClick != null ) { boton.Image = bIn.Image; Application.DoEvents(); System.Threading.Thread.Sleep(timeToWaitAfterClick); shapedButtonClick(this, e); } } [Category("Appearance")] [Description("Sets the image mask to define the shape of the button.")] public Image imageForMask { get { return imgMask;

3 de 8

19/06/2012 8:31

Colabora.NET: Botones Personalizados

http://www.elguille.info/colabora/NET2005/ewing_boton_personalizad...

} set { imgMask = value; leeBotonMask(); } } [Category("Appearance")] [Description("Sets the appearance of the button when the mouse is out of it.")] public Image imageForMouseOut { get { return imgOut; } set { imgOut = value; leeBotonMask(); } } [Category("Appearance")] [Description("Sets the appearance of the button when the mouse is over it.")] public Image imageForMouseIn { get { return imgIn; } set { imgIn = value; leeBotonMask(); } } [Category("Appearance")] [Description("Sets the appearance of the button when it is clicked.")] public Image imageForMouseClick { get { return imgClick; } set { imgClick = value; leeBotonMask(); } }

[Category("Behavior")] [Description("Sets the number of milliseconds to sleep after the click action (999 as maxi public int timeAfterClick { get { return timeToWaitAfterClick.Milliseconds; } set { timeToWaitAfterClick = TimeSpan.FromMilliseconds(value); if (value >= 1000) timeToWaitAfterClick = TimeSpan.FromMilliseconds(999); if (value < 0) timeToWaitAfterClick = TimeSpan.FromMilliseconds(0); } } #endregion

4 de 8

19/06/2012 8:31

Colabora.NET: Botones Personalizados

http://www.elguille.info/colabora/NET2005/ewing_boton_personalizad...

Variables y funciones auxiliares Este cdigo define la variable mas importante del control, un ArrayList llamado puntosActivos, el cual almacenar cada uno de los puntos negros de la mascar Para qu? Antes de que el objeto botn haga caso a los mtodos referentes a la accin del puntero del ratn, preguntar si el punto sobre el cual esta ubicado el puntero es uno de los puntos activos, si es as, la accin puede proceder, en caso contrario, la accin es omitida. En el cdigo que se muestra a continuacin tambin puedes ver como se llena este ArrayList, la funcin leeBotonMask realiza sta tarea y siempre est evaluando la mascar si haces algn cambio en las propiedades del control. #region Variables y funciones axiliares private System.Collections.ArrayList puntosActivos = new ArrayList(); private Boolean presionado = false; private void leeBotonMask() { this.boton.Image = imgMask; this.bOut.Image = imgOut; this.bIn.Image = imgIn; this.bClick.Image = imgClick; puntosActivos.Clear(); this.Width = boton.Image.Width; this.Height = boton.Image.Height; Bitmap bmp = new Bitmap(boton.Image); Color cActual, negro = Color.FromArgb(255,0,0,0); int i, j; for (i = 1; i < bmp.Height; i++) { for (j = 1; j < bmp.Width; j++) { cActual = bmp.GetPixel(j, i); if (cActual == negro) { puntosActivos.Add(new Point(j, i)); } } } foreach (Point p in puntosActivos) { bmp.SetPixel(p.X,p.Y,Color.LightSteelBlue); } boton.Image = bOut.Image; } #endregion Acciones de Objetos Por ltimo, vemos las acciones del objeto botn, cuando se carga en un nuevo formulario (mtodo que solo debe ocurrir una vez), cuando el puntero del ratn est sobre l, cuando est fuera de l, cuando se presiona el botn del ratn sobre l y cuando este botn es liberado. Como platiqu anteriormente se verifica que el ratn este sobre un rea activa definida por la mascara y adems controla el estado del click del ratn. Vern que el mtodo Click como tal, esta siendo llamado por el mtodo MouseUp (Ver propiedades y mtodos). #region Acciones de Objetos private void shapedButton_Load(object sender, System.EventArgs e) { if (puntosActivos != null && puntosActivos.Count > 0) { return; } imgMask = this.boton.Image; imgOut = this.bOut.Image; imgIn = this.bIn.Image; imgClick = this.bClick.Image;

5 de 8

19/06/2012 8:31

Colabora.NET: Botones Personalizados

http://www.elguille.info/colabora/NET2005/ewing_boton_personalizad...

leeBotonMask(); } private void boton_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e) { Point pOver = new Point(e.X, e.Y); if ( puntosActivos.IndexOf(pOver) < 0 ) { boton.Image = bOut.Image; return; } if ( presionado == false ) boton.Image = bIn.Image; else boton.Image = bClick.Image; } private void boton_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e) { Point pOver = new Point(e.X, e.Y); if ( puntosActivos.IndexOf(pOver) < 0 ) { return; } boton.Image = bClick.Image; presionado = true; } private void boton_MouseLeave(object sender, System.EventArgs e) { boton.Image = bOut.Image; } private void boton_MouseUp(object sender, System.Windows.Forms.MouseEventArgs e) { Point pOver = new Point(e.X, e.Y); presionado = false; if ( puntosActivos.IndexOf(pOver) < 0 ) { return; } this.boton_Click(sender, System.EventArgs.Empty); } #endregion Ahora asigna los eventos MouseDown, MouseLeave, MouseMove y MouseUp del picture box llamado botn a su correspondiente funcin e igualmente hazlo con el evento Load del formulario (del control).

Controles de usuario transparentes

6 de 8

19/06/2012 8:31

Colabora.NET: Botones Personalizados

http://www.elguille.info/colabora/NET2005/ewing_boton_personalizad...

Te has dado cuenta que por omisin no se puede definir en un control de usuario la propiedad de color de fondo como transparente. Bueno para poder hacer esto solo agrega en constructor de clase la lnea: SetStyle(System.Windows.Forms.ControlStyles.SupportsTransparentBackColor,true); Como se ve en el siguiente ejemplo, el constructor debe quedar as: public shapedButton() { // This call is required by the Windows.Forms Form Designer. InitializeComponent(); // TODO: Add any initialization after the InitComponent call SetStyle(System.Windows.Forms.ControlStyles.SupportsTransparentBackColor,true); }

Cmo se usa?
Compilen su proyecto, lo cual les va a generar una DLL. Creen un nuevo proyecto de tipo Aplicacin de Windows. Copien a su directorio de proyecto la DLL generada por el control personalizado (no es necesario pero acurdense donde esta si no hacen esta copia). Agrguenlo a la barra de herramientas ubicando la DLL con el explorador de componentes .NET. Agreguen tambin a las referencias del proyecto esta DLL y as mismo en el cdigo del proyecto definan el uso de este componente.

En la aplicacin de ejemplo para el uso de este control personalizado mostramos el control que se pinta por default, uno que mostrar un MessageBox y otro que emula la opcin cerrar.

7 de 8

19/06/2012 8:31

Colabora.NET: Botones Personalizados

http://www.elguille.info/colabora/NET2005/ewing_boton_personalizad...

Por ahora es todo para esta entrega. Esperen pronto algunas ms. Dudas y comentarios del tema dirjanlas a mi correo. Saludos.

Fichero con el cdigo de ejemplo: ewing_boton_personalizado.zip - 104 KB

8 de 8

19/06/2012 8:31

Anda mungkin juga menyukai