Stratos: Punto de Encuentro de Desarrolladores

¡Bienvenido a Stratos!

Acceder

Foros





Duda En C#

Iniciado por Buffon, 19 de Abril de 2005, 07:39:45 PM

« anterior - próximo »

Buffon

 Okey señores tengo una clase que hereda de Form.

la clase tiene unos metodos por defecto los cuales son llamados según les lleguen eventos.

yo sobrecargo el metodo OnPaint de la siguiente manera:


protected override void OnPaint(PaintEventArgs e)
{
 i++;
 System.Console.WriteLine("entramos "+i+" vez");
 //base.OnPaint (e);
 Graphics grx = e.Graphics;
 grx.DrawString("bucle "+i,Font,Brushes.BlanchedAlmond,0,0);
}


y estoy con una duda por que cuando muevo la ventana fuera de mi escritorio por la zona que no tiene nada escrita, solo actualiza la parte del formulario modificada "clipping" sin hacer caso a mi llamada DrawString, cuando en la consola si que me actualiza y me muestra cuantas veces se ha llamado a OnPaint realmente, el formulario solo me lo muestra cuando tiene que actualizar esa porcion de la ventanita :(
---------------

Vale esto como el formulario redibuja por "clipping" puedo llegar a entenderlo, y supongo que la llamada a DrawString es ignorada por que el area que tiene que redibujar y el area de escritura del DrawString  no tienen puntos en común y por eso no hace nada, pero me gustaría saber como forzar al windows form a que cuando se llame al metodo OnPaint invalide toda la region del formulario, como si hicieramos un Invalidate() para tenerlo que volver a dibujar.

y no me digais que haga Invalidate ya que entrariamos en un bucle infinito =P

Ah y tampoco es por comentar el base.OnPaint

zupervaca

 no debes de hacer que se redibuje todo el area cliente de la ventana, lo que tienes que hacer es que cuando cambie el valor que quieres mostrar actualizar la zona donde se pinta esa informacion

si todas las apps redibujar todo siempre necesitariamos un ordenador bastante potente para mover windows

se me olvidaba, si quieres hacer que repinte lo justo tiene que existir una funcion en c# para saber el ancho y alto de un string con caracteres no proporcionales

saludos

Buffon

 si todo eso lo se encontrar. pero el problema es como le digo al formulario que invalide justo esa region?

por que el formulario tiene una propiedad llamada ClipRectangle que especifica justo el rectangulo mínimo que engloba el area del cliente que ha sido invalidad en ese mismo momento, pero si yo cogo y redimensiono ese ClipRectangle si estoy invalidando la zona inferior derecha y yo escribo arriba izquierda, invalidaré todo el area del cliente de todas maneras.

supongo que tendré que llamar antes de nada a otra función, del estilo justo cuando entro en OnPaint

mifuncionpropia(PaintEventArgs e)
{
--> guardo estado antiguo de ClipRectangle
--> cambio estado de ClipRectangle y pinto en esa zona
--> restauro estado antiguo de ClipRectangle
--> return
}

-----------------

pero he de suponer que deberia haber alguna forma más sencilla de hacer esto mismo.

zupervaca

 la idea de las zonas a invalidar es que no tiene que repintarse todo la ventana en la misma llamada, puede haber varios mensajes para pintar para diferentes zonas, en el api de win32 para invalidar un rectangulo se llama invalidaterect

saludos

Buffon

 si que eso ya lo entendía  <_< pero como entenderás tu si yo me pongo a escribir texto por el formulario a cada llamada de OnPaint y no se escribe, pues vaya gracia xD

la funcion invalidaterect no existe, toy buscando algo similar :)

BeRSeRKeR

 Hola.

El método invalidate de un control tiene varias versiones entre ellas una que te permite invalidar un rectángulo, una región, etc.

Saludos.
¡Si te buscan en nombre de la ley, huye en nombre de la libertad!!

Buffon

 el problema es el siguiente.

dentro de la funcion OnPaint kiero decirle que me lo invalide el area del cliente entera, pero que solo lo haga en ese momento y no se vuelva a llamar al metodo OnPaint recursivamente :)

es que si dentro hago un Invalidate(); este llama a OnPaint y recursivamente se vuelve loco =) y yo lo que quiero hacer es que cuando entre en la función simplemente invalide todo el area del cliente, y me supongo que esto debe haber una funcion que lo haga pero no la encuentro >_<


shephiroth

 Wenas.

No se mucho de c#, pero si lo q quieres es para la recursividad puedes hacer algo como:


tuclass::OnPaint(...)
{
static bool recursive = true;
if (recursive)
{
...
recursive=false;
invalidate(...);
...
}
else recursive=true;
}


