Stratos: Punto de Encuentro de Desarrolladores

¡Bienvenido a Stratos!

Acceder

Foros





Duda Windows Forms Con Vs.net 03 Y C#

Iniciado por nsL, 16 de Febrero de 2006, 08:58:00 PM

« anterior - próximo »

nsL

 Hola!

Ya he acabado los examenes, asi que ya me he puesto a enredar con la programacion.
Hoy me dio por echarle un ojo a C# y windows forms, que si boton para aqui , que si textbox para alla. Y me he puesto a "intentar hacer" un editor de mapas de tiles por echar el rato.

Pues bien, me he quedado atascado en este punto:

Ya tengo todo lo facil hecho (botones y cosillas wapas) y empece a programar las funciones y demas. Como era la primera vez q trabajaba con windows forms y este tipo de programacion, pues ando algo liado.

El problema es el siguiente: Me he creado una clase que va a contener un array dinamico a PictureBox's que contendran los tiles del mapa (no se si lo normal es hacerlo con picturebix, o si hay alguna forma mas curiosa). Entonces lo que hago es pasarle el Form como parametro al metodo de esa clase, y en el se supone que lo dibuja. Como no me entero de lo que pongo ni yo, os pongo codigo.


 public void assignForm(System.Windows.Forms.Form mainForm)
 {
  mainForm.SuspendLayout();

  tiles = new System.Windows.Forms.PictureBox();

  this.tiles.BackColor = System.Drawing.Color.Black;
  this.tiles = new System.Windows.Forms.PictureBox();
  this.tiles.Location = new System.Drawing.Point(25,25);
  this.tiles.Name = "pictureBox";
  this.tiles.Size = new System.Drawing.Size(128, 64);
  this.tiles.TabIndex = 0;
  this.tiles.TabStop = false;

 
  mainForm.Controls.Add(this.tiles);

  mainForm.ResumeLayout(false);
 }


En este ejemplo lo hago solo para un picturebox y sin array como os dije, pero era pa probar a ver si iba 1, y luego pasar a varios. He estado mirando la ayuda de msdn para lo de SuspendLayout y ResumeLayout, y creo que lo estoy usando bien. msdn

Pasarle el form como parametro funciona, porq probe a hacer un mainForm.text y cambiarlo y lo cambia. Asi q no se me ocurre que puede ser.

Si no se entendio bien la duda decirlo , y lo esplico mejor :P

Saludos y gracias!
Yo no muero hasta la muerte -

Vicente

 Hola,

la verdad que no tengo muy claro porque no sale, como apunte quizás solo que primero lo asignes al form y luego le des la posición, a ver si es eso (que lo posiciones respecto a nada de nada porque aun no tiene un padre). No se me ocurre otra cosa.

Respecto a si eso se hace así o no, yo cuando he hecho alguna cosa de estas he utilizado un panel y me he cargado el evento OnPaint sobreescribiéndolo con el código que a mi me interesaba (el panel tenía una matriz de objetos Tile y eso era lo que pintaba en el panel a mano).

Espero te sirva de algo. Un saludo!

Vicente

nsL

 jajaja
sabes donde estaba el fallo?

Si te fijas hago 2 instancias (tanto copiar y pegar :P), una justo despues del ajustarle el color. Entonces solo tenia en cuenta la segunda, que se creaba de color gris, por eso no la veia y yo pensando que no salia :P

Gracias por tu tiempo ;)

Saludos!
Yo no muero hasta la muerte -

Jare

 El método de Vicente creo que tiene más futuro.  (ole)  

nsL

 Estoy haciendo un hibrido ahora :P

Estoy metiendo los pictureBox dentro del panel, que no sabia que tb podia contener controles como un Form.

Por cierto, los objetos Tile a los que te refieres Vicente, son un tipo creado por ti, o ya te vienen....

Mas cosillas ahora q me vienen a la cabeza. Lo que voy a intentar hacer es un array (o matriz) con pictureboxes, que al darles click cambien su imagen al tile de pintado actual. Esto ya lo habia intentado otra vez, pero no sake la solucion a como discenir sobre que picturebox estoy clickando. Lo que hacia era usar para cada pictBox la misma funcion OnClick, que ponia su color background a negro. Pero claro, de cual de ellos ha de poner en negro si todos utilizaban la misma funcion. Me hacia falta una funcion que me devuelva sobre que controlador esta el puntero o algo similar, o calcular mediante coordenadas del raton que pict es, pero eso es mas engorroso.

gracias de antemano ;)

Saludos!
Yo no muero hasta la muerte -

Vicente

 Hola,

jejeje, la verdad que vaya fallo más tonto, no lo había visto yo tampoco.

Respecto al Tile: sip, era una clase propia mía (que tenía la imagen que representaba esa Tile y más cosas). Respecto a lo de sacar que PictureBox, lo de las coordenadas te lo vas a encontrar con las Tiles también, pero al final no es tan engorroso saber en que tile te han pulsado dentro de un mapa de tiles cuadradas  (si son hexagonales ya es más pesado, pero cuadradas no es tan difícil).

Un saludo!

Vicente

P.D.: Jare, me desespera la IA de tu jueguecito, jugando en plan "casual" siempre me da pal pelo :P

nsL

 Hombre, lo de las coordenadas es relativamente facil. Lo q pasa que el Panel tiene scroll para cuando se metan mas pcitBox del tamaño. Entonces no se si las coordenadas de cada tile son respecto al Panel, o al Form. De ser este ultimo caso veo muy dificil calcular a que pictBox estoy apuntando. Mañana le echo un ojo y ya os comento ;)

Gracias de nuevo.

Saludos!
Yo no muero hasta la muerte -

Vicente

 Hola,

yo diría que las coordenadas te las da en base al contenedor donde has pinchado. Por cierto, creo que zupervaca hizo un editor de tiles en C#, lo mismo le puedes echar un ojo. Un saludo!

Vicente

nsL

 Si, es lo mas logico, porq cuando agregas un controlador al contenedor y le indicas coordenadas las hace respecto a las del contenedor, asi q me parece q va a ser mas facil de lo que parece  (ole)

Lo de zupervaca ya lo habia pensado, le tendre q echar un ojo a ver q tal. Y a ver si esta el codigo pa bajar, y no solo el editor, sino estoy igual :P

Saludos!
Yo no muero hasta la muerte -

zupervaca

 Si lo hice cuando estaba aprendiendo c-sharp, el metodo que usaba era tener imagenes por separado y luego las pintaba sobre un control panel, tambien tenia una imagen con todos los tiles para mostrarla en el panel izquierdo, como el codigo que habia hecho era tan cutre me dio verguenza enseñarlo :lol:, no obstante no ofusque el codigo con lo que podras hecharle un ojo con algun programa, mi idea era tener algo hecho para luego reescribir todo el codigo y dejarlo limpio, pero no tuve nunca mas ni ganas ni tiempo :)

Editado: He mirado otra vez el proyecto y almaceno las imagenes en clases Bitmap y luego las pinto usando la funcion DrawImageUnscaled de Graphics, si no creo recordar mal el tema de pintar en un graphics era lentisimo y tuve que hacer que no borrara el fondo del control y hacerlo yo solo en las zonas que pinto los bitmaps, es decir, dibujar solo lo necesario mediante el rectangle que nos pasan a la funcion de dibujar el control.

nsL

 Me he bajado tu pack de herramientas, y la verdad, no se como estaran en cuanto a codigo, pero tienen wena pinta :D

He estado mirando en la ayuda de msdn sobre DrawImageUnscaled y el PaintEventArgs y parece un wen metodo. Probare varias formas y vere a ver cual se adapta mejor :P. Lo que tu explicabas de los rectangulos te refieres a el metodo de Dirty Rectangles o algo asi no? en plan actualizar el rectangulo que vas a pintar y nada mas...

Gracias por la info y la ayuda!

Saludos!
Yo no muero hasta la muerte -

nsL

 Madre mia que caos :D

He estado probando mil cosas, y he hecho y rehecho codigo pa'lante y pa'tras. He probado estas opciones:

1. La idea inicial de tener un array de pictureboxes, donde meter cada tile, todos ellos dentro de un panel. Este metodo me funciona de momento, salvo unos eventos de raton. Por ejemplo, hago que cuando el puntero pase por encima de 1 picturebox, este ponga su borderStyle a bordersimple o algo asi, pa que parezca q esta recuadrado. Esto funciona bien, pero se van quedando todos los pictbox con el borde, asi que le meti otro evento para q cuando el puntero salga del pictbox se quite el borde. Este evento funciona cuando quiere. Si el puntero va muy rapido se los deja con borde... en fin una chapuza.

2. He probado lo que decia vicente de pintar directamente sobre el panel. Y si, funciona, lo que pasa es que si pinto algo fuera de los limites visibles del panel, pues no me sale la barra de Autoscroll, ya q solo sale cuando un Control esta fuera de los limites. Y no estoy usando ningun control , solo pinto el fondo del panel.

3. Tb he probado lo "que creo" que decia zupervaca. Me cargo cada imagen en una clase Image (en bitmap no puedo ya que aun heredando de la clase image, el metodo para cargar los ficheros (FromFile) me devuelve un Image y no un bitmap). He intentado usar como fondo del panel un objeto de la clase image, para ver si salian las barras de autoscroll y asi pintar sobre esa "plantilla". Pero resulta q no es un control, y no se puede hacer.

En fin, las ideas creo q las tengo, pero me falta destrza con los controles y demas cosas de Windows Forms y C# para hacer el maldito editor :P

Alguna idea mas clarividente sobre que tengo q hacer exactamente? Respuestas en plan: create un panel que tenga un bla bla bla y, ahi pintas no se ke :P Diciendome exactamente q deberia usar :D

Saludos y mil gracias de antemano!
Yo no muero hasta la muerte -

Vicente

 Hola,

