Foros - Stratos

Proyectos => Jad Engine => Mensaje iniciado por: Buffon en 19 de Abril de 2005, 07:39:45 PM

Título: Duda En C#
Publicado por: Buffon en 19 de Abril de 2005, 07:39:45 PM
 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
Título: Duda En C#
Publicado por: zupervaca en 19 de Abril de 2005, 11:29:39 PM
 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
Título: Duda En C#
Publicado por: Buffon en 20 de Abril de 2005, 10:23:49 AM
 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.
Título: Duda En C#
Publicado por: zupervaca en 20 de Abril de 2005, 11:33:08 AM
 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
Título: Duda En C#
Publicado por: Buffon en 20 de Abril de 2005, 05:41:46 PM
 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 :)
Título: Duda En C#
Publicado por: BeRSeRKeR en 20 de Abril de 2005, 06:18:06 PM
 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.
Título: Duda En C#
Publicado por: Buffon en 20 de Abril de 2005, 06:52:57 PM
 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 >_<

Título: Duda En C#
Publicado por: shephiroth en 20 de Abril de 2005, 08:04:32 PM
 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:  
Título: Duda En C#
Publicado por: Buffon en 21 de Abril de 2005, 01:04:03 AM
 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
Título: Duda En C#
Publicado por: zupervaca en 21 de Abril de 2005, 12:36:02 PM
 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
Título: Duda En C#
Publicado por: Buffon en 21 de Abril de 2005, 04:34:52 PM
 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.
Título: Duda En C#
Publicado por: shephiroth en 21 de Abril de 2005, 05:21:42 PM
 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 ^^
