Home   Artículos   Recursos   Foros   
Artíclos recientes publicados en Latindevelopers:
Visual C++: NSDoubleEdit: Un control para el manejo de números decimales en Visual C++.
Visual C++: Implementando una Calculadora en Visual C++
Visual C++: CCommandLine: Una clase para el uso de la linea de comando
Visual C++: Una clase para el manejo del Registro

Graficos en Aplicacion Basada en Dialogos

Aqui programadores en la plataforma Win32 con Visual C++ de Microsoft...

Moderador: latindeveloper

Graficos en Aplicacion Basada en Dialogos

Notapor oscargim el Jue Jun 14, 2007 4:51 am

Tengo un proyecto MFC basado en Dialogos y quiero hacer graficos.
Lo que quiero simplemente que una parte de mi dialogo haya un dibujito de lineas nada mas que una linea recta.
La finalidad es crear mi propio Chart de lineas, ya que he buscado muchos y no encontre uno que sea de lineas que me guste.
Desde ya muchas gracias
oscargim
Usuario Muy Activo
Usuario Muy Activo
 
Mensajes: 113
Registrado: Mar May 09, 2006 5:53 am

Notapor oscargim el Jue Jun 14, 2007 8:18 am

Logre lo que queria

Código: Seleccionar todo
   CClientDC dlgDC(GetDlgItem(IDC_STATIC));   
   int x,y;
   CRect rect;
   GetDlgItem(IDC_STATIC)->GetClientRect(&rect);
   for (x=0; x<=rect.Width(); x++)
      for(y=0; y<=rect.Height(); y++)
         dlgDC.SetPixel (x,y,RGB(255,255,255)); 
   dlgDC.MoveTo( 0, 10 );
   dlgDC.LineTo (60,60);


Ahora el problema esta en que cada vez que saco el foco de mi ventana mi grafico se borra,
Como hago para que no suceda esto?

Espero que a alguien le sirva mi ejemplo
oscargim
Usuario Muy Activo
Usuario Muy Activo
 
Mensajes: 113
Registrado: Mar May 09, 2006 5:53 am

OnPaint

Notapor latindeveloper el Jue Jun 14, 2007 4:38 pm

Tienes que poner el codigo en la funcion OnPaint que es invocada por el mensaje WM_PAINT , en ese caso encontrarás una variable

CPaintDC dc(this);

con la que ienes que pintar.
Imagen
Avatar de Usuario
latindeveloper
Administrador
Administrador
 
Mensajes: 1061
Registrado: Lun Jun 02, 2003 8:29 pm
Ubicación: Peru

Notapor oscargim el Jue Jun 14, 2007 8:05 pm

Como siempre excelente, cortitas consistas y muy satisfactoria tus respuestas.
Ahora pregunto si saben como hacer la lina de

Código: Seleccionar todo
dlgDC.MoveTo( 0, 10 );
dlgDC.LineTo (60,60);


que sea mas grueza y con colores?
oscargim
Usuario Muy Activo
Usuario Muy Activo
 
Mensajes: 113
Registrado: Mar May 09, 2006 5:53 am

Notapor latindeveloper el Vie Jun 15, 2007 1:55 pm

Tienes que cambiar de pincel.

Código: Seleccionar todo
//Creando un pincel verde de 10 pixeles de ancho
CPen pen;
pen.CreatePen(PS_SOLID, 10, RGB(0,255,0));

CPen *oldPen = dlgDC.SelectObject(&pen);

dlgDC.MoveTo( 0, 10 );
dlgDC.LineTo (60,60);


dlgDC.SelectObject(oldPen);[/code]
Imagen
Avatar de Usuario
latindeveloper
Administrador
Administrador
 
Mensajes: 1061
Registrado: Lun Jun 02, 2003 8:29 pm
Ubicación: Peru

Notapor oscargim el Lun Jun 18, 2007 8:30 am

Bueno, despues de probar un trillon de veces, logre hacer mi propio graficador de lineas.
Espero que a alguien le sirva, no es de lo mejor pero si que funciona. Y lo publico para que alguien me ayude a mejorarlo.
No es nada mas que un par de funciones con variables publicas, se hace el grafico sobre un static que le puse nombre IDC_STATI, ya que si hay oto static no funca, plis agradeceria si alguien me ayuda en esa parte.
El grafico se muestra en la linea "y" una linea de tiempo y en la "x" un valor en la fecha determinada, los datos deben estar dentro de una estructura. Es recomendable tiempos de mas de 3 años.

Declarar las funciones y variables publicas a usar

Código: Seleccionar todo
   int x,y;
   struct sancione
   {
      int x;
      char y[20];
   } Sanc[100];//lo hice de esta manera porque no tengo mas tiempo, estoy super apurado
   void CargaStruct(CString caco);
   void Cuadricula (COleDateTime desd, COleDateTime hast,int max_x);
//fecha desde es la fecha minima del grafico
//fecha desde es la fecha maxima del grafico
//Max_x es el valor maximo de la estructura
//el minimo es 0
   COleDateTime desde;
   COleDateTime hasta;



pegar en el cpp lo siguiente:

Código: Seleccionar todo
void CMiClase::CargaStruct (CString legajo)
{
   x=y=0;
// aca hago un selec dato, fecha
   result=PQexec (cone,sql);
   if (PQresultStatus(result)==PGRES_TUPLES_OK)
      if (PQntuples(result)!=0)
      {
         for (int i=0;i<PQntuples(result);i++)
         {
            Sanc[i].x=atoi(PQgetvalue (result,i,0));// la cantidad de datos
            strcpy (Sanc[i].y,PQgetvalue (result,i,1));//fecha que corresponde al dato
         }
         Sanc[i].x=NULL;
      }
      else
         Sanc[0].x=NULL;
   maximo=20;
   // maximo es el valor mas alto para la columna X
   // puede ser cargado conforme lo que se obtiene
   // ej: con un selec MAX(dato) group by dato order by dato desc   
   Cuadricula (desde, hasta, maximo);
};
/*
sea cual fuere la forma lo importante es cargar algo como esto
Sanc[0].x=12;
Sanc[0].y="1997-05-01";

Sanc[1].x=2;
Sanc[1].y="2005-01-08";

Sanc[2].x=NULL;
*/


void CMiClase::Cuadricula (COleDateTime desd, COleDateTime hast, int max_x)
{
   if (desd>hast)
      return;
   if (max_x==0)
      return;

   COleDateTime aux (desd);
   CClientDC dlgDC(GetDlgItem(IDC_STATI));   
   CRect rect;
   GetDlgItem(IDC_STATI)->GetClientRect(&rect);
/////////////////////////////////// CUADRICULAS
//////////////// Linea de Tiempo   
   CString anio;
   COleDateTimeSpan dias;
   dias=hast-desd;
   int total=dias.GetDays();
   int punto=0, maxx;
   for (aux;aux<hast;aux+=1)
   {
      if (aux.GetDay()==1 && aux.GetMonth ()==1)//para hacer una linea por año... Oviamente el 1 de Enero...
      {

         /*   dias.GetDays()*rect.Width()/total
            es una regla de 3 simple para obtener los pixels
            total tiene todos los dias de "desde" a "hasta"
            si total=rect.Width() (osea el ancho del Static)
            cuanto seria dias.GetDays().
         */
         dias=aux-desd;
         dlgDC.MoveTo(dias.GetDays()*rect.Width()/total,0 );//
         dlgDC.LineTo(dias.GetDays()*rect.Width()/total,rect.Height()); 
         
         if (((dias.GetDays()*rect.Width()/total)-17)>=punto+34 || punto==0)//para q los años no se encimen
         {
            dlgDC.TextOut((dias.GetDays()*rect.Width()/total)-17,rect.Height(),aux.Format("%Y")); 
            punto=(dias.GetDays()*rect.Width()/total)-17;
         }
      }
   }
////////////////
   int fila=rect.Height()/max_x;
   punto=0;
   maxx=max_x-1;
   for (int I=fila;I<rect.Height();I+=fila)
   {
      if (I>punto+15 || punto==0)//mismo concepto... para que no se encimen los numeros
      {
         anio.Format("%d",maxx);//economia de variables...
         dlgDC.MoveTo(0,I);//
         dlgDC.LineTo(rect.Width(),I); 
         dlgDC.TextOut(-25,I-10,anio);
         punto=I;
      }
      maxx--;// en linea vertical el 0 esta arriba. Asi se muestra invertido.
   }
/////////////////////////////////// LINEAS DE VALORES
   CPen pen;
   pen.CreatePen(PS_SOLID, 3, RGB(0,0,255));
   CPen *oldPen = dlgDC.SelectObject(&pen);

   CString fecha;
   for (int i=0;i<1000;i++)
   {
      if (Sanc[i].x==NULL)
         break;
      else
      {

            fecha.Format("%s",Sanc[i].y);
            aux.SetDate(atoi(fecha.Left(4)),atoi(fecha.Mid(5,6)),atoi(fecha.Right(2)));
            dias=aux-desd;

            if (x!=0 && y!=0)
               dlgDC.MoveTo(  x,y );
            else
            {
            x=dias.GetDays()*rect.Width()/total;
            y=rect.Height()-((rect.Height()/max_x)*Sanc[i].x);
            dlgDC.MoveTo(x,y); 

            }

            x=dias.GetDays()*rect.Width()/total;
            y=rect.Height()-((rect.Height()/max_x)*Sanc[i].x);
            dlgDC.LineTo(x,y); 
            dlgDC.Ellipse( x-2, y-2,x+5, y+5 );
      }
   }
   x=y=0;
}


con el Windows Message Handle agregar la funcion OnPaint
y dentro colocar la funcion Cuadricula (desde, hasta,maximo);

Código: Seleccionar todo
void CMiClase::OnPaint()
{
   CPaintDC dc(this); // device context for painting
   // TODO: Add your message handler code here
   Cuadricula (desde, hasta,maximo);
   // Do not call CDialog::OnPaint() for painting messages
}

tener en cuenta que se debe cargar "desde" y "hasta" antes de llamar la funcion CargaStruct(legajo)

sancion->desde=desde;
sancion->hasta=hasta;
sancion->CargaStruct(legajo);
oscargim
Usuario Muy Activo
Usuario Muy Activo
 
Mensajes: 113
Registrado: Mar May 09, 2006 5:53 am

Notapor oscargim el Jue Jun 21, 2007 12:06 pm

Tengo una duda.
La funcion anda bien pero al invocarla muchas veces seguidas el dibujo se pinta fuera del dialogo , tomando las coordenadas del escritorio, me explico?
si en el grafico una linea se pinta en las coordenadas 15 15, pasa a pintar las mismas coordenadas en la pantalla osea en la esquina superior.
Que puede causar esto?
Como Libero la memoria que utiliza el grafico?, puede ser este el problema?
En que le estoy errando?
oscargim
Usuario Muy Activo
Usuario Muy Activo
 
Mensajes: 113
Registrado: Mar May 09, 2006 5:53 am


Volver a Visual C++

¿Quién está conectado?

Usuarios navegando por este Foro: No hay usuarios registrados visitando el Foro y 1 invitado