Textos Universitarios / Serie Docencia ________________________________________________________________________ Capítulo 3 Objetos Gráficos Los objetos gráficos son la parte medular de GDI+. Se generan mediante la Clase Graphics que define propiedades y métodos para dibujar y rellenar objetos gráficos. Cada vez que una aplicación necesita pintar o dibujar algo, necesita utilizar un objeto Graphics. Esta es la razón fundamental para que comprendamos su configuración y componentes y veamos como usarlos en el desarrollo de gráficos en línea. Esta clase provee métodos para dibujar líneas, figuras, imágenes y texto. Un objeto Graphics almacena atributos del dispositivo de pantalla y también de los elementos a dibujarse. 3.1 Clase Graphics113 Requisitos Espacio de nombres: System.Drawing Las secciones siguientes muestran los miembros expuestos por el objeto Graphics 3.1.1 Propiedades públicas Clip ClipBounds CompositingMode CompositingQuality DpiX DpiY InterpolationMode IsClipEmpty Obtiene o establece un objeto Region que limita la región de dibujo de este objeto Graphics. Obtiene una estructura RectangleF que delimita la región de recorte de este objeto Graphics. Obtiene un valor que especifica cómo se dibujan las imágenes compuestas en este objeto Graphics. Obtiene o establece la calidad de procesado de las imágenes compuestas que se dibujan en este objeto Graphics. Obtiene la resolución horizontal de este objeto Graphics. Obtiene la resolución vertical de este objeto Graphics. Obtiene o establece el modo de interpolación asociado al objeto Graphics. Obtiene un valor que indica si la región de recorte de este objeto Graphics está vacía. 13 http://msdn2.microsoft.com/en-us/library/system.drawing.graphics(d=ide).aspx Junio 3 de 2006 69 Jenaro C. Paz ________________________________________________________________________ Obtiene un valor que indica si la región de recorte visible de este objeto Graphics está vacía. Obtiene o establece la relación de escala entre las unidades universales y las unidades de página de este objeto Graphics. Obtiene o establece la unidad de medida utilizada para las coordenadas de página en este objeto Graphics. Obtiene o establece un valor que especifica cómo se calcula el desplazamiento de los píxeles durante el procesamiento de este objeto Graphics. Obtiene o establece el origen de procesamiento de este objeto Graphics para la interpolación y los pinceles de trama. Obtiene o establece la calidad de procesamiento de este objeto Graphics. Obtiene o establece el valor de corrección de gamma para el procesado de texto. Obtiene o establece el modo de procesamiento del texto asociado al objeto Graphics. Obtiene o establece la transformación universal de este objeto Graphics. Obtiene o establece el rectángulo delimitador que corresponde a la región de recorte visible de este objeto Graphics. IsVisibleClipEmpty PageScale PageUnit PixelOffsetMode RenderingOrigin SmoothingMode TextContrast TextRenderingHint Transform VisibleClipBounds Tabla 3.1. Miembros de la clase Graphics 3.1.2 Métodos públicos AddMetafileComment BeginContainer Clear CreateObjRef (se hereda de 70 Agrega un comentario al objeto Metafile actual. Sobrecargado. Guarda un contenedor de gráficos con el estado actual de este objeto Graphics y abre y utiliza un nuevo contenedor de gráficos. Borra toda la superficie de dibujo y la rellena con el color de fondo especificado. Crea un objeto que contiene toda la Textos Universitarios / Serie Docencia ________________________________________________________________________ MarshalByRefObject) Dispose EndContainer EnumerateMetafile Equals (se hereda de Object) ExcludeClip Flush FromHdc FromHdcInternal FromHwnd FromHwndInternal FromImage GetHalftonePalette GetHashCode (se hereda de Object) GetHdc GetLifetimeService (se hereda de información relevante necesaria para generar un proxy utilizado para comunicarse con un objeto remoto. Libera todos los recursos utilizados por este objeto Graphics. Cierra el contenedor de gráficos actual y restaura el estado que tenía este objeto Graphics al estado guardado mediante una llamada al método BeginContainer. Sobrecargado. Envía los registros del objeto Metafile especificado, de uno en uno, a un método de devolución de llamada para su presentación en un punto determinado. Sobrecargado. Determina si dos instancias de Object son iguales. Sobrecargado. Actualiza la región de recorte de este objeto Graphics con el fin de excluir el área especificada por una estructura Rectangle. Sobrecargado. Fuerza la ejecución de todas las operaciones de gráficos pendientes y devuelve inmediatamente el control sin esperar a que finalicen las operaciones. Sobrecargado. Crea un nuevo objeto Graphics a partir del identificador especificado en un contexto de dispositivo. Método interno. No utilizar. Crea un nuevo objeto Graphics a partir del identificador especificado de una ventana. Método interno. No utilizar. Crea un nuevo objeto Graphics a partir del objeto Image especificado. Obtiene un identificador de la paleta actual de medios tonos de Windows. Sirve como función hash para un tipo concreto, apropiado para su utilización en algoritmos de hash y estructuras de datos como las tablas hash. Obtiene el identificador del contexto de dispositivo asociado a este objeto Graphics. Recupera el objeto de servicio de duración 71 Jenaro C. Paz ________________________________________________________________________ MarshalByRefObject) GetNearestColor GetType (se hereda de Object) InitializeLifetimeService (se hereda de MarshalByRefObject) IntersectClip IsVisible MeasureCharacterRanges MeasureString MultiplyTransform ReleaseHdc ReleaseHdcInternal ResetClip ResetTransform Restore RotateTransform 72 actual que controla la directiva de duración de esta instancia. Obtiene el color más próximo a la estructura Color especificada. Obtiene el objeto Type de la instancia actual. Obtiene un objeto de servicio de duración para controlar la directiva de duración de esta instancia. Sobrecargado. Actualiza la región de recorte del objeto Graphics como la intersección de la región de recorte actual y la estructura Rectangle especificada. Sobrecargado. Indica si el punto especificado por un par de coordenadas se halla contenido en la región de recorte visible de este objeto Graphics. Obtiene una matriz de objetos Region, cada uno de los cuales delimita un intervalo de posiciones de caracteres dentro de la cadena especificada. Sobrecargado. Mide la cadena especificada al dibujarla con el objeto Font especificado. Sobrecargado. Multiplica la transformación universal del objeto Graphics y especificada en el objeto Matrix. Libera un identificador de contexto de dispositivo obtenido mediante una llamada anterior al método GetHdc de este objeto Graphics. Método interno. No utilizar. Restablece la región de recorte de este objeto Graphics en una región infinita. Restablece la matriz de transformación universal de este objeto Graphics en la matriz de identidades. Restaura como estado de este objeto Graphics el estado representado por un objeto GraphicsState. Sobrecargado. Aplica la rotación especificada a la matriz de transformación Textos Universitarios / Serie Docencia ________________________________________________________________________ Save ScaleTransform SetClip ToString (se hereda de Object) TransformPoints TranslateClip TranslateTransform de este objeto Graphics. Guarda el estado actual de este objeto Graphics e identifica el estado guardado con un objeto GraphicsState. Sobrecargado. Aplica la operación de cambio de escala especificada a la matriz de transformación de este objeto Graphics, anteponiéndola a esta última. Sobrecargado. Establece la región de recorte de este objeto Graphics en la propiedad Clip del objeto Graphics especificado. Devuelve un objeto String que representa al objeto actual. Sobrecargado. Transforma una matriz de puntos de un espacio de coordenadas a otro utilizando las transformaciones universal y de página actuales de este objeto Graphics. Sobrecargado. Convierte la región de recorte de este objeto Graphics usando las cantidades especificadas en las direcciones horizontal y vertical. Sobrecargado. Antepone la conversión especificada a la matriz de transformación de este objeto Graphics. 3.1.2.1 Métodos públicos para el dibujo DrawArc (1) DrawBezier (2) DrawBeziers (3) DrawClosedCurve (4) DrawCurve (5) Sobrecargado. Dibuja una imagen que representa una parte de una elipse especificada por un par de coordenadas, un valor de ancho y un valor de alto. Sobrecargado. Dibuja una curva spline de Bézier definida por cuatro estructuras Point. Sobrecargado. Dibuja una serie de curvas spline de Bézier a partir de una matriz de estructuras Point. Sobrecargado. Dibuja una curva spline cardinal cerrada, definida por una matriz de estructuras Point. Sobrecargado. Dibuja una curva spline cardinal a través de una matriz especificada de estructuras Point. 73 Jenaro C. Paz ________________________________________________________________________ DrawEllipse (6) DrawIcon (7) DrawIconUnstretched (8) DrawImage (9) DrawImageUnscaled (10) DrawLine (11) DrawLines (12) DrawPath (13) DrawPie (14) DrawPolygon (15) DrawRectangle (16) DrawRectangles (17) DrawString (18) 74 Sobrecargado. Dibuja una elipse definida por un rectángulo delimitador especificado por un par de coordenadas, un valor de alto y un valor de ancho. Sobrecargado. Dibuja la imagen representada por el objeto Icon especificado en las coordenadas señaladas. Dibuja la imagen representada por el objeto Icon especificado sin transformar a escala la imagen. Sobrecargado. Dibuja el objeto Image especificado en la ubicación especificada y con el tamaño original. Sobrecargado. Dibuja la imagen especificada con su tamaño físico original y en la ubicación especificada por un par de coordenadas. Sobrecargado. Dibuja una línea que conecta los dos puntos especificados por los pares de coordenadas. Sobrecargado. Dibuja una serie de segmentos de línea que conectan una matriz de estructuras Point. Dibuja un objeto GraphicsPath. Sobrecargado. Dibuja una forma circular definida por una elipse y determinada por un par de coordenadas, unos valores de ancho y alto y dos líneas radiales. Sobrecargado. Dibuja un polígono definido por una matriz de estructuras Point. Sobrecargado. Dibuja un rectángulo especificado por un par de coordenadas, un valor de ancho y un valor de alto. Sobrecargado. Dibuja una serie de rectángulos especificados por las estructuras Rectangle. Sobrecargado. Dibuja la cadena de texto especificada en la ubicación especificada y con los objetos Brush y Font especificados. Textos Universitarios / Serie Docencia ________________________________________________________________________ 3.1.2.1.1 Dibujando imágenes mediante una forma Web14 En esta sección se presentan diferentes formas Web y su código adjunto para ejemplificar los métodos de dibujo (1) al (18) de la sección 3.1.2.1 (Métodos públicos para el dibujo). 3.1.2.1.1.1 Generación del lienzo de dibujo definido por su color y tamaño. Forma DrawBG.aspx Figura 3.1. Identificadores para los controles de la forma DrawBG.aspx DrawBG.aspx.cs using using using using using using using using using using System; System.Collections; System.ComponentModel; System.Data; System.Drawing; System.Web; System.Web.SessionState; System.Web.UI; System.Web.UI.WebControls; System.Web.UI.HtmlControls; namespace JCPGraphics { /// <summary> /// Summary description for DrawBG. 14 A partir de esta sección todos los programas, codigo fuente y aplicaciones Web son propiedad intelectual del autor. 75 Jenaro C. Paz ________________________________________________________________________ /// </summary> public class DrawBG : System.Web.UI.Page { protected System.Web.UI.WebControls.TextBox txtWidth; protected System.Web.UI.WebControls.TextBox txtHeight; protected System.Web.UI.WebControls.Label Label1; protected System.Web.UI.WebControls.Button btnBuild; protected System.Web.UI.WebControls.Label Label2; private void Page_Load(object sender, System.EventArgs e) { // } #region Web Form Designer generated code override protected void OnInit(EventArgs e) { // // CODEGEN: This call is required by the ASP.NET Web Form Designer. // InitializeComponent(); base.OnInit(e); } /// <summary> /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// </summary> private void InitializeComponent() { this.btnBuild.Click += new System.EventHandler(this.btnBuild_Click); this.Load += new System.EventHandler(this.Page_Load); } #endregion private void btnBuild_Click(object sender, System.EventArgs e) { string recHeight = txtHeight.Text; string recWidth = txtWidth.Text; Response.Write("<img border='0' src='Server_bg.aspx?valueH=" + recHeight + "&valueW=" + recWidth + "'>"); Response.Write("<p><font color=red>Just the Background Rectangle!</font></p>"); } } } Listado 3.1. Código asociado con la forma DrawBG.aspx En el listado 3.1 encontramos definido el método btnBuild_Click que se ejecuta cuando el usuario pulsa sobre el botón con identificador btnBuild. En este método se lleva a cabo lo siguiente: 1. Se almacenan las dimensiones de la imagen a generar en las variables recHeight y recWidth 2. Se llama el método Response.Write para mandar al documento Web la cadena 76 Textos Universitarios / Serie Docencia ________________________________________________________________________ "<img border='0' src='Server_bg.aspx?valueH=" + recHeight + &valueW=" + recWidth + "'>" 3. La forma Web Server_bg.aspx utiliza los parámetros mencionados que le son pasados mediante el QueryString. Server_bg.aspx.cs using using using using using using using using using using using using System; System.Collections; System.ComponentModel; System.Data; System.Drawing; System.Web; System.Web.SessionState; System.Web.UI; System.Web.UI.WebControls; System.Web.UI.HtmlControls; System.IO; System.Drawing.Imaging; namespace JCPGraphics { /// <summary> /// Summary description for rectServer. /// </summary> public class Server_bg : System.Web.UI.Page { int w1,h1; Color bgColor=Color.LightGray; //=================================================================== private void Page_Load(object sender, System.EventArgs e) { w1 = UInt16.Parse(Request.QueryString["valueW"]); h1 = UInt16.Parse(Request.QueryString["valueH"]); // Create a Stream in memory to save the image MemoryStream memStream = canvasAndImage(); Response.Clear(); // Send the memory image to Browser in binary mode memStream.WriteTo(Response.OutputStream); } //=================================================================== public MemoryStream canvasAndImage() { // Define a Rectangle to be the BG rectangle Rectangle bgRect = new Rectangle(0,0,w1,h1); // The bitmap Object used to work with images defined by // pixel data Bitmap pixelImage = new Bitmap(w1,h1); // 1) Will be used to build the new Graphics object // 2) Whatever you do with the Graphics object you afect // the image object! Graphics g = Graphics.FromImage(pixelImage); // Fill the interior of the bg rectangle g.FillRectangle(new SolidBrush(bgColor), bgRect); 77 Jenaro C. Paz ________________________________________________________________________ MemoryStream aStream = new MemoryStream(); pixelImage.Save(aStream,ImageFormat.Png); // Bmp, Jpeg, Png, Gif return aStream; } //=================================================================== #region Web Form Designer generated code override protected void OnInit(EventArgs e) { // // CODEGEN: This call is required by the ASP.NET Web Form // Designer. // InitializeComponent(); base.OnInit(e); } /// <summary> /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// </summary> private void InitializeComponent() { this.Load += new System.EventHandler(this.Page_Load); } #endregion } } Listado 3.2. Código asociado con la forma Server_bg.aspx En la Figura 3.2 se presenta el resultado obtenido en el Navegador de Internet Figura 3.2. Lienzo de dibujo definido por su color y su tamaño 78 Textos Universitarios / Serie Docencia ________________________________________________________________________ Si comparamos los listados 2.2 y 3.2 encontramos que la clase del Servidor en el último, ha sido reestructurada de la siguiente manera: public class Server_xx : System.Web.UI.Page { // data members int w1,h1,..; // method Page_Load() that read info from QueryString // call the method to build a special kind of Image // and Writes to the Browser private void Page_Load(object sender, System.EventArgs e) { w1 = UInt16.Parse(Request.QueryString["valueW"]); h1 = UInt16.Parse(Request.QueryString["valueH"]); ... // Create a Stream in memory to save the image MemoryStream memStream = canvasAndImage(); Response.Clear(); // Send the memory image to Browser in binary mode memStream.WriteTo(Response.OutputStream); } // method canvasAndImage() public MemoryStream canvasAndImage() { // this method contains the logic to // build our GDI+ Image } ... } Listado 3.3 Estructura de las clases Server_xx que se presentan en este capítulo 3.1.2.1.1.2 Dibujando líneas sobre un lienzo Para dibujar líneas con GDI+ es necesario crear un objeto Graphics y un objeto Pen. El objeto Graphics proporciona los métodos que realmente realizan el dibujo, y el objeto Pen almacena atributos, como el estilo, el ancho y el color de línea. Para dibujar una línea, llame al método DrawLine del objeto Graphics. El objeto Pen se pasa como uno de los argumentos del método DrawLine. El siguiente código dibuja una línea del punto (4, 1) al punto (12, 5): [C#] myGraphics.DrawLine(myPen, 4, 1, 12, 5); DrawLine es un método sobrecargado de la clase Graphics, de modo que existen varias formas de suministrar argumentos a dicho método. Por ejemplo, se pueden construir dos objetos Point y pasarlos como argumentos del método DrawLine: [C#] Point myStartPoint = new Point(4, 1); Point myEndPoint = new Point(12, 5); myGraphics.DrawLine(myPen, myStartPoint, myEndPoint); 79 Jenaro C. Paz ________________________________________________________________________ Cuando se construye un objeto Pen, pueden especificarse ciertos atributos. Por ejemplo, un constructor Pen permite especificar el color y el ancho. En el siguiente ejemplo se dibuja una línea azul de ancho 2 de (10, 10) a (80, 30): [C#] Pen myPen = new Pen(Color.Red, 2); myGraphics.DrawLine(myPen, 10, 10, 80, 30); El objeto Pen también expone propiedades, como DashStyle, que pueden utilizarse para especificar características de la línea. En el siguiente código se dibuja una línea discontinua de (10, 40) a (30, 80): [C#] myPen.DashStyle = DashStyle.Dash; myGraphics.DrawLine(myPen, 10, 40, 30, 80); Las propiedades del objeto Pen pueden utilizarse para establecer muchos más atributos de la línea. Las propiedades StartCap y EndCap especifican la apariencia de los extremos de la línea; los extremos pueden ser lisos, cuadrados, redondeados, triangulares o pueden tener una forma personalizada. La propiedad LineJoin permite especificar si las líneas conectadas están en ángulo (unidas con esquinas definidas), biseladas, redondeadas o recortadas. En la siguiente ilustración se muestran líneas con varios estilos de combinación y extremos. Figura 3.3. Diferente tipo de extremos para líneas La Forma DrawLines.aspx es idéntica a la presentada en la Figura 2.13 y así mismo a las que utilizaremos en el resto de este Capitulo, razón por la cual no la volveremos a presentar, sin embargo el código relacionado es: DrawLines.aspx.cs using using using using using using using using using using System; System.Collections; System.ComponentModel; System.Data; System.Drawing; System.Web; System.Web.SessionState; System.Web.UI; System.Web.UI.WebControls; System.Web.UI.HtmlControls; namespace JCPGraphics 80 Textos Universitarios / Serie Docencia ________________________________________________________________________ { public class DrawLines : System.Web.UI.Page { protected System.Web.UI.WebControls.TextBox txtWidth; protected System.Web.UI.WebControls.TextBox txtHeight; protected System.Web.UI.WebControls.Label Label1; protected System.Web.UI.WebControls.Button btnGenerar; protected System.Web.UI.WebControls.Label Label2; private void Page_Load(object sender, System.EventArgs e) { // Introducir aquí el código de usuario para inicializar la página } #region Código generado por el Diseñador de Web Forms override protected void OnInit(EventArgs e) { // InitializeComponent(); base.OnInit(e); } /// <summary> /// Método necesario para admitir el Diseñador. /// No se puede modificar /// el contenido del método con el editor de código. /// </summary> private void InitializeComponent() { this.btnGenerar.Click += new System.EventHandler(this.btnGenerar_Click); this.Load += new System.EventHandler(this.Page_Load); } #endregion private void btnGenerar_Click(object sender, System.EventArgs e) { string recHeight = txtHeight.Text; string recWidth = txtWidth.Text; Response.Write("<img border='0' src='ServerLines.aspx?valueH=" + recHeight + "&valueW=" + recWidth + "'>"); Response.Write("<p><font color=red>Diferent kind of Lines!</font></p>"); } } } Listado 3.4. Codigo asociado a la forma DrawLines.aspx ServerLines.aspx.cs using using using using System; System.Collections; System.ComponentModel; System.Data; 81 Jenaro C. Paz ________________________________________________________________________ using using using using using using using using System.Drawing; System.Web; System.Web.SessionState; System.Web.UI; System.Web.UI.WebControls; System.Web.UI.HtmlControls; System.IO; System.Drawing.Imaging; namespace JCPGraphics { public class ServerLines : System.Web.UI.Page { int w1,h1; Color bgColor=Color.LightGray; private void Page_Load(object sender, System.EventArgs e) { w1 = UInt16.Parse(Request.QueryString["valueW"]); h1 = UInt16.Parse(Request.QueryString["valueH"]); // Create a Stream in memory to save the image MemoryStream memStream = canvasAndImage(); Response.Clear(); // Send the memory image to Browser in binary mode memStream.WriteTo(Response.OutputStream); } public MemoryStream canvasAndImage() { // Define a Rectangle to be the BG rectangle Rectangle bgRect = new Rectangle(0,0,w1,h1); // The bitmap Object used to work with images defined by // pixel data Bitmap pixelImage = new Bitmap(w1,h1); // 1) Will be used to build the new Graphics object // 2) Whatever you do with the Graphics object you afect // the image object! Graphics g = Graphics.FromImage(pixelImage); // Fill the interior of the bg rectangle g.FillRectangle(new SolidBrush(bgColor), bgRect); // +++++++++++++++Begins section related with this Server // /* Pens to draw lines */ Pen aPen1 = new Pen(Color.MediumPurple, 1); Pen aPen2 = new Pen(Color.Fuchsia, 2); Pen aPen3 = new Pen(Color.LemonChiffon, 3); Pen aPen4 = new Pen(Color.LightCoral, 4); Pen aPen5 = new Pen(Color.MediumVioletRed, 5); // Draw line using float coordinates float x1 = 20.0F, y1 = 20.0F; float x2 = 200.0F, y2 = 20.0F; g.DrawLine(aPen1, x1, y1, x2, y2); // Draw line using Point structure Point pt1 = new Point(20, 20); Point pt2 = new Point(20, 200); g.DrawLine(aPen2, pt1, pt2); // Draw line using PointF structure PointF ptf1 = new PointF(20.0F, 20.0F); 82 Textos Universitarios / Serie Docencia ________________________________________________________________________ PointF ptf2 = new PointF(200.0F, 200.0F); g.DrawLine(aPen3, ptf1, ptf2); // Draw line using integer coordinates int X1 = 20, Y1 = 200, X2 = 200, Y2 = 200; g.DrawLine(aPen4, X1, Y1, X2, Y2); // Draw line using integer coordinates int Xa = 200, Ya = 20, Xb = 200, Yb = 200; g.DrawLine(aPen5, Xa, Ya, Xb, Yb); // Dispose of objects aPen1.Dispose(); aPen2.Dispose(); aPen3.Dispose(); aPen4.Dispose(); aPen5.Dispose(); // // +++++++++++++++Ends section related with this Server MemoryStream aStream = new MemoryStream(); pixelImage.Save(aStream, ImageFormat.Png); // Bmp, Jpeg, Png, Gif return aStream ; } | Web Form Designer Generated Code | } } Listado 3.5. Codigo asociado a la forma ServerLines.aspx El resultado de la interacción de estas dos formas se muestra en la Figura 3.4 que se muestra a continuación. Figura 3.4. Diferente tipo de lineas sobre el lienzo 83 Jenaro C. Paz ________________________________________________________________________ 3.1.2.1.1.1 Dibujando rectángulos sobre un lienzo Dibujar rectángulos con GDI+ es parecido a dibujar líneas. Para dibujar un rectángulo son necesarios un objeto Graphics y un objeto Pen. El objeto Graphics proporciona un método DrawRectangle, y el objeto Pen almacena atributos tales como el color y el ancho de línea. El objeto Pen se pasa como uno de los argumentos de método DrawRectangle. En el siguiente código se dibuja un rectángulo con la esquina superior izquierda en (90, 40), un ancho de 70 y una altura de 40: [C#] myGraphics.DrawRectangle(myPen, 90, 40, 70, 40); DrawRectangle es un método sobrecargado de la clase Graphics, de modo que hay varias formas de suministrar argumentos a dicho método. Por ejemplo, se puede construir un objeto Rectangle y pasarlo como argumento del método DrawRectangle: [C#] Rectangle myRectangle = new Rectangle(60, 50, 90, 140); myGraphics.DrawRectangle(myPen, myRectangle); Un objeto Rectangle tiene métodos y propiedades para manipular y recopilar información sobre el rectángulo. Por ejemplo, los métodos Inflate y Offset cambian el tamaño y la posición del rectángulo. El método IntersectsWith indica si el rectángulo forma una intersección con otro rectángulo determinado, y el método Contains indica si un punto determinado se encuentra dentro del rectángulo. La única diferencia entre el Listado 3.1 y el Listado 3.4 es el URL que se manda llamar para generar la imagen, en este último caso: Response.Write("<img border='0' src='ServerLines.aspx?valueH=" + recHeight + "&valueW=" + recWidth + "'>"); Razón por la cual en lo sucesivo solo mostraremos el código relacionado con el método btnGenerar_Click(). DrawRectangle.aspx.cs private void btnGenerar_Click(object sender, System.EventArgs e) { string recHeight = txtHeight.Text; string recWidth = txtWidth.Text; Response.Write("<img border='0' rc='ServerRectangle.aspx?valueH=" + recHeight + "&valueW=" + recWidth + "'>"); Response.Write("<p><font color=red>Two Rectangles!</font></p>"); } Listado 3.6. Código asociado con la forma DrawRectangle.aspx 84 Textos Universitarios / Serie Docencia ________________________________________________________________________ ServerRectangle.aspx.cs using using using using using using using using using using using using System; System.Collections; System.ComponentModel; System.Data; System.Drawing; System.Web; System.Web.SessionState; System.Web.UI; System.Web.UI.WebControls; System.Web.UI.HtmlControls; System.IO; System.Drawing.Imaging; namespace JCPGraphics { public class ServerRectangle : System.Web.UI.Page { int w1,h1; Color bgColor=Color.LightGray; private void Page_Load(object sender, System.EventArgs e) { w1 = UInt16.Parse(Request.QueryString["valueW"]); h1 = UInt16.Parse(Request.QueryString["valueH"]); // Create a Stream in memory to save the image MemoryStream memStream = canvasAndImage(); Response.Clear(); // Send the memory image to Browser in binary mode memStream.WriteTo(Response.OutputStream); } public MemoryStream canvasAndImage() { // Define a Rectangle to be the BG rectangle Rectangle bgRect = new Rectangle(0,0,w1,h1); // The bitmap Object used to work with images defined by // pixel data Bitmap pixelImage = new Bitmap(w1,h1); // 1) Will be used to build the new Graphics object // 2) Whatever you do with the Graphics object you afect // the image object! Graphics g = Graphics.FromImage(pixelImage); // Fill the interior of the bg rectangle g.FillRectangle(new SolidBrush(bgColor), bgRect); // +++++++++++++++Begins section related with this Server // /* Pens to draw lines */ Pen aPen1 = new Pen(Color.MediumPurple, 1); Pen aPen2 = new Pen(Color.Fuchsia, 2); Pen aPen3 = new Pen(Color.LemonChiffon, 3); Pen aPen4 = new Pen(Color.LightCoral, 4); Pen aPen5 = new Pen(Color.MediumVioletRed, 5); g.DrawRectangle(aPen3,20, 40, 80, 120); g.DrawRectangle(aPen4,60, 80, 140, 50); aPen1.Dispose(); aPen2.Dispose(); aPen3.Dispose(); aPen4.Dispose(); aPen5.Dispose(); // // +++++++++++++++Ends section related with this Server 85 Jenaro C. Paz ________________________________________________________________________ aPen1.Dispose(); aPen2.Dispose(); aPen3.Dispose(); aPen4.Dispose(); aPen5.Dispose(); // // +++++++++++++++Ends section related with this Server MemoryStream aStream = new MemoryStream(); pixelImage.Save(aStream, ImageFormat.Png); // Bmp, Jpeg, Png, Gif return aStream; } | Web Form Designer Generated Code | } } Listado 3.7. Código asociado con la forma ServerRectangle.aspx El resultado de la interacción de estas dos formas se muestra en la Figura 3.25 que se muestra a continuación. Figura 3.5. Rectangulos sobre el lienzo 86 Textos Universitarios / Serie Docencia ________________________________________________________________________ Si sustituimos el metodo canvasAndImage por este otro public MemoryStream canvasAndImage() { // Define a Rectangle to be the BG rectangle Rectangle bgRect = new Rectangle(0,0,w1,h1); // The bitmap Object used to work with images defined by // pixel data Bitmap pixelImage = new Bitmap(w1,h1); // 1) Will be used to build the new Graphics object // 2) Whatever you do with the Graphics object you afect // the image object! Graphics g = Graphics.FromImage(pixelImage); // Fill the interior of the bg rectangle g.FillRectangle(new SolidBrush(bgColor), bgRect); // +++++++++++++++Begins section related with this Server // /* Pens to draw lines */ Pen aPen1 = new Pen(Color.MediumPurple, 2); Pen aPen2 = new Pen(Color.Fuchsia, 2); Pen aPen3 = new Pen(Color.LemonChiffon, 2); Pen aPen4 = new Pen(Color.LightCoral, 2); Pen aPen5 = new Pen(Color.MediumVioletRed, 2); RectangleF[] r1Array = { new RectangleF(0.0F, 0.0F, 400.0F, 400.0F), new RectangleF(20.0F, 20.0F, 360.0F, 360.0F), new RectangleF(40.0F, 40.0F, 320.0F, 320.0F), new RectangleF(60.0F, 60.0F, 280.0F, 280.0F), new RectangleF(80.0F, 80.0F, 240.0F, 240.0F), new RectangleF(100.0F, 100.0F, 200.0F, 200.0F), new RectangleF(120.0F, 120.0F, 160.0F, 160.0F), new RectangleF(140.0F, 140.0F, 120.0F, 120.0F), new RectangleF(160.0F, 160.0F, 80.0F, 80.0F), new RectangleF(180.0F, 180.0F, 40.0F, 40.0F), }; RectangleF[] r2Array = { new RectangleF(10.0F, 10.0F, 380.0F, 380.0F), new RectangleF(30.0F, 30.0F, 340.0F, 340.0F), new RectangleF(50.0F, 50.0F, 300.0F, 300.0F), new RectangleF(70.0F, 70.0F, 260.0F, 260.0F), new RectangleF(90.0F, 90.0F, 220.0F, 220.0F), new RectangleF(110.0F, 110.0F, 180.0F, 180.0F), new RectangleF(130.0F, 130.0F, 140.0F, 140.0F), new RectangleF(150.0F, 150.0F, 100.0F, 100.0F), new RectangleF(170.0F, 170.0F, 60.0F, 60.0F), new RectangleF(190.0F, 190.0F, 20.0F, 20.0F) }; g.DrawRectangles(aPen1,r1Array); g.DrawRectangles(aPen4,r2Array); // Dispose of objects aPen1.Dispose(); aPen4.Dispose(); 87 Jenaro C. Paz ________________________________________________________________________ // // +++++++++++++++Ends section related with this Server MemoryStream aStream = new MemoryStream(); pixelImage.Save(aStream, ImageFormat.Png); // Bmp, Jpeg, Png, Gif return aStream; } Listado 3.8. Codigo alterno asociado a la forma ServerRectangle.aspx Obtendremos como resultado la imagen de la Figura 3.6. Figura 3.6. Serie de rectangulos concentricos sobre el lienzo 3.1.2.1.1.1 Dibujando elipses y arcos sobre un lienzo Una elipse se especifica mediante su rectángulo delimitador. En la siguiente ilustración se muestra una elipse junto con su rectángulo delimitador. 88 Textos Universitarios / Serie Docencia ________________________________________________________________________ Figura 3.7. Elipse y su rectángulo delimitador Para dibujar una elipse, son necesarios un objeto Graphics y un objeto Pen. El objeto Graphics proporciona el método DrawEllipse, y el objeto Pen almacena atributos como el color y el ancho de la línea que se utiliza para representar la elipse. El objeto Pen se pasa como uno de los argumentos del método DrawEllipse. El resto de los argumentos que se pasan al método DrawEllipse especifican el rectángulo delimitador de la elipse. En el siguiente código se dibuja una elipse; el rectángulo delimitador tiene un ancho de 60, una altura de 30 y la esquina superior izquierda en (60, 50): [C#] myGraphics.DrawEllipse(myPen, 60, 50, 60, 30); DrawEllipse es un método sobrecargado de la clase Graphics, de modo que existen varias formas de proporcionar argumentos a dicho método. Por ejemplo, se puede construir un objeto Rectangle y pasarlo como argumento del método DrawEllipse: [C#] Rectangle myRectangle = new Rectangle(90, 50, 80, 30); myGraphics.DrawEllipse(myPen, myRectangle); Un arco es una parte de una elipse. Para dibujar un arco, se llama al método DrawArc de la clase Graphics. Los parámetros del método DrawArc son los mismos que los del método DrawEllipse, a excepción de que DrawArc precisa un ángulo inicial y un ángulo de barrido. En el siguiente ejemplo se dibuja un arco con un ángulo inicial de 30 grados y un ángulo de barrido de 180 grados: [C#] myGraphics.DrawArc(myPen, 100, 50, 140, 70, 30, 180); En la siguiente ilustración se muestran el arco, la elipse y el rectángulo delimitador. Figura 3.8. Arco de una elipse y su rectángulo delimitador 89 Jenaro C. Paz ________________________________________________________________________ Veamos ahora como aplicar lo anterior para trabajar con formas Web. Forma DrawEllipses.aspx.cs private void btnBuild_Click(object sender, System.EventArgs e) { string recHeight = txtHeight.Text; string recWidth = txtWidth.Text; Response.Write("<img border='0' src='ServerEllipses.aspx?valueH=" + recHeight + "&valueW=" + recWidth + "'>"); Response.Write("<p><font color=red>Three Ellipses!</font></p>"); } Listado 3.9. Código asociado con la forma DrawEllipses.aspx Forma ServerEllipses.aspx.cs using using using using using using using using using using using using System; System.Collections; System.ComponentModel; System.Data; System.Drawing; System.Web; System.Web.SessionState; System.Web.UI; System.Web.UI.WebControls; System.Web.UI.HtmlControls; System.IO; System.Drawing.Imaging; namespace JCPGraphics { public class ServerEllipses : System.Web.UI.Page { int w1,h1; Color bgColor=Color.LightGray; private void Page_Load(object sender, System.EventArgs e) { w1 = UInt16.Parse(Request.QueryString["valueW"]); h1 = UInt16.Parse(Request.QueryString["valueH"]); // Create a Stream in memory to save the image MemoryStream memStream = canvasAndImage(); Response.Clear(); // Send the memory image to Browser in binary mode memStream.WriteTo(Response.OutputStream); } public MemoryStream canvasAndImage() { // Define a Rectangle to be the BG rectangle Rectangle bgRect = new Rectangle(0,0,w1,h1); // The bitmap Object used to work with images defined by // pixel data Bitmap pixelImage = new Bitmap(w1,h1); 90 Textos Universitarios / Serie Docencia ________________________________________________________________________ // 1) Will be used to build the new Graphics object // 2) Whatever you do with the Graphics object you afect // the image object! Graphics g = Graphics.FromImage(pixelImage); // Fill the interior of the bg rectangle g.FillRectangle(new SolidBrush(bgColor), bgRect); // +++++++++++++++Begins section related with this Server // // Pens to draw Ellipses Pen aPen1 = new Pen(Color.LightCoral, 4); Pen aPen2 = new Pen(Color.Fuchsia, 2); Pen aPen3 = new Pen(Color.LemonChiffon, 3); g.DrawEllipse(aPen2,myRect.X+4,myRect.Y+4,myRect.Width-8, myRect.Height-8); g.DrawEllipse(aPen3,60, 60, 120, 120); g.DrawEllipse(aPen1,80.0F, 80.0F, 140.0F, 50.0F); // Dispose of objects aPen1.Dispose(); aPen2.Dispose(); aPen3.Dispose(); // // +++++++++++++++Ends section related with this Server MemoryStream aStream = new MemoryStream(); pixelImage.Save(aStream, ImageFormat.Png); // Bmp, Jpeg, Png, Gif return aStream ; } | Web Form Designer Generated Code | } } Listado 3.10. Código asociado con la forma ServerEllipses.aspx El resultado de la interacción de estas dos formas se muestra en la Figura 3.9 que se muestra a continuación. Figura 3.9. Diferentes elipses sobre el lienzo 91 Jenaro C. Paz ________________________________________________________________________ Forma DrawArcs.aspx.cs private void btnBuild_Click(object sender, System.EventArgs e) { string recHeight = txtHeight.Text; string recWidth = txtWidth.Text; Response.Write("<img border='0' src='ServerArcs.aspx?valueH=" + recHeight + "&valueW=" + recWidth + "'>"); Response.Write("<p><font color=red>Diferent Arcs!</font></p>"); } Listado 3.11. Codigo asociado a la forma DrawArcs.aspx Forma ServerArcs.aspx.cs using using using using using using using using using using using using System; System.Collections; System.ComponentModel; System.Data; System.Drawing; System.Web; System.Web.SessionState; System.Web.UI; System.Web.UI.WebControls; System.Web.UI.HtmlControls; System.IO; System.Drawing.Imaging; namespace JCPGraphics { public class ServerArcs : System.Web.UI.Page { int w1,h1; Color bgColor=Color.LightGray; private void Page_Load(object sender, System.EventArgs e) { w1 = UInt16.Parse(Request.QueryString["valueW"]); h1 = UInt16.Parse(Request.QueryString["valueH"]); // Create a Stream in memory to save the image MemoryStream memStream = buildImage(); Response.Clear(); // Send the memory image to Browser in binary mode memStream.WriteTo(Response.OutputStream); } public MemoryStream buildImage() { // Define a Rectangle to be the BG rectangle Rectangle bgRect = new Rectangle(0,0,w1,h1); // The bitmap Object used to work with images defined by // pixel data Bitmap pixelImage = new Bitmap(w1,h1); // 1) Will be used to build the new Graphics object 92 Textos Universitarios / Serie Docencia ________________________________________________________________________ // 2) Whatever you do with the Graphics object you afect // the image object! Graphics g = Graphics.FromImage(pixelImage); // Fill the interior of the bg rectangle g.FillRectangle(new SolidBrush(bgColor), bgRect); // +++++++++++++++Begins section related with this Server // // Pens to draw lines Pen redPen = new Pen(Color.Red, 3); Pen bluePen = new Pen(Color.Blue,2); Pen greenPen = new Pen(Color.Green,4); float startAngle = 45.0f; float sweepAngle = 90.0f; Rectangle rect = new Rectangle(20, 20, 200, 200); g.DrawArc(redPen,rect, startAngle, sweepAngle); g.DrawArc(bluePen,20,30,50,70, 90.0F, 135.0F); g.DrawArc(bluePen,170,30,50,70, 90, -135); g.DrawArc(greenPen,110,120,20,20,0,360); // // +++++++++++++++Ends section related with this Server MemoryStream aStream = new MemoryStream(); pixelImage.Save(aStream,ImageFormat.Png); // Bmp, Jpeg, Png, Gif return aStream; } | Web Form Designer Generated Code | } } Listado 3.12. Código asociado a la forma ServerArcs.aspx El resultado de la interacción de estas dos formas se muestra en la Figura 3.10 que se muestra a continuación. Figura 3.10. Diferente tipo de arcos sobre el lienzo 93 Jenaro C. Paz ________________________________________________________________________ 3.1.2.1.1.1 Dibujando Polígonos sobre un lienzo Un polígono es una forma cerrada con tres o más líneas rectas. Por ejemplo, un triángulo es un polígono con tres lados, un rectángulo es un polígono con cuatro lados y un pentágono es un polígono con cinco lados. En la siguiente ilustración se muestran varios polígonos. Figura 3.11. Ejemplo de Polígonos Para dibujar un polígono, son necesarios un objeto Graphics, un objeto Pen y un arreglo de objetos Point (o PointF). El objeto Graphics proporciona el método DrawPolygon. El objeto Pen almacena atributos, como el ancho y el color de la línea utilizada para representar el polígono, y el arreglo de objetos Point almacena los puntos que se van a conectar mediante líneas rectas. El objeto Pen y el arreglo de objetos Point se pasan como argumentos del método DrawPolygon. En el siguiente ejemplo se dibuja un polígono de tres lados. Tenga en cuenta que sólo existen tres puntos en myPointArray: (0, 0), (45, 25) y (25, 50). El método DrawPolygon cierra el polígono de forma automática ya que dibuja una línea desde (25, 50) hacia atrás hasta el punto inicial (0, 0). [C#] Point[] myPointArray = {new Point(0, 0), new Point(45, 25), new Point(25, 50)}; myGraphics.DrawPolygon(myPen, myPointArray); En la siguiente ilustración se muestra el polígono. Figura 3.12. Dibujo de un polígono con GDI+ 94 Textos Universitarios / Serie Docencia ________________________________________________________________________ DrawPolygon.aspx.cs private void btnGenerar_Click(object sender, System.EventArgs e) { string recHeight = txtHeight.Text; string recWidth = txtWidth.Text; Response.Write("<img border='0' src='ServerPolygon.aspx?valueH=" + recHeight +"&valueW=" + recWidth + "'>"); Response.Write("<p><font color=red>a Line Star and two Polygons!</font></p>"); } Listado 3.13. Código asociado con la forma DrawPolygon ServerPolygon.aspx.cs using using using using using using using using using using using using System; System.Collections; System.ComponentModel; System.Data; System.Drawing; System.Web; System.Web.SessionState; System.Web.UI; System.Web.UI.WebControls; System.Web.UI.HtmlControls; System.IO; System.Drawing.Imaging; namespace JCPGraphics { public class ServerPolygon : System.Web.UI.Page { int w1,h1; Color bgColor=Color.LightGray; private void Page_Load(object sender, System.EventArgs e) { w1 = UInt16.Parse(Request.QueryString["valueW"]); h1 = UInt16.Parse(Request.QueryString["valueH"]); // Create a Stream in memory to save the image MemoryStream memStream = canvasAndImage(); Response.Clear(); // Send the memory image to Browser in binary mode memStream.WriteTo(Response.OutputStream); } public MemoryStream canvasAndImage() { // Define a Rectangle to be the BG rectangle Rectangle bgRect = new Rectangle(0,0,w1,h1); // The bitmap Object used to work with images defined by // pixel data Bitmap pixelImage = new Bitmap(w1,h1); // 1) Will be used to build the new Graphics object 95 Jenaro C. Paz ________________________________________________________________________ // 2) Whatever you do with the Graphics object you afect // the image object! Graphics g = Graphics.FromImage(pixelImage); // Fill the interior of the bg rectangle g.FillRectangle(new SolidBrush(bgColor), bgRect); // +++++++++++++++Begins section related with this Server /* Pens to draw lines */ Pen aPen1 = new Pen(Color.MediumPurple, 3); Pen aPen2 = new Pen(Color.Fuchsia, 2); Pen aPen3 = new Pen(Color.LemonChiffon, 3); Pen aPen4 = new Pen(Color.LightCoral, 4); Pen aPen5 = new Pen(Color.MediumVioletRed, 5); PointF[] starArray = { new PointF(125.0F, 30.0F), new PointF(147.0F, 99.0F), new PointF(220.0F, 99.0F), new PointF(161.0F, 142.0F), new PointF(183.0F, 210.0F), new PointF(125.0F, 168.0F), new PointF(67.0F, 210.0F), new PointF(89.0F, 142.0F), new PointF(30.0F, 99.0F), new PointF(103.0F, 99.0F), new PointF(125.0F, 30.0F), }; PointF P1 =new PointF(125.0F, 30.0F); PointF P2 =new PointF(220.0F, 99.0F); PointF P3 =new PointF(183.0F, 210.0F); PointF P4 =new PointF(67.0F, 210.0F); PointF P5 =new PointF(30.0F, 99.0F); PointF P6 =new PointF(125.0F, 30.0F); PointF[] polyArray = { P1, P2, P3, P4, P5, P6 }; PointF p1 =new PointF(147.0F, 99.0F); PointF p2 =new PointF(161.0F, 142.0F); PointF p3 =new PointF(125.0F, 168.0F); PointF p4 =new PointF(89.0F, 142.0F); PointF p5 =new PointF(103.0F, 99.0F); PointF p6 =new PointF(147.0F, 99.0F); PointF[] poly2Array = { p1, p2, p3, p4, p5, p6 }; // Draw polygon g.DrawPolygon(aPen3,polyArray); g.DrawPolygon(aPen1,poly2Array); g.DrawLines(aPen2,starArray); // Dispose of objects aPen1.Dispose(); aPen2.Dispose(); aPen3.Dispose(); aPen4.Dispose(); 96 Textos Universitarios / Serie Docencia ________________________________________________________________________ aPen5.Dispose(); // // +++++++++++++++Ends section related with this Server MemoryStream aStream = new MemoryStream(); pixelImage.Save(aStream,ImageFormat.Png); // Bmp, Jpeg, Png, Gif return aStream; } | Web Form Designer Generated Code | } } Listado 3.14. Código asociado con la forma ServerPolygon El resultado de la interacción de estas dos formas se muestra en la Figura 3.13 que se muestra a continuación. Figura 3.13. Diferente tipo de polígonos sobre el lienzo 97 Jenaro C. Paz ________________________________________________________________________ 3.1.2.1.1.1 Dibujando Curvas sobre un lienzo Una curva spline cardinal es una secuencia de curvas individuales combinadas para formar una curva mayor. La curva spline se especifica mediante una matriz de puntos y un parámetro de tensión. Una curva spline cardinal pasa suavemente por cada punto de la matriz; no hay esquinas definidas ni cambios abruptos en la tensión de la curva. En la siguiente ilustración se muestra un conjunto de puntos y una curva spline cardinal que pasa por cada punto del conjunto. Figura 3.14. Curva spline definida por varios puntos Una curva spline física es un trozo fino de madera o de otro material flexible. Antes de la aparición de las curvas spline matemáticas, los diseñadores utilizaban curvas spline físicas para dibujar curvas. Un diseñador colocaba la curva spline en un trozo de papel y la delimitaba con respecto a un conjunto determinado de puntos. Después, el diseñador podía crear una curva dibujando a lo largo de la curva spline con un lápiz. Un conjunto determinado de puntos podría generar varias curvas, en función de las propiedades de la curva spline física. Por ejemplo, una curva spline con una resistencia alta a curvarse genera una curva distinta a la de una curva spline extremadamente flexible. Las fórmulas que se utilizan para calcular curvas spline matemáticas se basan en las propiedades de barras flexibles, de modo que las curvas creadas por curvas spline matemáticas son similares a las curvas que se crearon una vez con las curvas spline físicas. Del mismo modo que las curvas spline físicas de distinta tensión generan curvas distintas a través de un conjunto determinado de puntos, las curvas spline matemáticas con valores diferentes para el parámetro de tensión generan curvas diferentes a través de un conjunto determinado de puntos. En la siguiente ilustración se muestran cuatro curvas spline cardinales que pasan por el mismo conjunto de puntos. Se muestra la tensión de cada curva spline. Tenga en cuenta que una tensión de 0 se corresponde con una tensión física infinita, que obliga a la curva a tomar el camino más corto (líneas rectas) entre puntos. Una tensión de 1 corresponde a la ausencia de tensión física, que permite a la curva spline tomar el trazado de menor curvatura total. Con valores de tensión superiores a 1, la curva se comporta como un muelle comprimido, al que se empuja para tomar un trazado más largo. 98 Textos Universitarios / Serie Docencia ________________________________________________________________________ Figura 3.15. Aplicando diferentes tensiones a una curva spline Tenga en cuenta que las cuatro curvas spline de la ilustración anterior comparten la misma línea tangente en el punto inicial. La tangente es la línea que va desde el punto inicial hasta el siguiente punto de la curva. De forma similar, la tangente compartida en el punto final es la línea que va desde el punto final hasta el punto anterior de la curva. Para dibujar una curva spline cardinal, es necesario un objeto Graphics, un objeto Pen y un arreglo de objetos Point. El objeto Graphics proporciona el método DrawCurve, que dibuja la curva spline, y el objeto Pen almacena atributos de la curva spline, como el color y el ancho de línea. El arreglo de objetos Point almacena los puntos por los que pasará la curva. En el siguiente ejemplo se dibuja una curva spline cardinal que pasa por los puntos de myPointArray. La tensión es el tercer parámetro. [C#] myGraphics.DrawCurve(myPen, myPointArray, 1.5f); DrawCurves.aspx.cs private void btnBuild_Click(object sender, System.EventArgs e) { string recHeight = txtHeight.Text; string recWidth = txtWidth.Text; Response.Write("<img border='0' src='ServerCurves.aspx?valueH=" + recHeight + "&valueW=" + recWidth + "'>"); Response.Write("<p><font color=red>Drawing Open Curves!</font></p>"); } Listado 3.15. Codigo asociado a la forma DrawCurves.aspx ServerCurves.aspx.cs using using using using using using using using using using using System; System.Collections; System.ComponentModel; System.Data; System.Drawing; System.Web; System.Web.SessionState; System.Web.UI; System.Web.UI.WebControls; System.Web.UI.HtmlControls; System.IO; 99 Jenaro C. Paz ________________________________________________________________________ using System.Drawing.Imaging; namespace JCPGraphics { public class ServerCurves : System.Web.UI.Page { int w1,h1; Color bgColor=Color.LightGray; private void Page_Load(object sender, System.EventArgs e) { w1 = UInt16.Parse(Request.QueryString["valueW"]); h1 = UInt16.Parse(Request.QueryString["valueH"]); // Create a Stream in memory to save the image MemoryStream memStream = canvasAndImage(); Response.Clear(); // Send the memory image to Browser in binary mode memStream.WriteTo(Response.OutputStream); } public MemoryStream canvasAndImage() { // Define a Rectangle to be the BG rectangle Rectangle bgRect = new Rectangle(0,0,w1,h1); // The bitmap Object used to work with images defined by // pixel data Bitmap pixelImage = new Bitmap(w1,h1); // 1) Will be used to build the new Graphics object // 2) Whatever you do with the Graphics object you afect // the image object! Graphics g = Graphics.FromImage(pixelImage); // Fill the interior of the bg rectangle g.FillRectangle(new SolidBrush(bgColor), bgRect); // +++++++++++++++Begins section related with this Server // /* Pens to draw lines */ Pen aPen1 = new Pen(Color.MediumPurple, 3); Pen aPen2 = new Pen(Color.Fuchsia, 2); Pen aPen3 = new Pen(Color.LemonChiffon, 3); PointF[] starArray = { new PointF(195.0F, 30.0F), new PointF(217.0F, 99.0F), new PointF(290.0F, 99.0F), new PointF(231.0F, 142.0F), new PointF(253.0F, 210.0F), new PointF(195.0F, 168.0F), new PointF(137.0F, 210.0F), new PointF(159.0F, 142.0F), new PointF(100.0F, 99.0F), new PointF(173.0F, 99.0F), new PointF(195.0F, 30.0F), }; PointF P1 =new PointF(195.0F, 30.0F); PointF P2 =new PointF(290.0F, 99.0F); PointF P3 =new PointF(253.0F, 210.0F); 100 Textos Universitarios / Serie Docencia ________________________________________________________________________ PointF P4 =new PointF(137.0F, 210.0F); PointF P5 =new PointF(100.0F, 99.0F); PointF P6 =new PointF(195.0F, 30.0F); PointF[] polyArray = { P1, P2, P3, P4, P5, P6 }; PointF p1 =new PointF(217.0F, 99.0F); PointF p2 =new PointF(231.0F, 142.0F); PointF p3 =new PointF(195.0F, 168.0F); PointF p4 =new PointF(159.0F, 142.0F); PointF p5 =new PointF(173.0F, 99.0F); PointF p6 =new PointF(217.0F, 99.0F); PointF[] poly2Array = { p1, p2, p3, p4, p5 }; g.DrawCurve(aPen3,polyArray, 1,3,3.0F); g.DrawCurve(aPen1,poly2Array, 1.5F); g.DrawCurve(aPen2,starArray,1,8, 1.0F); aPen1.Dispose(); aPen2.Dispose(); aPen3.Dispose(); // // +++++++++++++++Ends section related with this Server MemoryStream aStream = new MemoryStream(); pixelImage.Save(aStream,ImageFormat.Png); // Bmp, Jpeg, Png, Gif return aStream; } | Web Form Designer Generated Code | } } Listado 3.16. Código asociado con la forma ServerCurves.aspx El resultado de la interacción de estas dos formas se muestra en la Figura 3.16 que se muestra a continuación. Figura 3.16. Curvas abiertas sobre el lienzo 101 Jenaro C. Paz ________________________________________________________________________ Sustituyendo el método canvasAndImage() por este otro public MemoryStream canvasAndImage() { // Define a Rectangle to be the BG rectangle Rectangle bgRect = new Rectangle(0,0,w1,h1); // The bitmap Object used to work with images defined by // pixel data Bitmap pixelImage = new Bitmap(w1,h1); // 1) Will be used to build the new Graphics object // 2) Whatever you do with the Graphics object you afect // the image object! Graphics g = Graphics.FromImage(pixelImage); // Fill the interior of the bg rectangle g.FillRectangle(new SolidBrush(bgColor), bgRect); // +++++++++++++++Begins section related with this Server // /* Pens to draw lines */ Pen aPen1 = new Pen(Color.MediumPurple, 3); Pen aPen2 = new Pen(Color.Fuchsia, 2); Pen aPen3 = new Pen(Color.LightCoral, 4); PointF[] starArray = { new PointF(195.0F, 30.0F), new PointF(217.0F, 99.0F), new PointF(290.0F, 99.0F), new PointF(231.0F, 142.0F), new PointF(253.0F, 210.0F), new PointF(195.0F, 168.0F), new PointF(137.0F, 210.0F), new PointF(159.0F, 142.0F), new PointF(100.0F, 99.0F), new PointF(173.0F, 99.0F), //new PointF(195.0F, 30.0F), }; PointF P1 =new PointF(195.0F, 30.0F); PointF P2 =new PointF(290.0F, 99.0F); PointF P3 =new PointF(253.0F, 210.0F); PointF P4 =new PointF(137.0F, 210.0F); PointF P5 =new PointF(100.0F, 99.0F); PointF P6 =new PointF(195.0F, 30.0F); PointF[] polyArray = { P1, P2, P3, P4, P5 }; PointF p1 =new PointF(217.0F, 99.0F); PointF p2 =new PointF(231.0F, 142.0F); PointF p3 =new PointF(195.0F, 168.0F); PointF p4 =new PointF(159.0F, 142.0F); PointF p5 =new PointF(173.0F, 99.0F); PointF p6 =new PointF(217.0F, 99.0F); PointF[] poly2Array = { p1, p2, p3, p4, p5 }; 102 Textos Universitarios / Serie Docencia ________________________________________________________________________ // Draw three closed curves g.DrawClosedCurve(aPen2, starArray, 2.0F,System.Drawing.Drawing2D.FillMode.Winding); g.DrawClosedCurve(aPen3, polyArray, 2.5F,System.Drawing.Drawing2D.FillMode.Winding); g.DrawClosedCurve(aPen1,poly2Array, 3.0F,System.Drawing.Drawing2D.FillMode.Winding); // Dispose of objects aPen1.Dispose(); aPen2.Dispose(); aPen3.Dispose(); // // +++++++++++++++Ends section related with this Server MemoryStream aStream = new MemoryStream(); pixelImage.Save(aStream,ImageFormat.Png); // Bmp, Jpeg, Png, Gif return aStream; } Listado 3.16b. Código alterno asociado con la forma ServerCurves.aspx Se obtiene una imagen con curvas cerradas sobre un lienzo como lo muestra la Figura 3.17. Figura 3.17. Curvas cerradas sobre un lienzo 3.1.2.1.1.1 Dibujando Curvas Bézier sobre un lienzo Una curva spline de Bézier es una curva que se especifica con cuatro puntos: dos puntos finales (p1 y p2) y dos puntos de control (c1 y c2). La curva comienza en p1 y acaba en p2. La curva no pasa por los puntos de control, pero éstos se comportan como imanes, y tiran de la curva en ciertas direcciones e influyen en el modo en que la curva se dobla. En la siguiente ilustración se muestra una curva de Bézier con los extremos y los puntos de control. 103 Jenaro C. Paz ________________________________________________________________________ Figura 3.18. Curva Bezier entre p1 y p2 con puntos de control c1 y c2 Tenga en cuenta que la curva comienza en p1 y avanza hacia el punto de control c1. La línea tangente a la curva en p1 es la línea que va de p1 a c1. Tenga en cuenta también que la línea tangente en el extremo p2 es la línea que va de c2 a p2. Para dibujar una curva spline de Bézier, son necesarios un objeto Graphics y un objeto Pen. El objeto Graphics proporciona el método DrawBezier, y el objeto Pen almacena atributos como el ancho y el color de la línea que se utiliza para representar la curva. El objeto Pen se pasa como uno de los argumentos del método DrawBezier. El resto de los argumentos que se pasan al método DrawBezier son los extremos y los puntos de control. En el siguiente ejemplo se dibuja una curva spline de Bézier con un punto inicial (0, 0), dos puntos de control (40, 20) y (80, 150) y un punto final (100, 10): [C#] myGraphics.DrawBezier(myPen, 0, 0, 40, 20, 80, 150, 100, 10); En la siguiente ilustración se muestra la curva, los puntos de control y dos líneas tangentes. Figura 3.19. Una curva spline de Bezier mediante GDI+ Pierre Bézier desarrolló por primera vez las curvas spline de Bézier para el diseño en la industria del automóvil. Desde entonces, han resultado muy útiles en muchos tipos de CAD (computer-aided design, diseño asistido por computadora) y también se utilizan para definir los contornos de fuentes. Las curvas spline de Bézier pueden generar una gran variedad de formas, algunas de las cuales se muestran en la siguiente ilustración. 104 Textos Universitarios / Serie Docencia ________________________________________________________________________ Figura 3.20. Diferentes curves Bezier DrawBezier.aspx.cs private void btnBuild_Click(object sender, System.EventArgs e) { string recHeight = txtHeight.Text; string recWidth = txtWidth.Text; Response.Write("<img border='0' src='ServerBezier.aspx?valueH=" + recHeight + "&valueW=" + recWidth + "'>"); Response.Write("<p><font color=red>Diferent Beziers!</font></p>"); } Listado 3.17. Codigo asociado con la forma DrawBezier.aspx ServerBezier.aspx.cs using using using using using using using using using using using using System; System.Collections; System.ComponentModel; System.Data; System.Drawing; System.Web; System.Web.SessionState; System.Web.UI; System.Web.UI.WebControls; System.Web.UI.HtmlControls; System.IO; System.Drawing.Imaging; namespace JCPGraphics { public class ServerBezier : System.Web.UI.Page { int w1,h1; Color bgColor=Color.LightGray; private void Page_Load(object sender, System.EventArgs e) { w1 = UInt16.Parse(Request.QueryString["valueW"]); h1 = UInt16.Parse(Request.QueryString["valueH"]); // Create a Stream in memory to save the image MemoryStream memStream = canvasAndImage(); Response.Clear(); // Send the memory image to Browser in binary mode memStream.WriteTo(Response.OutputStream); } 105 Jenaro C. Paz ________________________________________________________________________ public MemoryStream canvasAndImage() { // Define a Rectangle to be the BG rectangle Rectangle bgRect = new Rectangle(0,0,w1,h1); // The bitmap Object used to work with images defined by // pixel data Bitmap pixelImage = new Bitmap(w1,h1); // 1) Will be used to build the new Graphics object // 2) Whatever you do with the Graphics object you afect // the image object! Graphics g = Graphics.FromImage(pixelImage); // Fill the interior of the bg rectangle g.FillRectangle(new SolidBrush(bgColor), bgRect); // +++++++++++++++Begins section related with this Server // Pens to draw lines Pen aPen1 = new Pen(Color.MediumPurple, 2); Pen aPen2 = new Pen(Color.Fuchsia, 2); Pen aPen3 = new Pen(Color.LemonChiffon, 3); // Draw a Bezier using Points Point pt1 = new Point(20, 260); Point pt2 = new Point(380, 40); Point pt3 = new Point(140,30); Point pt4 = new Point(200,350); g.DrawBezier(aPen2, pt1,pt3,pt4,pt2); // Draw a Bezier using an Array of Points PointF p1 = new PointF(20.0F, 50.0F); PointF p2 = new PointF(60.0F, 80.0F); PointF p3 = new PointF(80.0F, 36.0F); PointF p4 = new PointF(120.0F, 180.0F); PointF p5 = new PointF(220.0F, 150.0F); PointF p6 = new PointF(350.0F, 260.0F); PointF p7 = new PointF(210.0F, 210.0F); PointF[] ptsBezier = { p1, p2, p3, p4, p5, p6, p7 }; g.DrawBeziers(aPen3, ptsBezier); // Draw Béziers g.DrawBezier(aPen1, 30, 30, 80, 70, 120, 190, 140, 70); aPen1.Dispose(); aPen2.Dispose(); aPen3.Dispose(); // // +++++++++++++++Ends section related with this Server MemoryStream aStream = new MemoryStream(); pixelImage.Save(aStream,ImageFormat.Png); // Bmp, Jpeg, Png, Gif return aStream; } | Web Form Designer Generated Code | } } Listado 3.18. Codigo asociado a la forma ServerBezier.aspx 106 Textos Universitarios / Serie Docencia ________________________________________________________________________ El resultado de la interacción de las dos formas se muestra en la Figura 3.21. Figura 3.21. Diferentes curves Bezier sobre el lienzo 3.1.2.1.1.1 Dibujando Trazados sobre un lienzo Los trazados se forman mediante la combinación de líneas, rectángulos y curvas simples. En GDI+, el objeto GraphicsPath permite recopilar una secuencia de estas unidades de creación en una única unidad. La secuencia completa de líneas, rectángulos, polígonos y curvas puede dibujarse pues con una llamada al método DrawPath de la clase Graphics En la siguiente ilustración se muestra un trazado creado mediante la combinación de una línea, un arco, una curva spline de Bézier y una curva spline cardinal. Figura 3.22. Ejemplo de Trazado 107 Jenaro C. Paz ________________________________________________________________________ La clase GraphicsPath proporciona los siguientes métodos para la creación de una secuencia de elementos que se van a dibujar: AddLine, AddRectangle, AddEllipse, AddArc, AddPolygon, AddCurve (para curvas spline cardinales) y AddBezier. Cada uno de estos métodos está sobrecargado, es decir, cada método admite varias listas de parámetros distintas. Por ejemplo, una variación del método AddLine recibe cuatro enteros, y otra variación del método AddLine recibe dos objetos Point. Los métodos que existen para agregar líneas, rectángulos y curvas spline de Bézier a un trazado disponen de varios métodos asociados que agregan diversos elementos al trazado en una única llamada: AddLines, AddRectangles y AddBeziers. Además, los métodos AddCurve y AddArc disponen de métodos asociados, AddClosedCurve y AddPie, que agregan una curva cerrada o un sector al trazado. Para dibujar un trazado, son necesarios un objeto Graphics, un objeto Pen y un objeto GraphicsPath. El objeto Graphics proporciona el método DrawPath, y el objeto Pen almacena atributos como el ancho y el color de la línea que se utiliza para representar el trazado. El objeto GraphicsPath almacena la secuencia de líneas y curvas que componen el trazado. El objeto Pen y el objeto GraphicsPath se pasan como argumentos del método DrawPath. En el siguiente ejemplo se dibuja un trazado que consta de una línea, una elipse y una curva spline de Bézier: [C#] myGraphicsPath.AddLine(0, 0, 30, 20); myGraphicsPath.AddEllipse(20, 20, 20, 40); myGraphicsPath.AddBezier(30, 60, 70, 60, 50, 30, 100, 10); myGraphics.DrawPath(myPen, myGraphicsPath); En la siguiente ilustración se muestra el trazado. Figura 3.23. Trazado generado con GDI+ Además de agregar líneas, rectángulos y curvas a un trazado, se pueden agregar trazados a un trazado. Esto permite combinar los trazados existentes para formar trazados enormes y complejos. [C#] myGraphicsPath.AddPath(graphicsPath1, false); myGraphicsPath.AddPath(graphicsPath2, false); 108 Textos Universitarios / Serie Docencia ________________________________________________________________________ DrawPath.aspx.cs private void btnGenerar_Click(object sender, System.EventArgs e) { string recHeight = txtHeight.Text; string recWidth = txtWidth.Text; Response.Write("<img border='0' src='ServerPath.aspx?valueH=" + recHeight + "&valueW=" + recWidth + "'>"); Response.Write("<p><font color=red>Making an Image with <I>Path</I>!</font></p>"); } Listado 3.19. Código asociado con la forma DrawPath.aspx ServerPath.aspx.cs using using using using using using using using using using using using System; System.Collections; System.ComponentModel; System.Data; System.Drawing; System.Web; System.Web.SessionState; System.Web.UI; System.Web.UI.WebControls; System.Web.UI.HtmlControls; System.IO; System.Drawing.Imaging; namespace JCPGraphics { public class ServerPath : System.Web.UI.Page { int w1,h1; Color bgColor=Color.LightGray; private void Page_Load(object sender, System.EventArgs e) { w1 = UInt16.Parse(Request.QueryString["valueW"]); h1 = UInt16.Parse(Request.QueryString["valueH"]); // Create a Stream in memory to save the image MemoryStream memStream = canvasAndImage(); Response.Clear(); // Send the memory image to Browser in binary mode memStream.WriteTo(Response.OutputStream); } public MemoryStream canvasAndImage() { // Define a Rectangle to be the BG rectangle Rectangle bgRect = new Rectangle(0,0,w1,h1); // The bitmap Object used to work with images defined by // pixel data Bitmap pixelImage = new Bitmap(w1,h1); 109 Jenaro C. Paz ________________________________________________________________________ // 1) Will be used to build the new Graphics object // 2) Whatever you do with the Graphics object you afect // the image object! Graphics g = Graphics.FromImage(pixelImage); // Fill the interior of the bg rectangle g.FillRectangle(new SolidBrush(bgColor), bgRect); // +++++++++++++++Begins section related with this Server // // Pens to draw lines Pen aPen1 = new Pen(Color.MediumPurple, 2); Pen aPen2 = new Pen(Color.Fuchsia, 2); Pen aPen3 = new Pen(Color.LemonChiffon, 3); Pen aPen4 = new Pen(Color.LightCoral, 4); Pen aPen5 = new Pen(Color.MediumVioletRed, 5); // Draw line using PointF structure PointF ptf1 = new PointF(20.0F, 20.0F); PointF ptf2 = new PointF(200.0F, 200.0F); GraphicsPath path = new GraphicsPath(); // Add a line to the path path.AddLine(ptf1,ptf2); // Add an ellipse to the path path.AddEllipse(100, 50, 100, 100); // Add three more lines path.AddLine(X1, Y1, X2, Y2); path.AddLine(Xa, Ya, Xb, Yb); //path.AddLine(195, 120, 300, 120); // Create a rectangle and call // AddRectangle Rectangle rect = new Rectangle(50, 110, 180, 60); path.AddRectangle(rect); // Draw path g.DrawPath(aPen1, path); aPen1.Dispose(); aPen2.Dispose(); aPen3.Dispose(); aPen4.Dispose(); aPen5.Dispose(); // // +++++++++++++++Ends section related with this Server MemoryStream aStream = new MemoryStream(); pixelImage.Save(aStream,ImageFormat.Png); // Bmp, Jpeg, Png, Gif return aStream; } | Web Form Designer Generated Code | } } Listado 3.20. Código asociado a la forma ServerPath.aspx El resultado entre la interacción de las dos formas se muestra en la Figura 3.24. 110 Textos Universitarios / Serie Docencia ________________________________________________________________________ Figura 3.24. Trazado sobre lienzo 3.1.2.1.1.1 Dibujando Iconos sobre un lienzo DrawIcon.aspx.cs private void btnBuild_Click(object sender, System.EventArgs e) { string recHeight = txtHeight.Text; string recWidth = txtWidth.Text; Response.Write("<img border='0' src='ServerIcon.aspx?valueH=" + recHeight + "&valueW=" + recWidth + "'>"); Response.Write("<p><font color=red>Draw Icons!</font></p>"); } Listado 3.21. Codigo asociado con la forma DrawIcon.aspx ServerIcon.aspx.cs using using using using using using using using System.Drawing; System.Web; System.Web.SessionState; System.Web.UI; System.Web.UI.WebControls; System.Web.UI.HtmlControls; System.IO; System.Drawing.Imaging; 111 Jenaro C. Paz ________________________________________________________________________ namespace JCPGraphics { public class ServerIcon : System.Web.UI.Page { int w1,h1; Color bgColor=Color.LightGray; private void Page_Load(object sender, System.EventArgs e) { w1 = UInt16.Parse(Request.QueryString["valueW"]); h1 = UInt16.Parse(Request.QueryString["valueH"]); // Create a Stream in memory to save the image MemoryStream memStream = canvasAndImage(); Response.Clear(); // Send the memory image to Browser in binary mode memStream.WriteTo(Response.OutputStream); } public MemoryStream canvasAndImage() { // Define a Rectangle to be the BG rectangle Rectangle bgRect = new Rectangle(0,0,w1,h1); // The bitmap Object used to work with images defined by // pixel data Bitmap pixelImage = new Bitmap(w1,h1); // 1) Will be used to build the new Graphics object // 2) Whatever you do with the Graphics object you afect // the image object! Graphics g = Graphics.FromImage(pixelImage); // Fill the interior of the bg rectangle g.FillRectangle(new SolidBrush(bgColor), bgRect); // +++++++++++++++Begins section related with this Server // // Read the Icons from Folder (root) Icon icon1 = new Icon(Server.MapPath("ar.ico")); Icon icon2 = new Icon(Server.MapPath("be.ico")); Icon icon3 = new Icon(Server.MapPath("br.ico")); Icon icon4 = new Icon(Server.MapPath("ca.ico")); Icon icon5 = new Icon(Server.MapPath("mx.ico")); Icon icon6 = new Icon(Server.MapPath("uk.ico")); int x1 = 20; int y1 = 50; int x2 = 60; int y2 = 90; int x3 = 100; int y3 = 130; int x4 = 140; int y4 = 170; int x5 = 180; int y5 = 210; int x6 = 220; int y6 = 250; g.DrawIcon(icon1, x1, y1); g.DrawIcon(icon2, x2, y2); g.DrawIcon(icon3, x3, y3); g.DrawIcon(icon4, x4, y4); 112 Textos Universitarios / Serie Docencia ________________________________________________________________________ g.DrawIcon(icon5, x5, y5); g.DrawIcon(icon6, x6, y6); // // +++++++++++++++Ends section related with this Server MemoryStream aStream = new MemoryStream(); pixelImage.Save(aStream,ImageFormat.Png); // Bmp, Jpeg, Png, Gif return aStream; } | Web Form Designer Generated Code | } } Listado 3.22. Codigo asociado con la forma ServerIcon.aspx El resultado entre la interacción de las dos formas se muestra en la Figura 3.25. Figura 3.25. Varios Iconos dibujados sobre el lienzo 113 Jenaro C. Paz ________________________________________________________________________ 3.1.2.1.1.1 Dibujando Imágenes sobre un lienzo DrawImage.aspx.cs private void btnBuild_Click(object sender, System.EventArgs e) { string recHeight = txtHeight.Text; string recWidth = txtWidth.Text; Response.Write("<img border='0' src='ServerImage.aspx?valueH=" + recHeight +"&valueW=" + recWidth + "'>"); Response.Write("<p><font color=red>Draw an Image!</font></p>"); } Listado 3.23. Código asociado con la forma DrawImage.aspx ServerImage.aspx.cs using using using using using using using using System.Drawing; System.Web; System.Web.SessionState; System.Web.UI; System.Web.UI.WebControls; System.Web.UI.HtmlControls; System.IO; System.Drawing.Imaging; namespace JCPGraphics { public class ServerImage : System.Web.UI.Page { int w1,h1; Color bgColor=Color.LightGray; private void Page_Load(object sender, System.EventArgs e) { w1 = UInt16.Parse(Request.QueryString["valueW"]); h1 = UInt16.Parse(Request.QueryString["valueH"]); // Create a Stream in memory to save the image MemoryStream memStream = canvasAndImage(); Response.Clear(); // Send the memory image to Browser in binary mode memStream.WriteTo(Response.OutputStream); } public MemoryStream canvasAndImage() { // Define a Rectangle to be the BG rectangle Rectangle bgRect = new Rectangle(0,0,w1,h1); // The bitmap Object used to work with images defined by // pixel data Bitmap pixelImage = new Bitmap(w1,h1); // 1) Will be used to build the new Graphics object // 2) Whatever you do with the Graphics object you afect // the image object! 114 Textos Universitarios / Serie Docencia ________________________________________________________________________ Graphics g = Graphics.FromImage(pixelImage); // Fill the interior of the bg rectangle g.FillRectangle(new SolidBrush(bgColor), bgRect); // +++++++++++++++Begins section related with this Server // // Load an Image from root Folder Bitmap imageBitmap = new Bitmap(Server.MapPath("Textura.png")); g.DrawImage(imageBitmap, 30, 30, imageBitmap.Width, imageBitmap.Height); // // +++++++++++++++Ends section related with this Server MemoryStream aStream = new MemoryStream(); pixelImage.Save(aStream,ImageFormat.Png); // Bmp, Jpeg, Png, Gif return aStream; } | Web Form Designer Generated Code | } } Listado 3.24. Código asociado con la forma ServerImage.aspx El resultado de la interacción entre las dos formas se muestra en la Figura 3.26. Figura 3.26. Dibujo de una imagen sobre el lienzo 115 Jenaro C. Paz ________________________________________________________________________ 3.1.2.1.1.1 Dibujando Pasteles sobre un lienzo DrawPies.aspx.cs private void btnGenerar_Click(object sender, System.EventArgs e) { string recHeight = txtHeight.Text; string recWidth = txtWidth.Text; Response.Write("<img border='0' src='ServerPies.aspx?valueH=" + recHeight + "&valueW=" + recWidth + "'>"); Response.Write("<p><font color=red>Three Pies!</font></p>"); } Listado 3.25. Código asociado con la forma DrawPies.aspx ServerPies.aspx.cs using using using using using using using using System.Drawing; System.Web; System.Web.SessionState; System.Web.UI; System.Web.UI.WebControls; System.Web.UI.HtmlControls; System.IO; System.Drawing.Imaging; namespace JCPGraphics { public class ServerPies : System.Web.UI.Page { int w1,h1; Color bgColor=Color.LightGray; private void Page_Load(object sender, System.EventArgs e) { w1 = UInt16.Parse(Request.QueryString["valueW"]); h1 = UInt16.Parse(Request.QueryString["valueH"]); // Create a Stream in memory to save the image MemoryStream memStream = canvasAndImage(); Response.Clear(); // Send the memory image to Browser in binary mode memStream.WriteTo(Response.OutputStream); } public MemoryStream canvasAndImage() { // Define a Rectangle to be the BG rectangle Rectangle bgRect = new Rectangle(0,0,w1,h1); // The bitmap Object used to work with images defined by // pixel data Bitmap pixelImage = new Bitmap(w1,h1); // 1) Will be used to build the new Graphics object // 2) Whatever you do with the Graphics object you afect // the image object! Graphics g = Graphics.FromImage(pixelImage); 116 Textos Universitarios / Serie Docencia ________________________________________________________________________ // Fill the interior of the bg rectangle g.FillRectangle(new SolidBrush(bgColor), bgRect); // +++++++++++++++Begins section related with this Server /* Pens to draw lines */ Pen aPen1 = new Pen(Color.MediumPurple, 1); Pen aPen2 = new Pen(Color.Fuchsia, 2); Pen aPen3 = new Pen(Color.LemonChiffon, 3); Pen aPen4 = new Pen(Color.LightCoral, 4); Pen aPen5 = new Pen(Color.MediumVioletRed, 5); g.DrawPie(aPen2,myRect.X+4,myRect.Y+4,myRect.Width-40,myRect.Height-40, 65,90); g.DrawPie(aPen3,20, 30, 120, 120,280,110); g.DrawPie(aPen4,170.0F, 20.0F, 140.0F, 140.0F, 20,170); // Dispose of objects aPen1.Dispose(); aPen2.Dispose(); aPen3.Dispose(); aPen4.Dispose(); aPen5.Dispose(); // +++++++++++++++Ends section related with this Server MemoryStream aStream = new MemoryStream(); pixelImage.Save(aStream,ImageFormat.Png); // Bmp, Jpeg, Png, Gif return aStream; } | Web Form Designer Generated Code | } } Listado 3.26. Código asociado con la forma ServerPies.aspx El resultado se ejemplifica con la siguiente Figura 3.27. Figura 3.27. Dibujo de Pies sobre el lienzo 117 Jenaro C. Paz ________________________________________________________________________ 3.1.2.1.1.1 Dibujando Cadenas sobre un lienzo DrawLetters.aspx.cs private void btnGenerar_Click(object sender, System.EventArgs e) { string recHeight = txtHeight.Text; string recWidth = txtWidth.Text; Response.Write("<img border='0' src='ServerStrings.aspx?valueH=" + recHeight +"&valueW=" + recWidth + "'>"); Response.Write("<p><font color=red>Just Read This!</font></p>"); } Listado 3.27. Codigo asociado con la forma DrawLetters.aspx ServerStrings.aspx.cs using using using using using using using using System.Drawing; System.Web; System.Web.SessionState; System.Web.UI; System.Web.UI.WebControls; System.Web.UI.HtmlControls; System.IO; System.Drawing.Imaging; namespace JCPGraphics { public class ServerStrings : System.Web.UI.Page { int w1,h1; Color bgColor=Color.LightGray; private void Page_Load(object sender, System.EventArgs e) { w1 = UInt16.Parse(Request.QueryString["valueW"]); h1 = UInt16.Parse(Request.QueryString["valueH"]); // Create a Stream in memory to save the image MemoryStream memStream = canvasAndImage(); Response.Clear(); // Send the memory image to Browser in binary mode memStream.WriteTo(Response.OutputStream); } public MemoryStream canvasAndImage() { // Define a Rectangle to be the BG rectangle Rectangle bgRect = new Rectangle(0,0,w1,h1); // The bitmap Object used to work with images defined by // pixel data Bitmap pixelImage = new Bitmap(w1,h1); // 1) Will be used to build the new Graphics object // 2) Whatever you do with the Graphics object you afect // the image object! Graphics g = Graphics.FromImage(pixelImage); // Fill the interior of the bg rectangle 118 Textos Universitarios / Serie Docencia ________________________________________________________________________ g.FillRectangle(new SolidBrush(bgColor), bgRect); // +++++++++++++++Begins section related with this Server g.DrawString("Drawing GDI+ Strings for the Web!", new Font("Verdana", 14), new SolidBrush(Color.Blue), new Point(42, 20)); StringFormat drawFormat = new StringFormat(); // Set string format flag to direction vertical, // which draws text vertically drawFormat.FormatFlags = StringFormatFlags.DirectionVertical; // Draw string g.DrawString("Drawing Strings", new Font("Tahoma", 14), Brushes.Purple, 20, 20, drawFormat); // +++++++++++++++Ends section related with this Server MemoryStream aStream = new MemoryStream(); pixelImage.Save(aStream,ImageFormat.Png); // Bmp, Jpeg, Png, Gif return aStream; } | Web Form Designer Generated Code | } } Listado 3.28. Código asociado a la forma ServerStrings.aspx El resultado de la interacción entre las dos formas se muestra en la Figura 3.28. Figura 3.28. Dibujo de cadenas de caracteres sobre el lienzo Si cambiamos el código en el programa anterior , para ahora tener: // +++++++++++++++Begins section related with this Server g.DrawString("Color Name :"+ bgColor.Name + ", A:"+bgColor.A.ToString() + ", R:"+bgColor.R.ToString() + 119 Jenaro C. Paz ________________________________________________________________________ ", B:"+bgColor.B.ToString() + ", G:"+bgColor.G.ToString(),new Font("Verdana", 14), new SolidBrush(Color.Blue), new Point(42, 20) ); float h = bgColor.GetHue(); float s = bgColor.GetSaturation(); float v = bgColor.GetBrightness(); g.DrawString("Hue: "+ h.ToString() + "\n" + "Saturation: "+ s.ToString() + "\n" + "Brightness: "+ v.ToString(),new Font("Verdana", 14), new SolidBrush(Color.Blue), new Point(42, 70) ); // +++++++++++++++Ends section related with this Server Listado 3.29. Código asociado a la forma ServerStrings.aspx modificado Obtendremos un lienzo de un color especificado por el usuario en el cual se despliegan sus componentes de Color en los dos sistemas ARGB y HSV. Figura 3.29. Componentes del color en cadenas de caracteres sobre el lienzo 3.1.2.2 Métodos Públicos para rellenar FillClosedCurve (1) FillEllipse (2) 120 Sobrecargado. Rellena el interior de una curva spline cardinal cerrada, definida por una matriz de estructuras Point. Sobrecargado. Rellena el interior de una Textos Universitarios / Serie Docencia ________________________________________________________________________ FillPath (3) FillPie (4) FillPolygon (5) FillRectangle (6) FillRectangles (7) elipse definida por un rectángulo de delimitación especificado por un par de coordenadas, un valor de alto y un valor de ancho. Rellena el interior de un objeto GraphicsPath. Sobrecargado. Rellena el interior de una sección de gráfico circular definida por una elipse, determinada por un par de coordenadas, unos valores de ancho y alto y dos líneas radiales. Sobrecargado. Rellena el interior de un polígono definido por una matriz de puntos, especificados por estructuras Point. Sobrecargado. Rellena el interior de un rectángulo especificado por un par de coordenadas, un valor de ancho y un valor de alto. Sobrecargado. Rellena el interior de una serie de rectángulos especificados por estructuras Rectangle. 3.1.2.2.1 Rellenando el interior de formas dibujadas en un lienzo En esta sección se presentan diferentes formas Web y su código adjunto para ejemplificar los métodos de relleno (1) al (7) de la sección 3.1.2.2 (Métodos públicos para rellenar). 3.1.2.2.1.1 Rellenando curvas cerradas FillCCurves.aspx.cs private void btnGenerar_Click(object sender, System.EventArgs e) { string recHeight = txtHeight.Text; string recWidth = txtWidth.Text; Response.Write("<img border='0' src='ServerFillCCurves.aspx?valueH=" + recHeight + "&valueW=" + recWidth + "'>"); Response.Write("<p><font color=red>Fill Closed Curves!</font></p>"); } Listado 3.30. Codigo asociado a la forma FillCCurves.aspx ServerFillCCurves.aspx.cs using System; 121 Jenaro C. Paz ________________________________________________________________________ using using using using using using using using using using using System.Collections; System.ComponentModel; System.Data; System.Drawing; System.Web; System.Web.SessionState; System.Web.UI; System.Web.UI.WebControls; System.Web.UI.HtmlControls; System.IO; System.Drawing.Imaging; namespace JCPGraphics { public class ServerFillCCurves : System.Web.UI.Page { int w1,h1; Color bgColor=Color.LightGray; private void Page_Load(object sender, System.EventArgs e) { w1 = UInt16.Parse(Request.QueryString["valueW"]); h1 = UInt16.Parse(Request.QueryString["valueH"]); // Create a Stream in memory to save the image MemoryStream memStream = canvasAndImage(); Response.Clear(); // Send the memory image to Browser in binary mode memStream.WriteTo(Response.OutputStream); } public MemoryStream canvasAndImage() { // Define a Rectangle to be the BG rectangle Rectangle bgRect = new Rectangle(0,0,w1,h1); // The bitmap Object used to work with images defined by // pixel data Bitmap pixelImage = new Bitmap(w1,h1); // 1) Will be used to build the new Graphics object // 2) Whatever you do with the Graphics object you afect // the image object! Graphics g = Graphics.FromImage(pixelImage); // Fill the interior of the bg rectangle g.FillRectangle(new SolidBrush(bgColor), bgRect); // +++++++++++++++Begins section related with this Server SolidBrush lemonBrush = new SolidBrush(Color.LemonChiffon); SolidBrush fuchsiaBrush = new SolidBrush(Color.Fuchsia); SolidBrush coralBrush = new SolidBrush(Color.LightCoral); PointF[] starArray = { new PointF(195.0F, new PointF(217.0F, new PointF(290.0F, new PointF(231.0F, new PointF(253.0F, new PointF(195.0F, new PointF(137.0F, new PointF(159.0F, 122 30.0F), 99.0F), 99.0F), 142.0F), 210.0F), 168.0F), 210.0F), 142.0F), Textos Universitarios / Serie Docencia ________________________________________________________________________ new PointF(100.0F, 99.0F), new PointF(173.0F, 99.0F), }; PointF PointF PointF PointF PointF PointF P1 P2 P3 P4 P5 P6 =new =new =new =new =new =new PointF(195.0F, PointF(290.0F, PointF(253.0F, PointF(137.0F, PointF(100.0F, PointF(195.0F, 30.0F); 99.0F); 210.0F); 210.0F); 99.0F); 30.0F); PointF[] polyArray = { P1, P2, P3, P4, P5 }; g.FillClosedCurve(lemonBrush,polyArray, System.Drawing.Drawing2D.FillMode.Winding, 2.0F); g.FillClosedCurve(coralBrush, polyArray, System.Drawing.Drawing2D.FillMode.Winding, 1.0F); g.FillClosedCurve(fuchsiaBrush, starArray, System.Drawing.Drawing2D.FillMode.Winding, 0.8F); // +++++++++++++++Ends section related with this Server MemoryStream aStream = new MemoryStream(); pixelImage.Save(aStream,ImageFormat.Png); // Bmp, Jpeg, Png, Gif return aStream; } | Web Form Designer Generated Code | } } Listado 3.31. Código asociado con la forma ServerFillCCurves.aspx El resultado de la interacción entre estas dos formas genera la imagen mostrada en la Figura 3.30. Figura 3.30. Rellenado de curvas cerradas 123 Jenaro C. Paz ________________________________________________________________________ 3.1.2.2.1.2 Rellenando elipses FillEllipses.aspx.cs private void btnGenerar_Click(object sender, System.EventArgs e) { string recHeight = txtHeight.Text; string recWidth = txtWidth.Text; Response.Write("<img border='0' src='ServerFillEllipses.aspx?valueH=" + recHeight + "&valueW=" + recWidth + "'>"); Response.Write("<p><font color=red>Fill Closed Curves!</font></p>"); } Listado 3.32. Código asociado a la forma FillEllipses.aspx ServerFillEllipses.aspx.cs using using using using using using using using using using using using System; System.Collections; System.ComponentModel; System.Data; System.Drawing; System.Web; System.Web.SessionState; System.Web.UI; System.Web.UI.WebControls; System.Web.UI.HtmlControls; System.IO; System.Drawing.Imaging; namespace JCPGraphics { public class ServerFillEllipses : System.Web.UI.Page { int w1,h1; Color bgColor=Color.LightGray; private void Page_Load(object sender, System.EventArgs e) { w1 = UInt16.Parse(Request.QueryString["valueW"]); h1 = UInt16.Parse(Request.QueryString["valueH"]); // Create a Stream in memory to save the image MemoryStream memStream = canvasAndImage(); Response.Clear(); // Send the memory image to Browser in binary mode memStream.WriteTo(Response.OutputStream); } public MemoryStream canvasAndImage() { // Define a Rectangle to be the BG rectangle Rectangle bgRect = new Rectangle(0,0,w1,h1); 124 Textos Universitarios / Serie Docencia ________________________________________________________________________ // The bitmap Object used to work with images defined by // pixel data Bitmap pixelImage = new Bitmap(w1,h1); // 1) Will be used to build the new Graphics object // 2) Whatever you do with the Graphics object you afect // the image object! Graphics g = Graphics.FromImage(pixelImage); // Fill the interior of the bg rectangle g.FillRectangle(new SolidBrush(bgColor), bgRect); // +++++++++++++++Begins section related with this Server SolidBrush rosyBrush = new SolidBrush(Color.RosyBrown); SolidBrush burlyBrush = new SolidBrush(Color.BurlyWood); SolidBrush greenBrush = new SolidBrush(Color.GreenYellow); g.FillEllipse(rosyBrush,bgRect.X+4, bgRect.Y+4, bgRect.Width-8,bgRect.Height-8); g.FillEllipse(burlyBrush,60, 60, 120, 120); g.FillEllipse(greenBrush,80.0F, 80.0F, 140.0F, 50.0F); // +++++++++++++++Ends section related with this Server MemoryStream aStream = new MemoryStream(); pixelImage.Save(aStream,ImageFormat.Png); // Bmp, Jpeg, Png, Gif return aStream; } | Web Form Designer Generated Code | } } Listado 3.33. Código asociado con la forma ServerFillEllipses.aspx El resultado de la interacción entre estas dos formas genera la imagen mostrada en la Figura 3.31. . Figura 3.31. Rellenado de tres elipses 125 Jenaro C. Paz ________________________________________________________________________ 3.1.2.2.1.3 Rellenando trazos FillPath.aspx.cs private void btnGenerar_Click(object sender, System.EventArgs e) { string recHeight = txtHeight.Text; string recWidth = txtWidth.Text; Response.Write("<img border='0' src='ServerFillPath.aspx?valueH=" + recHeight + "&valueW=" + recWidth + "'>"); Response.Write("<p><font color=red>Fill Closed Curves!</font></p>"); } Listado 3.34. Código asociado a la forma FillPath.aspx ServerFillPath.aspx.cs using using using using using using using using using using using using System; System.Collections; System.ComponentModel; System.Data; System.Drawing; System.Web; System.Web.SessionState; System.Web.UI; System.Web.UI.WebControls; System.Web.UI.HtmlControls; System.IO; System.Drawing.Imaging; namespace JCPGraphics { public class ServerFillPath : System.Web.UI.Page { int w1,h1; Color bgColor=Color.LightGray; private void Page_Load(object sender, System.EventArgs e) { w1 = UInt16.Parse(Request.QueryString["valueW"]); h1 = UInt16.Parse(Request.QueryString["valueH"]); // Create a Stream in memory to save the image MemoryStream memStream = canvasAndImage(); Response.Clear(); // Send the memory image to Browser in binary mode memStream.WriteTo(Response.OutputStream); } public MemoryStream canvasAndImage() { // Define a Rectangle to be the BG rectangle Rectangle bgRect = new Rectangle(0,0,w1,h1); 126 Textos Universitarios / Serie Docencia ________________________________________________________________________ // The bitmap Object used to work with images defined by // pixel data Bitmap pixelImage = new Bitmap(w1,h1); // 1) Will be used to build the new Graphics object // 2) Whatever you do with the Graphics object you afect // the image object! Graphics g = Graphics.FromImage(pixelImage); // Fill the interior of the bg rectangle g.FillRectangle(new SolidBrush(bgColor), bgRect); // +++++++++++++++Begins section related with this Server // Create a new GraphicsPath instance GraphicsPath path = new GraphicsPath(); PointF ptf1 = new PointF(20.0F, 20.0F); PointF ptf2 = new PointF(200.0F, 200.0F); int X1 = 20, Y1 = 200, X2 = 200, Y2 = 200; int Xa = 20, Ya = 20, Xb = 20, Yb = 200; // Add a line to the path path.AddLine(ptf1,ptf2); // Add an ellipse to the path path.AddEllipse(100, 50, 100, 100); // Add three more lines path.AddLine(X1, Y1, X2, Y2); path.AddLine(Xa, Ya, Xb, Yb); // Create a rectangle and call // AddRectangle Rectangle rect = new Rectangle(50, 110, 180, 60); path.AddRectangle(rect); // Draw path SolidBrush violetBrush = new SolidBrush(Color.Violet); g.FillPath(violetBrush, path); // +++++++++++++++Ends section related with this Server MemoryStream aStream = new MemoryStream(); pixelImage.Save(aStream,ImageFormat.Png); // Bmp, Jpeg, Png, Gif return aStream; } | Web Form Designer Generated Code | } } Listado 3.35. Código asociado con la forma ServerFillPath.aspx 127 Jenaro C. Paz ________________________________________________________________________ El resultado de la interacción entre estas dos formas genera la imagen mostrada en la Figura 3.32 . Figura 3.32. Rellenado de un trazo 3.1.2.2.1.4 Rellenando pasteles FillPies.aspx.cs private void btnGenerar_Click(object sender, System.EventArgs e) { string recHeight = txtHeight.Text; string recWidth = txtWidth.Text; Response.Write("<img border='0' src='ServerFillPies.aspx?valueH=" + recHeight + "&valueW=" + recWidth + "'>"); Response.Write("<p><font color=red>Fill Closed Curves!</font></p>"); } Listado 3.36. Código asociado a la forma FillPies.aspx ServerFillPies.aspx.cs using using using using using using using using using 128 System; System.Collections; System.ComponentModel; System.Data; System.Drawing; System.Web; System.Web.SessionState; System.Web.UI; System.Web.UI.WebControls; Textos Universitarios / Serie Docencia ________________________________________________________________________ using System.Web.UI.HtmlControls; using System.IO; using System.Drawing.Imaging; namespace JCPGraphics { public class ServerFillPies : System.Web.UI.Page { int w1,h1; Color bgColor=Color.LightGray; private void Page_Load(object sender, System.EventArgs e) { w1 = UInt16.Parse(Request.QueryString["valueW"]); h1 = UInt16.Parse(Request.QueryString["valueH"]); // Create a Stream in memory to save the image MemoryStream memStream = canvasAndImage(); Response.Clear(); // Send the memory image to Browser in binary mode memStream.WriteTo(Response.OutputStream); } public MemoryStream canvasAndImage() { // Define a Rectangle to be the BG rectangle Rectangle bgRect = new Rectangle(0,0,w1,h1); // The bitmap Object used to work with images defined by // pixel data Bitmap pixelImage = new Bitmap(w1,h1); // 1) Will be used to build the new Graphics object // 2) Whatever you do with the Graphics object you afect // the image object! Graphics g = Graphics.FromImage(pixelImage); // Fill the interior of the bg rectangle g.FillRectangle(new SolidBrush(bgColor), bgRect); // +++++++++++++++Begins section related with this Server //Define three brushes SolidBrush goldenBrush = new SolidBrush(Color.DarkGoldenrod); SolidBrush burlyBrush = new SolidBrush(Color.BurlyWood); SolidBrush indianBrush = new SolidBrush(Color.IndianRed); g.FillPie(goldenBrush,bgRect.X+4,bgRect.Y+4, bgRect.Width-40,bgRect.Height-40, 65,90); g.FillPie(burlyBrush,20, 30, 120, 120,280,110); g.FillPie(indianBrush,170.0F, 20.0F, 140.0F, 140.0F, 20,170); // +++++++++++++++Ends section related with this Server MemoryStream aStream = new MemoryStream(); pixelImage.Save(aStream,ImageFormat.Png); // Bmp, Jpeg, Png, Gif return aStream; } | Web Form Designer Generated Code | } } Listado 3.37. Código asociado con la forma ServerFillPies.aspx 129 Jenaro C. Paz ________________________________________________________________________ El resultado de la interacción entre estas dos formas genera la imagen mostrada en la Figura 3.33 Figura 3.33. Rellenado de pasteles 3.1.2.2.1.5 Rellenando polígonos FillPolygon.aspx.cs private void btnGenerar_Click(object sender, System.EventArgs e) { string recHeight = txtHeight.Text; string recWidth = txtWidth.Text; Response.Write("<img border='0' src='ServerFillPolygon.aspx?valueH=" + recHeight + "&valueW=" + recWidth + "'>"); Response.Write("<p><font color=red>Fill Closed Curves!</font></p>"); } Listado 3.38. Código asociado a la forma FillPies.aspx ServerFillPolygon.aspx.cs using using using using using using using 130 System; System.Collections; System.ComponentModel; System.Data; System.Drawing; System.Web; System.Web.SessionState; Textos Universitarios / Serie Docencia ________________________________________________________________________ using using using using using System.Web.UI; System.Web.UI.WebControls; System.Web.UI.HtmlControls; System.IO; System.Drawing.Imaging; namespace JCPGraphics { public class ServerFillPolygon : System.Web.UI.Page { int w1,h1; Color bgColor=Color.LightGray; private void Page_Load(object sender, System.EventArgs e) { w1 = UInt16.Parse(Request.QueryString["valueW"]); h1 = UInt16.Parse(Request.QueryString["valueH"]); // Create a Stream in memory to save the image MemoryStream memStream = canvasAndImage(); Response.Clear(); // Send the memory image to Browser in binary mode memStream.WriteTo(Response.OutputStream); } public MemoryStream canvasAndImage() { // Define a Rectangle to be the BG rectangle Rectangle bgRect = new Rectangle(0,0,w1,h1); // The bitmap Object used to work with images defined by // pixel data Bitmap pixelImage = new Bitmap(w1,h1); // 1) Will be used to build the new Graphics object // 2) Whatever you do with the Graphics object you afect // the image object! Graphics g = Graphics.FromImage(pixelImage); // Fill the interior of the bg rectangle g.FillRectangle(new SolidBrush(bgColor), bgRect); // +++++++++++++++Begins section related with this Server PointF P1 =new PointF(125.0F, 30.0F); PointF P2 =new PointF(220.0F, 99.0F); PointF P3 =new PointF(183.0F, 210.0F); PointF P4 =new PointF(67.0F, 210.0F); PointF P5 =new PointF(30.0F, 99.0F); PointF P6 =new PointF(125.0F, 30.0F); PointF[] polyArray = { P1, P2, P3, P4, P5, P6 }; PointF p1 =new PointF(147.0F, 99.0F); PointF p2 =new PointF(161.0F, 142.0F); PointF p3 =new PointF(125.0F, 168.0F); PointF p4 =new PointF(89.0F, 142.0F); PointF p5 =new PointF(103.0F, 99.0F); PointF p6 =new PointF(147.0F, 99.0F); PointF[] poly2Array = { p1, p2, p3, p4, p5, p6 }; 131 Jenaro C. Paz ________________________________________________________________________ SolidBrush lemonBrush = new SolidBrush(Color.LemonChiffon); SolidBrush purpleBrush = new SolidBrush(Color.MediumPurple); g.FillPolygon(lemonBrush,polyArray); g.FillPolygon(purpleBrush,poly2Array); // +++++++++++++++Ends section related with this Server MemoryStream aStream = new MemoryStream(); pixelImage.Save(aStream,ImageFormat.Png); // Bmp, Jpeg, Png, Gif return aStream; } | Web Form Designer Generated Code | } } Listado 3.39. Código asociado con la forma ServerFillPolygon.aspx El resultado de la interacción entre estas dos formas genera la imagen mostrada en la Figura 3.34. Figura 3.34. Rellenado de polígonos 132 Textos Universitarios / Serie Docencia ________________________________________________________________________ 3.1.2.2.1.6 Rellenando un rectángulo FillRectangle.aspx.cs private void btnGenerar_Click(object sender, System.EventArgs e) { string recHeight = txtHeight.Text; string recWidth = txtWidth.Text; Response.Write("<img border='0' src='ServerFillRectangle.aspx?valueH=" + recHeight + "&valueW=" + recWidth + "'>"); Response.Write("<p><font color=red>Fill Closed Curves!</font></p>"); } Listado 3.40. Código asociado a la forma FillRectangle.aspx ServerFillRectangle.aspx.cs using using using using using using using using using using using using System; System.Collections; System.ComponentModel; System.Data; System.Drawing; System.Web; System.Web.SessionState; System.Web.UI; System.Web.UI.WebControls; System.Web.UI.HtmlControls; System.IO; System.Drawing.Imaging; namespace JCPGraphics { public class ServerFillRectangle : System.Web.UI.Page { int w1,h1; Color bgColor=Color.LightGray; private void Page_Load(object sender, System.EventArgs e) { w1 = UInt16.Parse(Request.QueryString["valueW"]); h1 = UInt16.Parse(Request.QueryString["valueH"]); // Create a Stream in memory to save the image MemoryStream memStream = canvasAndImage(); Response.Clear(); // Send the memory image to Browser in binary mode memStream.WriteTo(Response.OutputStream); } public MemoryStream canvasAndImage() { // Define a Rectangle to be the BG rectangle Rectangle bgRect = new Rectangle(0,0,w1,h1); // The bitmap Object used to work with images defined by 133 Jenaro C. Paz ________________________________________________________________________ // pixel data Bitmap pixelImage = new Bitmap(w1,h1); // 1) Will be used to build the new Graphics object // 2) Whatever you do with the Graphics object you afect // the image object! Graphics g = Graphics.FromImage(pixelImage); // Fill the interior of the bg rectangle g.FillRectangle(new SolidBrush(bgColor), bgRect); // +++++++++++++++Begins section related with this Server Rectangle myRect2 = new Rectangle(20,20,w1-40,h1-40); g.FillRectangle(new SolidBrush(Color.Chocolate), myRect2); // +++++++++++++++Ends section related with this Server MemoryStream aStream = new MemoryStream(); pixelImage.Save(aStream,ImageFormat.Png); // Bmp, Jpeg, Png, Gif return aStream; } | Web Form Designer Generated Code | } } Listado 3.41. Código asociado con la forma ServerFillRectangle.aspx El resultado de la interacción entre estas dos formas genera la imagen mostrada en la Figura 3.35. Figura 3.35. Rellenado de rectángulos 134