Título: Duda En C#
Publicado por: Buffon en 21 de Abril de 2005, 08:14:33 PM
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 :(
Título: Duda En C#
Publicado por: Juan Mellado en 22 de Abril de 2005, 04:19:18 PM
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
Título: Duda En C#
Publicado por: zupervaca en 22 de Abril de 2005, 07:44:17 PM
 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
Título: Duda En C#
Publicado por: shephiroth en 22 de Abril de 2005, 08:57:21 PM
 Wenas.

Estoy mirando un poco.....y me he dado cuenta que llamas a un objeto equivocado. En vez de utilizar e.Graphics utiliza e.ClipRectangle.......este objeto (no se donde he leido q es de solo lectura, no se que te dejara hacer y que no >_<) tiene las propiedades .Location y .Size que puede que sean las q te den problemas. Usando el debug o con un print comprueba que seccion de la pantalla esta realmente dibujando.

Respecto a lo q comentaste antes del fallo, no te preocupes.....por eso dije si no crearia problema por otros lados......
Título: Duda En C#
Publicado por: Buffon en 25 de Abril de 2005, 11:21:29 AM
Cita de: "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
zuper no te mosquees pero no estás aportando nada a la conversación.

simplemente dices lo que ya he dicho yo anteriormente y de lo que estoy preguntando no respondes, simplemente afirmas cosas ya dichas.

Lo de que Invalidate genera una llamada a Onpaint lo he dicho yo en 4 mensajes de este mismo thread.

@Sephirot

Esa propiedad está muy bien ^^ dice todo los datos que la nueva ventana a pintar.

De todas maneras seguramente me rendiré, ya que era una prueba, el evento que registrará que se ha de volver a pintar no será por sacar la ventana fuera de pantalla y éste si que podrá hacer un Invalidate ^^.
------------------------

más que nada era por lo siguiente, queremos hacer un reloj digital.

si forzamos al metodo OnPaint a dibujar cada segundo con un simple sleep solo tendrá que recoger la hora y mostrarla.

y el codigo es mucho más sencillo que si nos declaramos un objeto "reloj" al cual le asignamos un evento de tiempo que hará un invalidate();

El primero es muy intuitivo y fácil de aprender.
El segundo como docencia es mucho más estricto, ya que enseña eventos bien y comunicación entre ellos.

pero weno, no os preocupeis yo sigo para adelante ^^
Título: Duda En C#
Publicado por: zupervaca en 25 de Abril de 2005, 11:59:55 AM
 ¿sabes lo que es el un evento timer? pues eso tienes que utilizar, y en cada evento timer haz un invalidate, mira que facil es
Título: Duda En C#
Publicado por: zupervaca en 25 de Abril de 2005, 12:51:14 PM
 la verdad es que no se por que me molesto en contestar, te llevo diciendo desde el primer post la metodologia a seguir y tu sigues empeñado en hacer saltarte las normas de redibujado de windows, creo que lo mejor que puedes hacer es aprender primero esto y luego ponte a hacer el reloj, ya veras como lo entiendes todo luego
Título: Duda En C#
Publicado por: shephiroth en 25 de Abril de 2005, 01:29:23 PM
 Tranquilos, que bajen loshumos, que esto es un foro para ayudarnos, no para saltar a atacarnos a la minima discordancia.

Zupervaca, me aventuro a pedirte perdon de parte de Buffon.....el estaba dando por sentado unas cosas, tu otras, y simplemente ninguno os entendisteis. No dejes que el tema vaya mas allá ^^

Buffon, creo q te falta un moco de autoanálisis......sabes q invalidate hace una llamada a onpaint, y buscas un metodo q haga lo mismo sin esa llamada???? Tal funcion no existe, y te explicaré pq.....es ilogico (por lo menos para mi) que en OnPaint() quieras actualizar datos. Esto esta fuera de la metodologia de OOP....la funcion OnPaint() se ha de encargar de pintar y solo de pintar.......si quieres hacer un reloj digital tienes q hacer el evento que cada minuto llame a CambiarHora()....en ella haces los cambios, y haces el Invalidate()

Espero que se me haya entendido  (nooo)

Un salundo a ambos  (ole)  (ole)  
Título: Duda En C#
Publicado por: Buffon en 26 de Abril de 2005, 12:23:47 AM
 Si yo te he entendido es más esa era la forma sencilla que tenía para hacerlo, y también entiendo que no sea la forma lógica de hacerlo, y mucho más que la llamada OnPaint esté realizada de tal forma que sea casi imposible modificar esa llamada, pero entended que también era casi imposible en windows modificar el vector de interrupciones, pero con esfuerzo y dedicación se puede conseguir eso mismo y programarte tus propias rutinas de interrupciones.

Llevo en esto de la programación bastante tiempo ya, y siempre me ha gustado saber el por qué de las cosas, como está algo implementado y como poderlo mejorar, o en todo caso modificar y si puede ser de la manera más sencilla.

Ahí está el motivo de mi duda ^^.

@zupervaca

Si te ha ofendido mi alusión, pues lo siento solemnemente, pero tio xDDD acabo de decir yo lo del timer y como si yo no lo supiera me lo sueltas en tu siguiente mensaje sin leer el mio anterior >_<

@sephirot

gracias por la gran ayuda que me has brindado ^^ seguiré en mi busqueda ;)

Título: Duda En C#
Publicado por: zupervaca en 26 de Abril de 2005, 01:07:45 PM
 pues bien tu analisis funcional de las cosas no creo que puedas mejorar lo que hay ya hecho desde el primer windows que se hizo, sin animo de ofender, en tu post anteior dices dos soluciones, el timer y otro hilo aparte del de la aplicacion, en mi post te digo que uses el timer, un hilo con un sleep puede ser la mayor chapuza que haya podido ver en programacion para crear un reloj, cualquier universitario (yo estuve trabajando con uno y yo no lo soy) te diria que los hilos son las formas faciles de hacer las cosas pero que solo se deben de usar en casos muy excepcionales, si hay eventos que hagan lo que quieres hacer o parte de ello tienes que utilizarlos, que es mas jaleo, pues hay que aguantarse, pero las cosas hay que hacerlas bien no en plan chapuza, si todos usaran hilos con sleep tendriamos los ordenadores sin recursos (muchos sabran lo que digo)

usa la metodologia que windows te da que es la correcta:

- evento timer
- modificas valores en el evento timer
- invalidas la zona donde se pinta el reloj desde el evento timer
- en el mensaje de pintar pintas que pa eso esta  :P

saludos

Citar@sephirot

gracias por la gran ayuda que me has brindado ^^ seguiré en mi busqueda
me encanta ver como otra persona dice lo mismo que yo decia desde el primer post y el dice lo correcto y yo no, esta claro que hay gente que no necesita mi ayuda o sencillamente no la quiere  :huh: