none
Error al crear el identificador de ventana RRS feed

  • Pregunta

  •  

    Hola! resulta que estoy haciendo un control personalizado (es el primero que hago), que consta de un GroupBox, este control a su vez contiene un Panel, al que llamo panelDeColores. Dentro del 'panelDeColores' voy agregando controles a la coleccion de controles del mismo. Estos controles que agrego son a su vez del tipo Panel, y les asigno a su propiedad BackGroundColor un color que tomo de la enumeracion KnownColor. La idea es ir formando una especia de paleta de colores al estilo del Paint. Lo que sucede es que cuando el control se pinta (o sea, cuando se produce el evento Paint del control personalizado), en ese momento voy creando los paneles y se los voy agregando al existente. Pero cuando estoy depurando, me marca en amarillo la instruccion:

    Bloque de código
    panelDeColores.Controls.Add(muestraDeColor);

     

     



    muestraDeColor vendria a ser el panel que acabo de crear y que quiero agregar al panel principal. El error que me tira es:

    Win32Exception - "Error al crear el identificador de ventana"

    Todo esto lo hago dentro de un ciclo for, recorriendo la enumeracion con los colores del sistema.
    Probe distintas cosas, por ejemplo, despues de crear al control con el new llamo al metodo createControl(), o sea:

    Bloque de código
    muestaDeColor = new Panel();
    muestraDeColor.CreateControl();

     

     

    para forzar que se cree nuevamente el identificador del control, pero tampoco funciona.

    Este es el codigo completo:
     

    Bloque de código

    using System;

    using System.Collections.Generic;

    using System.ComponentModel;

    using System.Drawing;

    using System.Data;

    using System.Text;

    using System.Windows.Forms;

    namespace bibDeContrDeWindowsPaletaDeColores

    {

    public partial class UserControlPaletaDeColores : UserControl

    {

    private int altoPanelColores;

    private int anchoPanelColores;

    private int margenDeLaMuestraDeColor = 5;

    public UserControlPaletaDeColores()

    {

    InitializeComponent();

    this.Height = 80;

    this.Width = 480;

    //estable los tama¤os predeterminados para los controles

    //que componen al control personalizado

    //hay que respetar las diferencias de tama¤o que hay entre los distintos

    //controles. Es una diferencia absoluta, en pixeles, el panelDeColores

    //con respecto al UserControlPaletaDeColores es, en alto, de 15 pixeles

    //y en ancho, de 9 pixeles. La diferencia entre el GroupBoxPaletaDeColores

    //y el UserControlPaletaDeColores es, en alto, de 1 pixel y en ancho

    //de 4 pixeles.

    this.panelDeColores.Height = this.Height - 15;

    this.panelDeColores.Width = this.Width - 9;

    this.groupBoxPaletaDeColores.Height = this.Height - 1;

    this.groupBoxPaletaDeColores.Width = this.Width - 4;

    this.altoPanelColores = this.panelDeColores.Height;

    this.anchoPanelColores = this.panelDeColores.Width;

    this.Left = 0;

    this.Top = 0;

    this.Paint += new PaintEventHandler(UserControlPaletaDeColores_Paint);

    this.panelDeColores.Paint += new PaintEventHandler(panelDeColores_Paint);

    this.SizeChanged += new EventHandler(UserControlPaletaDeColores_SizeChanged);

    }

    void panelDeColores_Paint(object sender, PaintEventArgs e)

    {

    //calcula las dimensiones de las muestas de color a partir de las dimensiones

    //del panel que las contiene en el formulario.

    //arbitrariamente, la array dimensiones contendra en su primer elemento

    //el alto, y en su segundo elemento contendra el ancho

    int[] dimensiones = new int[2];

    //el tercer parametro de este metodo especifica

    //los margenes (en pixeles) que separaran a cada muestra de color

    //si el mismo vale 0 (cero), no existe separacion.

    dimensiones = calcularDimensionesDeUnaMuestraDeColor(this.altoPanelColores, this.anchoPanelColores, this.margenDeLaMuestraDeColor);

    //hace un ajuste de las dimensiones del tama¤o de la muestra a partir

    //del area que realmente se aprovecha, pero esta vez con margen igual a 0 (cero)

    int areaAprovechada = calcularAreaAprovechada(dimensiones);

    int lado = (int)Math.Truncate(Math.Sqrt((double)areaAprovechada));

    dimensiones = calcularDimensionesDeUnaMuestraDeColor(lado, lado, 0);

    //usada para guardar una referencia temporal a las distintas muestras

    //de color que se van creando y que se agregan al panel.

    System.Windows.Forms.Panel muestraDeColor;

    //suspende la logica de dise¤o del control mientras se agregan nuevos controles

    //al mismo, y se reanuda una vez terminado el proceso.

    //Esto afecta directamente al control Panel llamado panelDeColores, que es

    //al que se le agregan las distintas muestras de colores (que son a su ves controles del tipo Panel).

    //Es conveniente suspender la logica de dise¤o para los controles que contienen al panel panelDeColores.

    this.panelDeColores.SuspendLayout();

    this.groupBoxPaletaDeColores.SuspendLayout();

    this.SuspendLayout();

    int posX, posY = 0;

    for (KnownColor enumValue = 0; enumValue <= KnownColor.YellowGreen && (posY + dimensiones[0]) < this.altoPanelColores; enumValue++, posY += dimensiones[0])

    {

    for (posX = 0; enumValue <= KnownColor.YellowGreen && (posX + dimensiones[1]) < this.anchoPanelColores; enumValue++, posX += dimensiones[1])

    {

    muestraDeColor = new System.Windows.Forms.Panel();

    if (muestraDeColor.IsHandleCreated == false)

    {

    //Console.WriteLine("No se ha podido crear el identificador del control. Recreando...");

    muestraDeColor.CreateControl();

    if (muestraDeColor.RecreatingHandle == false)

    {

    //Console.WriteLine("No se ha podido recrear el identificador del control. EROOOR!!!");

    }

    }

    //suspende temporalmente la logica de dise¤o del control

    //muestraDeColor, mientras se modifican los atributos correspondientes.

    muestraDeColor.SuspendLayout();

    muestraDeColor.BackColor = Color.FromKnownColor(enumValue);

    muestraDeColor.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D;

    muestraDeColor.Margin = new System.Windows.Forms.Padding(this.margenDeLaMuestraDeColor);

    //establece la distancia en pixeles que existe entre el borde izquierdo del panel

    //o sea, de la muestra de color, y el borde izquierdo del control (en este caso, un GroupBox).

    muestraDeColor.Left = posX;

    //establece la distancia en pixeles que existe entre el borde superior del panel

    //y el borde superior del control (en este caso, un GroupBox).

    muestraDeColor.Top = posY;

    //establece las propiedades del alto y el ancho del panel que representa la muestra de color

    muestraDeColor.Height = dimensiones[0]; //la variable dimensiones[0] contiene el alto

    muestraDeColor.Width = dimensiones[1]; //la variable dimensiones[1] contiene el ancho

    //reanuda la logica de dise¤o del control porque se han terminado

    //de configurar los distintos atributos de la muestra de color.

    muestraDeColor.ResumeLayout();

    this.panelDeColores.Controls.Add(muestraDeColor);

    }

    }

    //reanuda la logica de dise¤o del control una vez finalizado

    //el proceso de carga de las muestras de colores al control

    //de usuario paletaDeColores.

    this.panelDeColores.ResumeLayout();

    this.groupBoxPaletaDeColores.ResumeLayout();

    this.ResumeLayout();

    }

    void UserControlPaletaDeColores_SizeChanged(object sender, EventArgs e)

    {

    //para el panel de colores, si el control principal

    //cambia de tama¤o, hay que ajustarlo respetando la diferencia

    //de tama¤o. Diferencia en alto 15 y en ancho 9.

    this.panelDeColores.Width = this.Width - 9;

    this.panelDeColores.Height = this.Height - 15;

    //para el panel de colores, si el control principal

    //cambia de tama¤o, hay que ajustarlo respetando la diferencia

    //de tama¤o. Diferencia en alto 1 y en ancho 4.

    this.groupBoxPaletaDeColores.Width = this.Width - 4;

    this.groupBoxPaletaDeColores.Height = this.Height - 1;

    }

    void UserControlPaletaDeColores_Paint(object sender, PaintEventArgs e)

    {

    this.panelDeColores.Invalidate();

    }

    public int cantidadDeColoresConocidos()

    {

    int cantidad = 0;

    for (KnownColor color = 0; color <= KnownColor.YellowGreen; color++)

    cantidad++;

    return cantidad;

    }

    public int[] calcularDimensionesDeUnaMuestraDeColor(int alto, int ancho, int margen){

    int areaPaleta = alto * ancho;

    int areaMuestra = 0;

    int[] dimensiones = new int[2];

    //divide el area de la paleta por la cantidad de colores conocidos

    //por el sistema.

    areaMuestra = areaPaleta / this.cantidadDeColoresConocidos();

    //calcula la raiz cuadrada del area para dibujar un cuadrado de muestra

    //el area de la muestra, ademas del area del panel, incluye los margenes (en pixeles) que

    //separaran al mismo del resto de los paneles. Por eso se resta el margen

    //a las dimensiones del panel. Se reserva parte del area del panel para el margen.

    //En realidad, le resto la mitad del margen, porque dos paneles adyacentes comparten

    //un mismo tama¤o de margen. Si el margen es de 5, entonces, el panel A reserva 2.5

    //y el panel B (adyacente a A) reserva 2.5 para el margen. La suma de las dos areas

    //reservadas para el margen que estos dos paneles comparten es igual al tama¤o del margen (o sea, 5).

    //Sin embargo, como se tienen que manejar valores enteros,

    //se redondea para arriba. De esta forma, me aseguro que el margen siempre cabera

    //en el area reservada por los dos paneles adyacentes.

    //En el ejemplo anterior, si el margen es de 5 pixeles, se restarian 3 al panel A

    //y 3 al panel B (adyacente a A). De esta forma, 3 + 3 = 6, 6 es mayor que 5.

    //O sea, la suma de las areas reservadas para el margen en cada panel, siempre

    //sera mayor que el area del margen, o sea, que el margen siempre cabera entre

    //los dos paneles adyacentes, sin que esto provoque que alguno de los paneles

    //aparezca "cortado" cuando se dibuje en la pantalla.

    dimensiones[0] = (int) Math.Truncate (Math.Sqrt ((double) areaMuestra)) - (int) Math.Round ((double) margen/2, MidpointRounding.AwayFromZero) ;

    dimensiones[1] = dimensiones[0];

    return dimensiones;

    }

    private int calcularAreaAprovechada(int[] dimensiones) {

    int cantidadDeMuestrasVertical, cantidadDeMuestrasHorizontal;

    //calcula cuantas muestras entran a lo alto

    cantidadDeMuestrasVertical = this.altoPanelColores / dimensiones[0];

    cantidadDeMuestrasHorizontal = this.anchoPanelColores / dimensiones[1];

    return cantidadDeMuestrasVertical * cantidadDeMuestrasHorizontal * dimensiones[0] * dimensiones[1];

    }

    }

    }

     

     

    Alguien tiene alguna idea de por donde puede venir el problema. Muchas Gracias!!! Saludos!!!
    lunes, 21 de enero de 2008 13:31