Ya se que esto tiene muchos fallos :( , pero espero que la idea sirva de algo  :huh:  

Buffon

 gracias por la idea pero yo no me refiero a eso exactamente.

mira la idea es la siguiente.

se invalida un trozo del formulario entonces -> se llama al metodo OnPaint.

dentro del metodo OnPaint se realiza una accion que yo he redefinido para que escriba por el formulario una variable i que se incrementa cada vez que se llama al metodo OnPaint.

el problema es que cuando se invalida una zona que no contiene ese string no se actualiza esa parte.

conclusion,

solo kiero una llamada que me invalide toda la area del formulario pero sin que genere ningún otro evento a la función OnPaint.
-------------------------

Invalidate(); <----- invalida TODO el area del cliente y llama a la función OnPaint() mandando un evento "throw new PaintHandlerEvent".

lo que yo kiero es.

this.setFormInvalidate(); <---- invalida TODO el area del cliente para la próxima vez que haya que actualizarlo, no genera ningun evento nuevo.

el problema es que no encuentro ese setFormInvalidate();
----------------

NOTA, nombre de función inventado xD

zupervaca

 veamos por lo que veo c# tiene proteccion de partes clientes de la ventana, cosa que no ocurre en win32, cuando en un lenguaje que usa el api win32 recibe el mensaje wm_paint (OnPaint c#) se debe de obtener el rectangulo de donde se quiere pintar llamando a una funcion, si no obtienes este rectangulo y pintas al tuntun la ventana se actualizara perfectamente, por lo que veo c# en este sentido esta muy bien y me gusta el sistema de proteger la ventana de esta manera

la solucion a tu problema es sencillo, cada vez que cambie el valor que quieres actualizar haz un invalidate y si alguna vez encuentras un invalidaterect usalo  ;)

saludos

pd: cualquier funcion de pintar sobre un dispositivo de contexto (dc) no invalidara la ventana

Buffon

 zupervaca lo he repetido ya unas cuantas veces pero no lees mis mensajes ^^

el metodo Invalidate por definicion genera un evento OnPaint

si hago

public override void OnPaint(...)
{
  Invalidate();
....
}

--------------------

esto desde el inicio del programa genera infinitas llamadas al metodo OnPaint.

y eso no me interesa, yo kiero que sólo se invalide esa vez que se ha llamado a la función OnPaint, no que se llame infinitas veces.

shephiroth

 Wenas.

Se que no es lo q esperas, pero mi idea te viene como anillo al dedo. Cierto es q mi idea no "evita" la llamada al OnPaint, pero si es cierto que anulara esa llamada.....lo q no s si tendra repercusiones laterales.....

SALUDOS y suerte ^^

Buffon

Cita de: "shephiroth"Wenas.

Se que no es lo q esperas, pero mi idea te viene como anillo al dedo. Cierto es q mi idea no "evita" la llamada al OnPaint, pero si es cierto que anulara esa llamada.....lo q no s si tendra repercusiones laterales.....

SALUDOS y suerte ^^
Tu idea es como mejor se soluciona, pero hay un pequeño problema y no te enfades conmigo, que es un poco una warrada xD en vez de hacer una llamada cada vez que se invalida, se hacen 2.

esto requiere producir otro evento más. >_< aunque funcionar funciona correctamente ;)

pero claro, yo estoy convencido de que se puede hacer lo siguiente.


protected override void OnPaint(PaintEventArgs e)
{
[B]MARCAR TODO EL AREA PARA REPINTAR[/B]
i++;
System.Console.WriteLine("entramos "+i+" vez");
//base.OnPaint (e);
Graphics grx = e.Graphics;
grx.DrawString("bucle "+i,Font,Brushes.BlanchedAlmond,0,0);
}




---------------------------------------------

por ejemplo hay una funcion que se llama cada vez que se produce un evento de redimensionar la ventana. y esta funcion actualiza completamente toda la pantalla calculando el nuevo ancho/alto y haciendo un Invalidate();
pero si te la defines tu haciendo simplemente por ejemplo

Graphics grx = e.Graphics.
grx.Clear(Color.distinto);

pues solo se actualiza el color de la parte nueva que expandes.



también se puede establecer que se redibuje todo el area del cliente, poniendo en el constructor de tu clase una propiedad que me parece que era PaintReDraw = true

(es que estoy en otro ordenador)

y no encuentro ninguna propiedad que haga que Siempre se redibuje todo el area del cliente :(

Juan Mellado

Hola,
si el objeto Graphics que recibes en PaintEventArgs no te viene bien para lo que quieres hacer, ¿por qué no creas un objeto nuevo?


protected override void OnPaint(PaintEventArgs e)
{
 Graphics g = this.CreateGraphics();
...
 g.xxx();
...
 g.Dispose();
}


Saludos

zupervaca

 vamos a ver, invalidate genera un mensaje onpaint, pues claro para eso esta!!

debes de llamar a invalidate cada vez que MODIFIQUES el valor que quieres mostrar, NUNCA dentro de la funcion OnPaint

saludos






Stratos es un servicio gratuito, cuyos costes se cubren en parte con la publicidad.
Por favor, desactiva el bloqueador de anuncios en esta web para ayudar a que siga adelante.
Muchísimas gracias.