el problema del autoscroll es un poco pesado. Esto no te aseguro que sea así, pero creo que es lo que te pasa: tu estás pintando fuera de pantalla, y además, fuera del panel. Tienes que conseguir que el panel crezca para que aparezca el scroll. Si estás usando docking, tu puedes ponerle un tamaño al panel (el que te de la gana), pero el manejador del layout va a saltarse tu decisión para cumplir la propiedad de docking (lo mismo si usaras layouts de C# 2.0). Puede que lo que te ocurra sea esto.

Si no te funciona dilo, que si tengo un rato hago un ejemplo ;) Un saludo!

Vicente

Edit: en Winforms Quickstarts a lo mejor encuentras algo de info.

nsL

 Este es el procedimiento que uso:

Citar
  public void assignForm(Panel mainPanel)
  {
     imagen =  System.Drawing.Bitmap.FromFile("hola.jpg");
     mainPanel.Paint += new PaintEventHandler(panelPaint);
     mainPanel.Invalidate();
  }

Le meto el evento de pintado y invalido el panel para q lo repinte.

El procedimiento de pintado es este:

 public void panelPaint (object sender,PaintEventArgs e)
 {
  Point arribaIz = new Point(300, 0);
  Point arribaDe = new Point(400, 0);
  Point abajoIz = new Point(300, 100);
  Point [] destPara = {arribaIz, arribaDe, abajoIz};
  e.Graphics.DrawImage(imagen, destPara);
 }


Y lo que ma sale es esto:



Pero si dibujo mitad fuera del panel y mitad dentro no sale el autoscroll pero si lo dibuja:

 public void panelPaint (object sender,PaintEventArgs e)
 {
  Point arribaIz = new Point(500, 0);
  Point arribaDe = new Point(600, 0);
  Point abajoIz = new Point(500, 100);
  Point [] destPara = {arribaIz, arribaDe, abajoIz};
  e.Graphics.DrawImage(imagen, destPara);
 }



Segun lei en msdn la funcion de autoscroll del panel sale cuando esta fuera del rango un control. Parece ser que el pintado no le afecta. Estaria bien poder forzarle a crear autoscroll, aunq no se si se podra. Tb se me paso por la cabeza crear un control invisible. Por ejemplo, si pinto el panel por la derecha 100 pixeles mas alla del rango de vision, creo un control invisible a esa distancia y lo mismo para abajo. Y solo usando 2 solucionaria (creo) el problema. Pero probablemente sea la cosa mas chapuza que haya programado nunca xDDD

Por cierto, eso de docking que se supone q es? es qu viendo la definicion que dan a la propiedad en el VS no me queda muy claro aun :S

Saludos y (gracias) elevado a mil!
Yo no muero hasta la muerte -

zupervaca

 Para leer un archivo en un bitmap haz esto:

Bitmap imagen = new Bitmap("imagen.png");

Un truco para redimensionar los paneles (es un truco guarro) es crear un control panel hijo del control que quieras tener barras de scroll desde el editor de formularios y posicionarlo desde codigo, algo asi:

determinatamanio.Bounds = new Rectangle( anchomapa, altomapa, 0, 0);
Asi obligas al panel a mostrar las barras de scroll, asegurate que la propiedad AutoScroll del panel padre de este este control esta true, ademas por suerte (mas milagro que otra cosa) los controles panel no crean un nuevo dispositivo de contexto para su contenido solventando el problema de que pudiera chupar mucha memoria segun fuera mas grande, he de decirte que en windows vista pintar con drawimage, o usar controles picutrebox hace que la aplicacion vaya muy, pero que muy lenta, asi como a los 1000 picturebox la aplicacion genera un error, creo que la solucion perfecta es usar una llamada a bitblt del gdi de win32 mediante una dllimport.

Editado: He hecho el codigo del bitblt por si quieres probarlo:

       using System.Runtime.InteropServices;
       [DllImport("gdi32.dll")]
       private static extern bool BitBlt(IntPtr obj, int xDest, int yDest, int widthDest,
           int heightDest, IntPtr objSource, int xSource, int ySource, int rop);
       [DllImport("gdi32.dll")]
           public static extern IntPtr CreateCompatibleDC(IntPtr dc);
       [DllImport("gdi32.dll")]
           public static extern bool DeleteDC(IntPtr dc);
       [DllImport("gdi32.dll")]
           public static extern IntPtr SelectObject(IntPtr dc, IntPtr obj);
       [DllImport("gdi32.dll")]
           public static extern bool DeleteObject(IntPtr obj);

       // Pintar una imagen usando el GDI de Win32
       private void DrawImage(Graphics g, Bitmap image, int x, int y)
       {
           IntPtr target = g.GetHdc();
           IntPtr source = CreateCompatibleDC(target);
           IntPtr oldObj = SelectObject(source, image.GetHbitmap());
           BitBlt(target, x, y, image.Width, image.Height, source, 0, 0, 0x00CC0020);
           IntPtr newObj = SelectObject(source, oldObj);
           DeleteObject(newObj);
           DeleteDC(source);
           g.ReleaseHdc(target);
       }

En el vista me ha acelerado un poco, pero no lo suficiente, puede que en el xp vaya mucho mas rapido.






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.