Respuestas

  • el problema es por el numero de instancias que estas creando del objeto muestraDeColor ya que cada vez que se llama al objeto paint (decenas de veces por segundo) estas creadno mas y mas instancias hasta que tu aplicacion se totea por memoria...

     tienes mal diseñado tu programa...

    si lo que quieres es dibujar una paleta de colores al inicializar la forma puedes dejar listos todos los objetos y ya .

    no necesitas hacerlo en el evento paint.


    saludos.

    lunes, 21 de enero de 2008 13:45
  • conque sean publicas basta pero puedes adicionar categorias, valores por defecto y descripciones utilizando atributos... ejemplo tomado de un conocido libro:


    Bloque de código

    public partial class CarControl : UserControl
    {
    ...
    [Category("Car Configuration"),
    Description("Sent when the car is approaching terminal speed.")]
    public event CarEventHandler AboutToBlow;
    ...
    [Category("Car Configuration"),
    Description("Name your car!"),
    DefaultValue("Lemon")]
    public string PetName {...}
    ...
    }




    tambien puedes definir por ejemplo con que icono quieres que salga el control en el toolbox de visual studio etc.
    lunes, 21 de enero de 2008 16:49

Todas las respuestas

  • el problema es por el numero de instancias que estas creando del objeto muestraDeColor ya que cada vez que se llama al objeto paint (decenas de veces por segundo) estas creadno mas y mas instancias hasta que tu aplicacion se totea por memoria...

     tienes mal diseñado tu programa...

    si lo que quieres es dibujar una paleta de colores al inicializar la forma puedes dejar listos todos los objetos y ya .

    no necesitas hacerlo en el evento paint.


    saludos.

    lunes, 21 de enero de 2008 13:45
  • Y aún así, deberías de comprobar que el objeto se ha creado ya para evitar posibles colapsos.

     

    Un Saludo

     

    lunes, 21 de enero de 2008 14:12
    Moderador
  • Bueno, ya que me pudiste contestar esa bien, me gustaria que me ayudaras con otra cosita. Cuando uno diseña en visual studio, en la ventana de propiedades uno puede ver todos los atributos que un control exhibe para que un usuario del mismo pueda manejarlos, ya sea en tiempo de diseño o por medio de programacion. Por ejemplo, me gustaria que el usuario pudiera decidir el tamaño de las muestras de color, la separacion que hay entre ellas, y no se, despues se vera si algo mas. Entonces, basta con definir dentro de mi control un atributo public y ya esta, o es necesario que ademas, agregue metadatos? Yo ya probe lo primero y no puedo ver en la Ventana de Propiedades, las propiedades public (anchoDeLaMuestra, altoDeLaMuestra) que defini dentro de la clase paletaDeColores. Estuve leyendo algo de metadatos, que serian los attributes (como las annotations en Java, cosa que tampoco se manejar muy bien) y parece algo complejo. Me podrian orientar donde puedo encontrar buena documentacion, o sea, me refiero si me pueden dar algun link (y si me pueden dar la respuesta directamente mejor ). Espero su respuesta ansiosamente.

     

    Saludos!!!

     

    lunes, 21 de enero de 2008 16:36
  • conque sean publicas basta pero puedes adicionar categorias, valores por defecto y descripciones utilizando atributos... ejemplo tomado de un conocido libro:


    Bloque de código

    public partial class CarControl : UserControl
    {
    ...
    [Category("Car Configuration"),
    Description("Sent when the car is approaching terminal speed.")]
    public event CarEventHandler AboutToBlow;
    ...
    [Category("Car Configuration"),
    Description("Name your car!"),
    DefaultValue("Lemon")]
    public string PetName {...}
    ...
    }




    tambien puedes definir por ejemplo con que icono quieres que salga el control en el toolbox de visual studio etc.
    lunes, 21 de enero de 2008 16:49
  •  

    Por favor no olvides marcar la s res puestas que te hayan sido de ayuda  como correctas.

    sábado, 26 de enero de 2008 15:25