Sei sulla pagina 1di 106

Universidad Nacional de

Ingeniería
Ingeniería Mecánica

Gráficos en
Visual C++

1
• Para gráficos (incluyendo texto) en Visual C++
Windows utiliza la interfaz Graphics Device Interfaz
(GDI) lo que llama a los gestores de dispositivo ya
sea de video, impresora o trazadores de gráficos ya
establecidos.
• Se tiene a la
interfaz GDI
que provee
de la
aplicación y
va al
dispositivo

Ing. Daniel Osorio Maldonado 29/11/2019 2


Contexto de Dispositivo
Windows no permite el acceso directo al hardware de
visualización, lo hace utilizando un nivel de abstracción
denominado contexto de dispositivo (DC).
Un contexto de dispositivo (DC) es una estructura de datos,
mantenida internamente por el GDI que contiene los
atributos básicos para graficar o poner un texto.

Un ejemplo es el OnDraw en
Visual C++.
La ventanita que se aprecia fue
confeccionada en un
documento unico.

Ing. Daniel Osorio Maldonado 29/11/2019 3


Ing. Daniel Osorio Maldonado 29/11/2019 4
Ing. Daniel Osorio Maldonado 29/11/2019 5
Ing. Daniel Osorio Maldonado 29/11/2019 6
Ing. Daniel Osorio Maldonado 29/11/2019 7
Ing. Daniel Osorio Maldonado 29/11/2019 8
Ing. Daniel Osorio Maldonado 29/11/2019 9
Ing. Daniel Osorio Maldonado 29/11/2019 10
Ing. Daniel Osorio Maldonado 29/11/2019 11
Ing. Daniel Osorio Maldonado 29/11/2019 12
Ing. Daniel Osorio Maldonado 29/11/2019 13
Ing. Daniel Osorio Maldonado 29/11/2019 14
Atributos del Contexto de
Dispositivo
Cuando Windows crea un dispositivo asigna valores
por omisión para todos los atributos.
Para que una aplicación pueda obtener o modificar
cualquiera de estos atributos , la GDI proporciona
las funciones que a continuación se detallan.

Ing. Daniel Osorio Maldonado 29/11/2019 15


ATRIBUTOS POR OMISION MODIFICAR OBTENER
Modo de M_MTEXT SetMapMode GetMapMode
conversión

Origen de (0,0) SetWindowOrg GetWindowOrg


ventana OffSetWindowOrg
Tamaño lógico de (1,1) SetWindowExt GetWindowExp
la ventana lógica SetMapMode
Origen de la (0,0) SetViewportOrg GetViewportOrg
superficie de la OffsetViewportOrg
proyección
Tamaño de la (1,1) SetViewportExt GetViewportExt
superficie de SetMapMode
proyección

Pluma BLACK_PEN SelecObject SelecObject

Ing. Daniel Osorio Maldonado 29/11/2019 16


ATRIBUTOS POR OMISION MODIFICAR OBTENER
Posición actual (0,0) MoveTo, LineTo, GetCurrentPosition
de la pluma ArcTO, PolylineTo
Pincel WHITE_BRUSH SelecObject SelecObject

Origen del (0,0) SetBrushOrg GetBrushOrg


pincel
Color de texto Negro SetTextColor GetTextColor

Fuente SISTEM_FONT SelecObject SelecObject


Mapa de bits Ninguno SelecObject SelecObject

Color de fondo Blanco SetBkColor GetBkColor

Modo de fondo OPAQUE SetBkMode GetBkMode

Ing. Daniel Osorio Maldonado 29/11/2019 17


ATRIBUTOS POR OMISION MODIFICAR OBTENER
Modo de dibujo R2_copypen SetROP2 GetROP2
Modo de ajuste BLACKONWHITE SetStrechBltMode GetStrechBltMode

Modo de relleno ALTERNATE SetPolyFillMode GetPolyFillMode

Con estas funciones básicas se puede graficar en la


pantalla de dispositivo así como en Visual C++
Activando la pestaña vista de clases se aprecia la
clase CElipse0View.
Haciendo clic botón derecho en ella podrá apreciar
Asistente para clase.
Ir a la pestaña Mensajes y en ella vera el método On
Paint. Aprecie en los gráficos lo dicho.

Ing. Daniel Osorio Maldonado 29/11/2019 18


Ing. Daniel Osorio Maldonado 29/11/2019 19
Ing. Daniel Osorio Maldonado 29/11/2019 20
Ing. Daniel Osorio Maldonado 29/11/2019 21
Ing. Daniel Osorio Maldonado 29/11/2019 22
Objetos GDI
La GDI de Windows emplea herramientas de dibujo, incluyendo plumas ,
pinceles tipos de letra, mapas bits, paleta de color y regiones, que se
contempla en la MFC.
//DIBUJA Y RELLENA UNA ELIPSE DE COLOR AMARILLO
CElipseView::OnPaint()
{
static DWORD dwColor[9]={RGB(0,0,0),RGB(255,0,0),
RGB(0,255,0),RGB(0,0,255),
RGB(255,255,0),RGB(255,0,255), RGB(0,255,255),
RGB(128,128,128), RGB(255,255,255)};
POINT polylpts[4], polygpts[5];
int xcoord;
CBrush n_brocha;
CBrush *v_brocha;
CPen n_pincel;
CPen *v_pincel;
n_pincel.CreatePen(PS_SOLID, 2,dwColor[3]);
/* n_pincel.CreatePen(PS_SOLID, ancho de la línea de borde, dwColor [color
de la línea de borde]); */
v_pincel=dc.SelectObject(&n_pincel);
n_brocha. CreateSolidBrush(dwColor[4]);
//n_brocha. CreateSolidBrush(dwColor[color del relleno])
Ing. Daniel Osorio Maldonado 29/11/2019 23
v_brocha=dc.SelectObject(&n_brocha);
dc.Ellipse(475,400,100,150);//los dos primeros dan las dimensiones de la elipse
//superior ,los otros 2 dan la ubicación de los puntos uno de la parte derecha
//el otro de la parte izquierda
dc.TextOutW(220,265,_T(«elipse»),6); //visualiza textos dc.TextOut(posición X,
posición Y, “ Texto ", numero de letras del texto);
dc.SelectObject(v_brocha); //selecciona al objeto GDI y lo incorpora al
dispositivo
n_brocha.DeleteObject();
dc.SelectObject(v_pincel);
n_pincel.DeleteObject();

Ing. Daniel Osorio Maldonado 29/11/2019 24


Asociación de Colores
Windows utiliza un entero de 32 bits para
representar un color.
El byte menos especificativo es el color rojo el
siguiente el verde, el siguiente el azul y el otro
no se utiliza.

Ing. Daniel Osorio Maldonado 29/11/2019 25


Normalmente a este entero lo denominamos “color
RGB”.
La macro RGB de la Windows convierte a estos colores
a un color en conjunto como ...COLORREF color = RGB
(0,250,0), este valor es para el verde.
Cuando los 3 valores son cero (RGB (0,0,0)) el color es
negro cuando los 3 valores son 250 (RGB(250,250,250))
es blanco.

Ing. Daniel Osorio Maldonado 29/11/2019 26


Color Nivel de Azul Nivel de Verde Nivel de Rojo
Negro 0 0 0
Azul 255 0 0
Verde intenso 0 255 0
Aguamarina 255 255 0
Rojo 0 0 255
Fucsia 255 0 255
Amarillo 0 255 255
Blanco 255 255 255
Azul Marino 128 0 0
Verde 0 128 0
Verde Azul 128 128 0
Granate 0 0 128
Púrpura 128 0 0
Ing. Daniel Osorio Maldonado 29/11/2019 27
Color Nivel de Azul Nivel de Verde Nivel de Rojo
Verde oliva 0 128 128
Gris 128 128 128
Gris Plata 192 192 192

Otros colores definidos por Windows son :

Color Nivel de Azul Nivel de Verde Nivel de Rojo

Verde claro 192 220 192

Azul claro 240 202 166

Marfil 240 251 255

Gris mediano 164 160 160


Ing. Daniel Osorio Maldonado 29/11/2019 28
DIBUJAR EN VISUAL C++
Hasta ahora las unidades que se han
empleado para dibujar han sido los píxeles,
también denominadas “unidad de
dispositivo”.
Windows proporciona varios modos de
proyección (también denominados modos de
mapeado o modos de conversión) que se
puede asociar con el dispositivo sobre el que
se esta dibujando,si queremos graficar una
circunferencia podemos elegir como modo
de proyección MM_LOMETRIC, ya que en este
modo la unidad lógica tiene 0.1 mm, en vez
de un píxel, pero habrá de tener presente que
en éste modo el eje Y aumenta hacia arriba,
cuando utilizamos el MM_TEXT aumenta hacia
abajo.
Ing. Daniel Osorio Maldonado 29/11/2019 29
Con SetWindowExt(540,900) se puede tener la relación
de las unidades de la ventana lógica.
Con SetViewportOrg(cx,-cy), con SetViewportExt(cx,-
cy), y SetViewportOrg(cx/2,cy/2) la posición de
coordenadas.

Ing. Daniel Osorio Maldonado 29/11/2019 30


Unidades de un sistema de coordenadas
Las unidades de un sistema de coordenadas X-Y dependen del
modo de proyección empleado.
Además de MM_TEXT, hay cinco modos de proyección
métricos y dos personalizados, que podemos ver en la siguiente
tabla.

Modo de Unidad X aumenta Y aumenta


proyección lógica hacia hacia
MM_TEXT 1 Pixel Derecha abajo
MM_TWIPS 1 twip Derecha arriba
MM_LOMERIC 0.1 mm Derecha arriba
MM_HIMETRIC 0.01 mm Derecha arriba
Ing. Daniel Osorio Maldonado 29/11/2019 31
Modo de Unidad X aumenta Y aumenta
proyección lógica hacia hacia
MM_LOENGLISH 0.01 Pul Derecha arriba
MM_TWIPS 0.001 Pul Derecha arriba

MM_ISOTROPIC arbitrario Seleccionable Seleccionable


MM_ANISOTROPIC arbitrario Seleccionable Seleccionable

Para ajustar el sistema de coordenadas a uno de


estos se debe llamar a la función miembro
CDC::SetMapMode.
Por ejemplo el GetClientRect no es una función
GDI por lo tanto seguirá devolviendo las
coordenadas en pixeles.
Ing. Daniel Osorio Maldonado 29/11/2019 32
Modo de Proyección MM_TEXT
Dado por omisión, la unidad se mide en pixeles, X aumenta
hacia la derecha e Y hacia abajo, la razón entre la pantalla
lógica y la superficie de proyección es 1 , se puede variar el
origen de coordenadas con la función:
CDC::SetViewprtOrg o la función CDC::SetWindowOrg.

//Establecer la escala del sistema de coordenadas

dc.SetWindowExt(840,300); //nos da el nivel de ampliación de la


//ventana que no es para pixeles

dc.SetViewportOrg(cx,-cy); //supuestamente lleva el origen al


// centro de la pantalla
dc.SetViewportExt(cx,-cy);

dc.SetViewportOrg(cx/2,cy/2);//lleva el origen de coordenadas al


//centro de la pantalla física y a la superficie de grafico

Ing. Daniel Osorio Maldonado 29/11/2019 33


• void CEJESCOORDENADASView::OnDraw(CDC* pDC){
• CEJESCOORDENADASDoc* pDoc = GetDocument();
DIBUJA LINEAS DE LOS EJES CORDENADOS
• ASSERT_VALID(pDoc);
• if (!pDoc)
• return;
• CClientDC dc(this);
• dc.SetViewportOrg (300,300);
• static DWORD dwColor[9]={RGB(0,0,0),RGB(255,0,0),
RGB(0,255,0),RGB(0,0,255),RGB(255,255,0),RGB(255,0,255),
RGB(0,255,255),RGB(127,127,127), RGB(255,255,255)};
• POINT polylpts[4], polygpts[5];
• int xcoord;
• CBrush n_brocha;
• CBrush *v_brocha;
• CPen n_pincel;
• CPen *v_pincel;
• n_pincel.CreatePen(PS_SOLID, 1,dwColor[0]);
• v_pincel=dc.SelectObject(&n_pincel);
• dc.MoveTo(0,-140);//punto inicial
• dc.LineTo(0,140);//punto final
• dc.TextOutW(0,-150,_T("Y"),1);
• dc.SelectObject(v_pincel);
• n_pincel.DeleteObject();
• n_pincel.CreatePen(PS_SOLID, 1,dwColor[0]);//características de
• //las líneas de trazado
• v_pincel=dc.SelectObject(&n_pincel);
• dc.MoveTo(-100,0); //punto inicial
• dc.LineTo(300,0); //punto final
• dc.TextOutW(305,0,_T("X"),1);
• dc.SelectObject(v_pincel);
• n_pincel.DeleteObject();}

Ing. Daniel Osorio Maldonado 29/11/2019 34


Ing. Daniel Osorio Maldonado 29/11/2019 35
Modo de Proyecciones Metricas
Los modos de proyección MM_TEXT, MM_TWIPS,
MM_LOMERIC, MM_HIMETRIC y MM_LOENGLISH las
unidades del eje X e Y se expresan en medidas físicas
idénticas para ambos.

Ing. Daniel Osorio Maldonado 29/11/2019 36


Ing. Daniel Osorio Maldonado 29/11/2019 37
Modos de Proyección Personalizados
Son los MM_ISOTROPIC, MM_ANISOTROPIC
cuando se utiliza estos modos de proyección
se puede cambiar tanto el origen de
coordenadas como la razón, características
que permiten cambiar el tamaño delas
figuras cuando se redimensiones las
ventanas.

El sistema de proyección MM_ISOTROPIC


expresan las coordenadas x e y en unidades
lógicas de tamaño físico idéntico, en cambio
MM_ANISOTROPIC expresan las
coordenadas x e y en unidades lógicas de
tamaño físico distinto

Ing. Daniel Osorio Maldonado 29/11/2019 38


En el sistema MM_ISOTROPIC la razón de la
pantalla física y la lógica es uno.

Ing. Daniel Osorio Maldonado 29/11/2019 39


En el sistema MM_ANISOTROPIC la razón de
la pantalla física y la lógica es distinto a uno.
Ing. Daniel Osorio Maldonado 29/11/2019 40
Con la función dc.SetMapMode(MM_ANISOTROPIC); la
grafica de la cúbica es al tope por el eje Y.

Ing. Daniel Osorio Maldonado 29/11/2019 41


Con la función dc.SetMapMode(MM_ISOTROPIC);
la grafica de la cúbica no se ajusta a la ventana
de grafico.

Ing. Daniel Osorio Maldonado 29/11/2019 42


Creación de una grafica en Visual C++
Paso 1: Seleccione File/New de la lista de opciones del menú,
aparecerá un cuadro de dialogo que permitirá iniciar un
nuevo proyecto.

Ing. Daniel Osorio Maldonado 29/11/2019 43


EJEMPLOS DE GRAFICAS
Agregar la librería #include <math.h>

void CGRAFICADELARAIZView::OnPaint()
{ CPaintDC dc(this);
static DWORD dwColor[9]={RGB(0,0,0), RGB(255,0,0), RGB(0,255,0),
RGB(0,0,255), RGB(255,255,0), RGB(255,0,255), RGB(0,255,255),
RGB(127,127,127), RGB(255,255,255)};
CPen n_pincel;
CPen *v_pincel;
CRect rect;
GetClientRect(rect);
int cx=(rect.right -rect.left);
int cy=(rect.bottom-rect.top);
dc.SetMapMode(MM_ANISOTROPIC);
//Establecer la escala del sistema de coordenadas
dc.SetWindowExt(840,300);
dc.SetViewportOrg(cx,-cy);
dc.SetViewportExt(cx,-cy);
dc.SetViewportOrg(cx/2,cy/2);
Ing. Daniel Osorio Maldonado 29/11/2019 44
//Dibujar curvas
float x,x2;
for (x=0; x<300; x+=0.1)//valores de x a evaluar
{x2=(8*pow(x,0.5));//
dc.SetPixel(x,x2,RGB(0,0,255));//permite visualizar la grafica
dc.TextOut(50,40,"RAIZ");//crea un texto dentro de la pantalla }
//DIBUJA LINEAS DE LOS EJES COORDENADOS
n_pincel.CreatePen(PS_SOLID, 1,dwColor[0]);
v_pincel=dc.SelectObject(&n_pincel);
dc.MoveTo(0,-140);
dc.LineTo(0,140);
dc.TextOutW(0,145,_T("Y”),1);
dc.SelectObject(v_pincel);
n_pincel.DeleteObject();
n_pincel.CreatePen(PS_SOLID, 1,dwColor[0]);
v_pincel=dc.SelectObject(&n_pincel);
dc.MoveTo(-100,0);
dc.LineTo(300,0);
dc.TextOut(305,0,"X",1);
dc.SelectObject(v_pincel);
n_pincel.DeleteObject();
}
Ing. Daniel Osorio Maldonado 29/11/2019 45
Muestra el siguiente grafico

Ing. Daniel Osorio Maldonado 29/11/2019 46


void CGRAFICADELACUBICAView::OnPaint()
{CPaintDC dc(this); // device context for painting
static DWORD dwColor[9]={RGB(0,0,0), RGB(255,0,0), RGB(0,255,0), RGB(0,0,255),
RGB(255,255,0), RGB(255,0,255), RGB(0,255,255), RGB(127,127,127),
RGB(255,255,255)};
CPen n_pincel;
CPen *v_pincel;
CRect rect;
GetClientRect(rect);
int cx=(rect.right -rect.left);
int cy=(rect.bottom-rect.top);
dc.SetMapMode(MM_ANISOTROPIC);
//Establecer la escala del sistema de coordenadas
dc.SetWindowExt(840,300);
dc.SetViewportOrg(cx,-cy);
dc.SetViewportExt(cx,-cy);
dc.SetViewportOrg(cx/2,cy/2);
//Dibujar curvas
float x,x3;
for (x=-395; x<395; x+=0.1)
{x3=(0.0002*pow(x,3));//
dc.SetPixel(x,x3,RGB(0,0,255));
dc.TextOut(50,40,"cubica");}

Ing. Daniel Osorio Maldonado 29/11/2019 47


//DIBUJA UNA LINEAS DE LOS EJES COORDENADOS
n_pincel.CreatePen(PS_SOLID, 1,dwColor[0]);
v_pincel=dc.SelectObject(&n_pincel);
dc.MoveTo(0,-140);
dc.LineTo(0,140);
dc.TextOut(0,145,"Y",1);
dc.SelectObject(v_pincel);
n_pincel.DeleteObject();

n_pincel.CreatePen(PS_SOLID, 1,dwColor[0]);
v_pincel=dc.SelectObject(&n_pincel);
dc.MoveTo(-100,0);
dc.LineTo(100,0);
dc.TextOut(105,0,"X",1);
dc.SelectObject(v_pincel);
n_pincel.DeleteObject();}

Ing. Daniel Osorio Maldonado 29/11/2019 48


Muestra el siguiente grafico

Ing. Daniel Osorio Maldonado 29/11/2019 49


void CGRAFICADELLOGARITMOView::OnPaint()
{CPaintDC dc(this);
static DWORD dwColor[9]={RGB(0,0,0),RGB(255,0,0),
RGB(0,255,0), RGB(0,0,255),RGB(255,255,0), RGB(255,0,255),
RGB(0,255,255), RGB(127,127,127), RGB(255,255,255)};
CPen n_pincel;
CPen *v_pincel;
CRect rect;
GetClientRect(rect);
int cx=(rect.right -rect.left);
int cy=(rect.bottom-rect.top);
dc.SetMapMode(MM_ANISOTROPIC);
//Establecer la escala del sistema de coordenadas
dc.SetWindowExt(840,300);
dc.SetViewportOrg(cx,-cy);
dc.SetViewportExt(cx,-cy);
dc.SetViewportOrg(cx/2,cy/2);
//Dibujar curvas
float x,loga;
for (x=0; x<300; x+=0.1)
{loga=100*log(x*0.02);
dc.SetPixel(x,loga,RGB(0,0,255));
dc.TextOut(50,40,"LOGARITMO");}

Ing. Daniel Osorio Maldonado 29/11/2019 50


//DIBUJA UNA LINEAS DE LOS EJES
CORDENADOS
n_pincel.CreatePen(PS_SOLID, 1,dwColor[0]);
v_pincel=dc.SelectObject(&n_pincel);
dc.MoveTo(0,-140);
dc.LineTo(0,140);
dc.TextOut(0,145,"Y",1);
dc.SelectObject(v_pincel);
n_pincel.DeleteObject();

n_pincel.CreatePen(PS_SOLID, 1,dwColor[0]);
v_pincel=dc.SelectObject(&n_pincel);
dc.MoveTo(-100,0);
dc.LineTo(300,0);
dc.TextOut(305,0,"X",1);
dc.SelectObject(v_pincel);
n_pincel.DeleteObject();
}

Ing. Daniel Osorio Maldonado 29/11/2019 51


Muestra el siguiente grafico

Ing. Daniel Osorio Maldonado 29/11/2019 52


void CGRAFICADELASECANTEView::OnPaint()
{CPaintDC dc(this);
static DWORD dwColor[9]={RGB(0,0,0),RGB(255,0,0),
RGB(0,255,0), RGB(0,0,255), RGB(255,255,0),RGB(255,0,255),
RGB(0,255,255), RGB(127,127,127),RGB(255,255,255)};
POINT polylpts[4], polygpts[5];
CPen n_pincel;
CPen *v_pincel;
CRect rect;
GetClientRect(rect);
int cx=(rect.right -rect.left);
int cy=(rect.bottom-rect.top);
dc.SetMapMode(MM_ANISOTROPIC);
//Establecer la escala del sistema de coordenadas
dc.SetWindowExt(1540,900);
dc.SetViewportOrg(cx,-cy);
dc.SetViewportExt(cx,-cy);
dc.SetViewportOrg(cx/2,cy/2);

Ing. Daniel Osorio Maldonado 29/11/2019 53


//Dibujar curvas
float x, sec;
for (x=-650; x<650; x+=0.1)
{sec=(int)(1/cos((double)x/100)*100);
dc.SetPixel(x,sec,RGB(255,0,0));
dc.TextOut(150,140,"SECANTE");}
// DIBUJA UNA LINEAS DE LOS EJES CORDENADOS
n_pincel.CreatePen(PS_SOLID, 1,dwColor[0]);
v_pincel=dc.SelectObject(&n_pincel);
dc.MoveTo(0,-440);
dc.LineTo(0,440);
dc.TextOut(0,445,"Y",1);
dc.SelectObject(v_pincel);
n_pincel.DeleteObject();
// DIBUJA UNA LINEAS DE LOS EJES CORDENADOS
n_pincel.CreatePen(PS_SOLID, 1,dwColor[0]);
v_pincel=dc.SelectObject(&n_pincel);
dc.MoveTo(-650,0);
dc.LineTo(650,0);
dc.TextOut(655,0,"X",1);
dc.SelectObject(v_pincel);
n_pincel.DeleteObject();

Ing. Daniel Osorio Maldonado 29/11/2019 54


Muestra el siguiente grafico

Ing. Daniel Osorio Maldonado 29/11/2019 55


void CGRAFICADELACOSECANTEView::OnPaint()
{CPaintDC dc(this);
static DWORD dwColor[9]={RGB(0,0,0), RGB(255,0,0), RGB(0,255,0),
RGB(0,0,255), RGB(255,255,0), RGB(255,0,255), GB(0,255,255),RGB(127,127,127),
RGB(255,255,255)};
POINT polylpts[4], polygpts[5];
CPen n_pincel;
CPen *v_pincel;
CRect rect;
GetClientRect(rect);
int cx=(rect.right -rect.left);
int cy=(rect.bottom-rect.top);
dc.SetMapMode(MM_ANISOTROPIC);
//Establecer la escala del sistema de coordenadas
dc.SetWindowExt(1540,900);
dc.SetViewportOrg(cx,-cy);
dc.SetViewportExt(cx,-cy);
dc.SetViewportOrg(cx/2,cy/2);
//Dibujar curvas
float x, cosec ;
for (x=-650; x<650; x+=0.1)
{cosec=(int)(1/sin((double)x/100)*100);dc.SetPixel(x,cosec,RGB(255,0,0));
dc.TextOut(150,140,"COSECANTE");}
Ing. Daniel Osorio Maldonado 29/11/2019 56
//DIBUJA UNA LINEAS DE LOS EJES COORDENADOS
n_pincel.CreatePen(PS_SOLID, 1,dwColor[0]);
v_pincel=dc.SelectObject(&n_pincel);
dc.MoveTo(0,-440);
dc.LineTo(0,440);
dc.TextOut(0,445,"Y",1);
dc.SelectObject(v_pincel);
n_pincel.DeleteObject();

n_pincel.CreatePen(PS_SOLID, 1,dwColor[0]);
v_pincel=dc.SelectObject(&n_pincel);
dc.MoveTo(-650,0);
dc.LineTo(650,0);
dc.TextOut(655,0,"X",1);
dc.SelectObject(v_pincel);
n_pincel.DeleteObject();
}

Ing. Daniel Osorio Maldonado 29/11/2019 57


Muestra el siguiente grafico

Ing. Daniel Osorio Maldonado 29/11/2019 58


GRAFICOS PERSISTENTES
Para que un gráfico realizado con métodos gráficos (imágenes y
texto) pueda ser reproducido automáticamente siempre que la
ventana que lo muestra reciba un mensaje WM_PAINT, la aplicación
debe conservar una copia del gráfico en memoria.
De aquí el nombre de gráficos persistentes.

Windows envía el mensaje XM.PAINT cuando:


• Una ventana se construye por primera vez.
• Una ventana se superpone encima de otra.
• Una ventana se minimiza y después se maximiza.
• Una ventana cambia de tamaño.
• El código de la aplicación envía explícitamente el mensaje
WM.PAINT.

Dibujar algo sobre una ventana lleva implícito pintar antes el fondo:,
por ejemplo, de blanco.
Por esta causa, cuando una ventana reciba un mensaje WM.PAINT si
la función OnPaint o la función OnDraw no incluyen código que
dibuje algo, el contenido de la ventana se borrará.

Ing. Daniel Osorio Maldonado 29/11/2019 59


REPINTAR OBJETOS
Para explicar cómo puede proceder a repintar el contenido de una
ventana, vamos a realizar una aplicación Repintar que muestre paso
a paso cada una de las acciones que hay que ejecutar.
Ejecute AppWizard y construya el esqueleto para una aplicación SDI;
deje seleccionadas las opciones Docking toolbar, minal status bar y
Printing and print preview por si más adelante las necesitamos.
Personalice la caja de diálogo Acerca de. Modifique la barra de
menús de la aplicación para que incluya un menú Dibujar con las
órdenes Círculo y Texto, en lugar del menú Edzczon.
Anteriormente hemos dibujado objetos, por ejemplo un círculo,
llamando directamente a las funciones de la clase CDC.
En programación orientada a objetos lo coherente es utilizar objetos
que se pinten a sí mismos.
Por esta razón vamos a escribir una clase base denominada CFigura
de la cual se puedan derivar otras clases que representen cada una
de las figuras concretas que deseemos dibujar.
De esta forma será fácil construir una colección con los objetos
dibujados lo que facilitará enormemente el repintado de la ventana.
Ejecute ClassWizard y añada la clase CFigura derivada de
CDocument (recuerde que CDocument se deriva de CObject).

Ing. Daniel Osorio Maldonado 29/11/2019 60


Almacene la declaración de la clase en el fichero RepintarDoc.h y la
definición en RepintarDoc.cpp.
La funcionalidad de esta clase estará soportada por dos constructores, un
destructor virtual, una función miembro pública virtual AutoPintado, y por
los datos miembro protegidos colorp tipo COLORREF, anchop y estilop de
tipo int y colorb de tipo COLORREF
class Cfigura : public CDocument.
{
DECLARE_SERIAL(CFigura)
public:
//Constructores
CFigura() {}
//Cfigura(COLORREF,int,COLORREF);
//Destructor
virtual ~Cfigura();
//Funcion miembro
virtual void AutoPintado(CDC*) const{}
//Attributes
protected:
COLORREF colorp;//color pluma
int anchop; //ancho pluma
int estilop; //estilo pluma
COLORRREF colorb //color pincel
//………
};
Ing. Daniel Osorio Maldonado 29/11/2019 61
A continuación escriba en el fichero repindoc.cpp la definición de las
funciones miembros; en nuestro caso, solo del constructor con
parámetros.
CFigura::CFigura(COLORREF ColorP, int AnchoP, int EstiloR, COLORREF
ColorB)
:colorp(Colorp),anchop(AnchoP),estilo(EstiloP),color(ColorB){
}
El constructor con parámetros CFigura asigna los valores pasados como
argumentos a los datos miembro del objeto que estamos creando.
La función miembro AutoPintado será redefinida en cada una de las
clases derivadas de CFigura (una por cada fjgura que queramos
dibujar).
Como ejemplo, vamos a diseñar las clases CElipse y CTexto para poder
dibujar elipses y texto, respectivamente.
Escriba estas clases en el fichero Repindoc.h

class CElipse: public CFigura {


DECLARE_SERIAL(CElipse)
public:
// Constructor
CElipse(int =0, int =0, /* coordenadas */
int = 0, int = 0,
COLORREF = RGB(0,0,0); /* color pluma */
int = 1,
Ing. Daniel Osorio Maldonado 29/11/2019 62
int = PS_SOLID,
COLORREF=RGB(255,255,255)): /* color pincel */
virtual ~CElipse(): // Destructor
// Funciones miembro
void AutoPintado( CDC * ) const;
protected:
int x1, v1, x2. y2: // coordenadas
}:
Los datos protegidos de la clase CElipse se corresponden con las
coordenadas de la esquina superior izquierda y de la esquina inferior
derecha del rectángulo circunscrito a la elipse.
El constructor CElipse proporciona los valores por defecto para los datos
protegidos de su clase y para los de la clase base.

class CTexto :public CFigura {


DECLARE_SERIAL(CTexto)
public:
// Constructor
CTexto(int =0,int =0,int =0, //coordenadas
CString text=“”, //texto
COLORREF =RGB(0,0,0), //color de texto
COLORREF =RGB(255,255,255) //color fondo
virtual ~CElipse(); //Destructor

Ing. Daniel Osorio Maldonado 29/11/2019 63


void AutoPintado(CDC*) const; //Función miembro
protected:
int x1,y1,y2; // coordenadas
CString text; // texto
};

Los datos protegidos de la clase CTexto se corresponden con


las coordenadas donde debe comenzar el texto, y del texto.

El constructor CTexto proporciona los valores por defecto para


los datos de la clase base que afectan a esta clase de objetos.

Cada uno de los objetos será dibujado por su correspondiente


funcion de AutoPintado.

Con lo expuesto podrá escribir la definición de estas funciones,


asi como las definiciones de los constructores y destructores de
cada una de las clases, en el archivo repindoc.cpp.

Ing. Daniel Osorio Maldonado 29/11/2019 64


///////////////////////////////////////////////////////////////////////////////
/////////////////////////////

//CElipse
IMPLEMENT_SERIAL(CElipse,CFigura,0)
CElipse:: CElipse(int X1,int Y1,int X2, int Y2,
COLORREF ColorP, int anchop,int Estilop,COLORREF ColorB);
X1(X1),y1(Y1),x2(X2),y2(Y2), CFigura(ColorP,EstiloP,ColorB)
{
}
CElipse::~CElipse()
{
}

Ing. Daniel Osorio Maldonado 29/11/2019 65


void Celipse::AutoPintado(CDC* pDC) const;
{
CPen *MiPluma = new CPen(estilop anchop,
colorp);
CPen *PlumaAnterior = pDC-
>SelectObject(MiPluma);
CBrush *MiPincel = new CBrush(colorb);
CBrush *PincelAnterior = pDC-
>SelectObject(MiPincel );
pDC->Ellipse(x1, y1, x2, y2);
pDC->SelectObject(PlumaAnterior)
pDC->SelectObject(PincelAnterior)
// Eliminar los objetos GDI creados
MiPluma->DeleteObject( ):
Mi Pincel ->DeleteObject( ):
delete MiPluma:
delete MiPincel
}
Ing. Daniel /***************************************/
Osorio Maldonado 29/11/2019 66
// CTexto
IMPLEMENT_SERIAL( CTexto, CFigura, 0 //esquema
numero)
CTexto::CTexto(int X. int Y. CString Text, COLORREF ColorP,
COLORREF ColorB)
: x(X), y(Y), text(Text). CFigura(ColorP, 1, PS SOLID, ColorB)
{
}
CTexto::~CTexto( )
{
}
void CTexto::AutoPintado( CDC *PDC ) const
{
pDC->SetlextColor(colorp)
pOC->SetBkColor(colorp)
pDC->TextOut(x, y, text);
}

Ing. Daniel Osorio Maldonado 29/11/2019 67


Una vez construidas las clases, dibujar una figura consiste en construir un
objeto de la clase de figura y llamar a su función AutoPintado.
Por ejemplo, el siguiente código pinta un círculo;
CElipseCir(-100, 100, 100, -100, RGB(255.215,D), 2);
Cir.AutoPintado(&dc);
El siguiente paso es construir una colección con los objetos que vayamos
dibujando, lo que facilitará enormemente el repintado de la ventana.
Para referenciar la colección de objetos mencionada, añada a la clase
CRepintarDoc el dato miembro público m_pListaFiguras.
class CRepintarDoc : public CDocument
{
//………
//Attributes
public:
// Puntero a la colección de figuras
COblist *m_pListafiguras:
};
El dato m_pListaFiguras se ha declarado como un puntero a la clase
CObArray que permite definir una lista para almacenar punteros a
objetos de la clase CObject o de clases derivadas de CObject. Inicie el
puntero m_pListaFiguras en el constructor CRepintarDoc y cuando la
aplicación finalice libere la memoria referenciada por él en el destructor
de la clase. Para liberar la memoria ocupada por los elementos de la
lista y por los objetos referenciados por éstos, utilice la función
DeleteContents
Ing. Daniel Osorio Maldonado 29/11/2019 68
CRepintarDoc; :CRepintarDoc()
}
//Asignar memoria para una colección de objetos (lista)
m_pListaFiguras = new CObList;
}
CRepintarDoc: :-CRepintarDoc()
{
delete a m_pListaFiguras;
}
/*Utilizando WizardBar, añada la función DeleteContents a la clase
CRepintarDoc y edítela como se muestra a continuación: */
Void CRepintarDoc::DeleteContents()
{
// Liberar la memoria ocupada por los objetos de la lista
POSITION pos = a PlistaFiguras>GetHeadposition( )
while (pos !=NULL)
delete m_PListaFiguras->GetNext(Pos):
// Liberar la memoria ocupada por el obeto colección
rn_pListaFiguras->RemoveA11 ( ):
CDocument : : DeleteContents ( )
}

Ing. Daniel Osorio Maldonado 29/11/2019 69


Añada la declaración de la función DelteContents a la
declaración de la clase CRepintarDoc.
Virtual void DeleteContents();
Cuando el usuario pulse la orden Circulo del menu
Dibujar el objeto dibujado se añadirá a la lista.
Para construir un objeto de la clase Celipse tiene
que invocar al constructor de la clase y pasar como
argumentos las coordenadas de la esquina superior
izquierda y de la esquina inferior derecha del
rectangulo circunscrito a la elipse.
Observe en el constructor de la clase que el resto
de los parámetros son opcionales.
Ing. Daniel Osorio Maldonado 29/11/2019 70
Finalmente el pintado del objeto lo haremos en la función
OnDraw.
Recuerde que OnDraw es llamada automáticamente cuando
en la cola de mensajes de la aplicación se coloca un mensaje
WM_PAINT lo que puede hacer ejecutando la función
InvalidateRect

void CRepintarliew::OnDibujarCirculo()
{
// Dibujar una circunferencia de radio 100 unidades
CElipse *pCir = new CElipse(-100, 100, 100, -100, RGB(255,255,0), 2);
// Añadir el objeto a la lista
CRepintarDoc* pDoc = GetDocument ():
pDoc->mpListaFiguras->AddHead(pCir);
// Dibujar
InvalidateRect(NULL, TRUE); // indirectamente llama a OnDraw
}

Observe en la función anterior que el objeto de la clase


CELipse se ha creado dinámicamente.
Si seDaniel
Ing. crea como
Osorio un objeto local a la funcion, vea en29/11/2019
Maldonado la 71
siguiente
CElipse Cir = CElipse(-100, 100, 100, -100, RGB(255.255,0), 2);
// Añadir el objeto a la lista
CRepintarDoc* pDoc = GetDocument();
pDoc->m_pListaFiguras->AddHead(&Cir);
El objeto será borrado automáticamente al finalizar la función, con lo que
el puntero almacenado en m_pListaFigura será inválido (no apunta al
objeto).
Asimismo, cuando el usuario pulse la orden Texto del menú Dibujar, el
objeto dibujado se añadirá también a la lista.
Para construir un objeto de la clase CTexto tiene que invocar al
constructor de la clase y pasar como argumentos las coordenadas
donde quiera que comience el texto, y el texto que desea pintar.
En el constructor de la clase vea que el resto de los parámetros son
opcionales.
Usando el mismo razonamiento, el nuevo objeto se puede crear
dinámicamente.
Es decir el pintado del objeto lo haremos en la función OnDraw.

void CRepintarView::OnDibujartexto()
{
// Escribir texto
CTexto *ptex = new CTexto( -15, 0, CString(“Circulo”)):
// Añadir el objeto a la lista
CRepintarDoc* pDoc = GetDocurnent():
pDoc->m_pListaFiguras->AddHead(pTex);
// Dibujar
Ing. Daniel Osorio Maldonado
InvalidateRect(NULL, TRUE); // indirectamente llama a OnDraw 29/11/2019 72
}
La función OnDraw se encarga de pintar la colección objetos.
Para ello, primero establece el sistema de coordenadas y después recorre
la colección de objetos en el mismo orden en el que han sido creados
invocando para cada uno de ellos su función AutoPintado correpondiente
(polimorfismo).
El resultado es el repintado de todos los objetos en el mismo orden que
fueron creados.
void CRepintarView::OnDraw(CDC* pDC) {
CRepintarDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc)
// Tamaño del área de cliente
CRect rect;
GetClientRect( rect );
int cx = (rect.right - rect.left):
int cy = (rect.bottom - rect.top);
// Establecer la escala del sistema de coordenadas
pDC->SetMapMode(MM_ISOTROPIC);
// Tamaño de la ventana
pDC->SetWindowExt( 200. 200 );
// Tamaño del área de dibujo (ventana gráfica)
pDC->SetViewportExt( cx, -cy )
// Establecer el origen de coordenadas en el centro
pDC->SetViewportOrg( cx/2, cy/2 );
// Dibujar
POSITION pos = pDoc->m_pListaFiguras->GetTailPosition();
while ( pos != NULL)
((CFigura *)(PDoc->m_ListaFiguras->GetPrev(Pos))->AutoPintado (PdC);
} Ing. Daniel Osorio Maldonado 29/11/2019 73
Si fuera el caso que a la aplicación se le pidiera dibujar otras figuras diferentes y
de distintos tamaños, se hará necesario que se observe que cada vez que se añade
una nueva figura a la colección, para pintarla hay que pintar todas ella.
Cuando en realidad esto debiera ocurrir solamente cuando la ventana sea ocultada
o redimensionada.
Este problema se soluciona definiendo en la clase CRepintarView una variable
m_bRepintarTodo de tipo BOOL que indique a OnDraw si tiene que repintar todas
las figuras o solamente la ultima dibujada.
Class CRepintarView:public Cview {
//................
//Attributes
public:
CRepintarDoc* GetDocument();
BOOL m_bRepintarTodo;
//..........
};
Inicialice esta variable en el constructor de la clase CRepintarView.
El valor TRUE indicara que hay que repintar todo.
Ing. Daniel Osorio Maldonado 29/11/2019 74
Un valor FALSE indicara que hay que repintar solo la figura que acabamos de
dibujar.
CRepintarView::CRepintarView()
{ m_bRepintadoTodo=TRUE;}
De lo expuesto debe modificar la función OnDraw para que ahora interrogue a la
variable m_bRepintadoTodo y para que deje dicha variable a valor TRUEN por si se
oculta o redimensiona la ventana.
void CRepintarView::OnDraw(CDC* pDC)
{
//.......... //Dibujar
if(m_bRepintado){
POSITION pos=pDoc->m_pListaFiguras ->GetTailPosition();
while (pos !=NULL)
((CFigura*) (pDoc ->m_pListaFiguras ->GetPrev(pos))) ->Autopintado(pDC);
}
else
((CFigura *)(pDC ->m_pListaFiguras ->GetHead())) ->Autopintado(pDC);
m_bRepintadoTodo=TRUE;
Ing. Daniel Osorio Maldonado 29/11/2019 75
}
La variable m_bRepintarTodo sólo debe de valer FALSE cuando pintemos una
nueva figura.
Por consiguiente hay la necesidad de modificar las funciones que llaman a
OnDraw para pintar cada una de las figuras, como se indica a continuación:
void CRepintarView::OnDibujarCirculo() {
// ............
//Dibujar
m_bRepintarTodo=FALSE:
invalidateRect(NULL,FALSE); // indirectamente llama a OnDraw
}
void CRepintarView::OnDibujarTexto()
{
//........
//Dibujar
m_bRepintarTodo=FALSE;
InvalidateRect(NULL,FALSE); //indirectamente llama a OnDraw
}

Ing. Daniel Osorio Maldonado 29/11/2019 76


Observar en la vista anterior el valor de FALSE del segundo parámetro
de InvalidateRect.
La función InvalidateRect establece el rectángulo que hay que repintar.
Su sintaxis es:
Void InvalidateRect(LPCRECT lpRect,BOOL berase= TRUE);

El primer parámetro es un puntero a un objeto CRect que contiene las


coordenadas del rectángulo que hay que repintar.
Un valor NULL indica que se repintara todo el área de trabajo.
El segundo parámetro es un BOOL que indica si el fondo del área que
hay que repintar tiene o no que ser borrado.
Un valor TRUE (valor por defecto) indica que el fondo será borrado y un
valor FALSE indica que no será borrado, lo que significa que lo que
tengamos pintado no se borrará.

Ing. Daniel Osorio Maldonado 29/11/2019 77


DIBUJAR PUNTOS
Para dibujar un punto en la pantalla, disponemos de la función
miembro SetPixel de la clase CDC.
Esta función pone color al píxel de la posición especificada por lo
cuál no se ve afectada por el ancho de la pluma. Su sintaxis es la
siguiente:
COLORREF SetPixel( int x, int y, COLORREF crColor);
COLORREF SetPixel( POINT punto, COLORREF crColor);
Los argumentos x e y o el argumento punto indican las
coordenadas del punto y crColor especifica el color utilizado para
pintar el punto.
Como ejemplo, dibuje en una ventana las curvas correspondientes
a las funciones sin(x) y cos(x) para valores de x entre 0 y 6,3
radianes.
Paralelamente, realice el mismo grafico en una caja de imagen.
El resultado puede verlo en la figura siguiente.

Ing. Daniel Osorio Maldonado 29/11/2019 78


Para visualizar el ejercicio añada a la barra de menús un nuevo menú
Gráficos con la orden Puntos.
Abrir el editor de diálogos y cree una plantilla (IDD_DLG_PUNTOS) para una
nueva caja de diálogo titulada Gráficos.
Después, ejecute ClassWizard y cree la clase CDlgGraficos asociada con
esa plantilla de diálogo IDD_DLG_PUNTOS.
Añada la declaración de la clase al fichero RepíntarVIew.h y la definición al
fichero RepintarView.cpp.
Para pintar las curvas, añada a la clase CDlgGraficos la función miembro
OnPaint, miembro de la clase CDLgGraficos, que se ejecute en respuesta al
mensaje WM_PAINT que se produce cada vez que se pinta la ventana, la
función debe:
Crear un sistema de coordenadas para valores de x entre 0 y 6,3 y para
valores de y entre -1 y 1 (tamaño de la ventana lógica expresado en
centésimas: 630 x 200), de forma que los valores positivos queden por
encima del eje x, lo que implica dar un valor negativo al parámetro cv de
SetViewportExt.
Dibujar las curvas punto a punto, el siguiente es el procedimiento:
void CDlgGraficcs::OnPaint()
{
// Contexto de dispositivo para pintar
CPaintDC ac (this):
// Tamaño del área de trabajo
CRect rect;
GetClientRect( rect) ;
int cx = (rect.right - rect.left);
inc cy = (rect.bottom - rect.top);
Ing. Daniel Osorio Maldonado 29/11/2019 79
// Establecer la escala del sistema de coordenadas
dc. SetMapMode( MM_ANISOTROPIC):
// Tamaño ae la ventana lóqica mx=6 .3*100, 7=2*100)
dc.SetWindowExt;( 630, 200):
// Tamaño de la superficie de proyección
dc. SetViewpor:Ext( cx, -cy)
// Establecer el origen lógico de coordenadas
dc.Set.ViewportOrg( 0, cy/2 ):
//Dibujar curvas
int x. ycos. ysen;
for ( x = 0; x <= 630; x += 5)
{
ycos = (int)(cos((double)x/100)*100,
ysen = (int)(sin((double)x/100)*100)
dc.SetPixel(x ycos, RGB(0,0,0)); //coseno
dc.SetPixel (x. ysen, RGB(255, 255, 255)) //seno
}
}
La función OnPaint será invocada cuando el usuario haga clic en la orden
Puntos del menú Gráficos .
Visualizando la ventana de diálogo Gráficos. para ello, ejecute ClassWizard y
añada a la clase CRepintarView la siguiente función:
void CRepintarView:;onGraficospuntos()
{
CDlgGraficos Dlg; // llama al constructor CD1gGraficos
Dlg.DoModal ();}
Ing. Daniel Osorio Maldonado 29/11/2019 80
Agregando una opcion al
submenu Grafico llamado
Grafica_Fun1

Agregar el
recurso Dialogo

Clic en New
Cambiando de Nombre el
IDD y el Caption del Recurso
Dialogo
Creando la Clase Funcion1

Aquí la clase con el Nombre de


CFuncion1Dlg
Ubicarse en luego doble clic aparece en ella debe
agregar el archivo de cabecera Funcion1Dlg.h
Aprecie la función
Funcion1Dlg.h agregada
al File View/Source Files
Ubicarse en el Menú
y en la opción
Grafica_Fun1, con la
idea de hacer el Link
con la Clase creada
Funcion1Dlg
Editando el Codigo y llamando al
DoModal()
Haciendo clic boton derecho en la
clase creada, vamos al ClassWizard
En el Mensaje buscamos
WM_Paint, adicionamos la
Función y luego Ok

Editamos la Función
Aquí queda expedito para realizar otra aplicación
DIBUJAR LÍNEAS
La clase CDC de la biblioteca MFC proporciona varias funciones para
dibujar líneas rectas y curvas
Líneas rectas:
BOOL LineTo( int x, int y);
BOOL LineTo( POINT punto);
Line To pinta una línea desde la posición actual de la pluma hasta el punto
lógico especificado por los argumentos x e y, o por el argumento punto.
Por defecto, la posición inicial de la pluma es el punto lógico (0,0).
Puede establecer otro punto utilizando la función MoveTo. MoveTo y LineTo
son las únicas funciones que modifican la posición actual de la pluma.
Esta posición puede obtenerse por medio de la función
CDC::GetCurrentposition
CPoint GetCurrentposition() const;
Líneas curvas:
BOOL Arc( int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4);
BOOL Arc( LPCRECT lpRect, POINT ptInicio, POINT ptFin;
Arc pinta una línea que se corresponde con un arco delimitado por los
radios que pasan por los puntos (x3, y3) - (x4, y4), perteneciente a la
elipse circunscrita en el rectángulo definido por la esquina superior
izquierda (x1,y1]) y por la esquina inferior derecha (x2, y2).
En el segundo formato de Arc el principio y el final de la línea vienen dados
por los puntos ptInicio y ptFin, y el rectángulo por un objeto CRect o RECT
referenciado lpRect.
El arco
Ing. se pinta
Daniel enMaldonado
Osorio sentido contrario a las agujas del reloj. 29/11/2019 91
Líneas quebradas:
BOOL Polyline( LPPOINT lpPuntos, int nPuntos);
Polyline permite pintar una serie de líneas unidas entre sí.
El argumento lpPuntos representa un array con los puntos que se quieren
conectar y el argumento nPuntos indica el número de puntos
almacenados en el array.
Añada a un menu Graficos el submenu Lineas con las ordenes
Rectas, Curvas y Quebradas.
A continuación utilizando ClassWizard vincule a cada una de estas
ordenes las funciones
OnGraficosLineasRectas,OngraficosLineasCurvas y
OngraficosLineasQuebradas, respectivamente.
Cada una de estas funciones invocara a la función
CDldGraficos::OnPaint para pintar el grafico deseado.
Para saber que orden es la que se ha invocado a OnPaint añada a la
CRepintarView el dato miembro m_uIOrdenMenuGraficos para que
contenga el ID de la orden ejecutada.
Class CRepintarView : public Cview {
//..................
//Atributes
public:
CRepintarDoc* GetDocument();
BOOL m_bRepintarTodo;
UINT m_uIdOrdenMenuGraficos;
// ...........
} Ing. Daniel Osorio Maldonado 29/11/2019 92
Para que la función OnPaint pueda acceder a m_uIdOrdenMenuGraficos
necesita conocer un puntero a la vista.
Para ello añada a la clase CDlgGraficos el dato miembro pView para que
almacene un puntero a la vista.
Class CDlgGraficos: public Cdialog
{
private:
//Puntero a la vista
CrepintarView *pView;
//........
}

Cada vez que crea un objeto de la clase CDlgGraficos para visualizar una
caja de dialogo con el fin de mostrar un grafico, pase como argumento al
constructor de la clase, el puntero a la vista.
Vea la función OnGraficosPuntos

Ing. Daniel Osorio Maldonado 29/11/2019 93


void CRepintarView::OnGraficosPuntos()
{
m_uIdOrdenMenuGraficos=ID_GRAFICOS_PUNTOS;
CDlgGraficos Dlg(This); //llama al constructor CDlgGraficos
Dlg.DoModal();
}

Asigne al dato miembro pView en el constructor CDlGraficos, el valor


pParent pasado como argumento(referencia ala ventana padre de la caja de
dialogo).
CDlgGraficos::CDlgGraficos(CWnd* pParent // NULL):CDialog(CDlgGraficos::
IDD,pParent)
{
pView=(CRepintarView*)pParent;
}

De lo expuesto modifique entonces la función CDlgGraficos::OnPaint ,


tal como se aprecia en la siguiente vista.
Ing. Daniel Osorio Maldonado 29/11/2019 94
void CDGraficos::OnPaint() {
//Contexto de dispositivo para pintar
CPaintDC dc(this);
//Tamaño del área de Trabajo
CRect rect;
GetClientRect(rect);
int cx=(rect.rigth – rect.left);
int cy =(rect.botton – rect.top);
//Establecer la escala del sistema de cooredenadas dc.MapMode(MM_ANISOTROPIC);
//Dibujar
int x,y;
swicht(pView->m_uIdOrdenMenuGraficos) {
Case ID_GRAFICOS_PUNTOS:
//Tamaño de la ventana(x=6.3*100,y=2*100)
dc.SetWindowExt(630,200);
//Tamaño del área de Dibujo(Ventana Grafica)
dc.SetViewportExt(cx,-cy);
Ing. Daniel Osorio Maldonado 29/11/2019 95
//Establecer el origen de coordenadas
dc.SetViewPortOrg(0,cy/2);
int ycos,ysen;
for(x=0,x<=630;x+=5) {
ycos=(int)(cos((double)x/100)*100);
ysen=(int)(sin ((double)x/100*100);//coseno
dc.SetPixel(x,ycos,RGB(0,0,0);//seno }
break;
Case ID_GRAFICOS_LINEAS_RECTAS;
//……….
Break;
Case ID_GRAFICOS_LINEAS_CURVAS;
//………..
break<;
Case ID_GRAFICOS_LINEAS_QUEBRADAS
//………
break;
}
///……..
}
Ing. Daniel Osorio Maldonado 29/11/2019 96
Al hacer clic en la orden Rectas(ID_GRAFICOS_LINEAS_RECTAS) del
menu Gráficos, queremos que se pinte en el Área de trabajo de la ventana una
rejilla que tenga entre líneas 50 unidades lógicas, empezando por la esquina
inferior izquierda (punto lógico(0,0)).
El código siguiente pinta la rejilla con las características especificadas.
Void CRepintarView::OnGraficosLineasRectas(){
m_uIdOrdenMenuGraficos=ID_GRAFICOS_LINEAS_RECTAS;
CDlgGraficos Dlg(this);
Dlg.DoModal(); }
Void CDlgGraficos::OnPaint()
{
// ........
swicht(pView->m_uIdOrdenMenuGraficos)
{
case ID_GRAFICOS_PUNTOS:
//………
break;

Ing. Daniel Osorio Maldonado 29/11/2019 97


case ID_GRAFICOS_LINEAS_RECTAS:
//Tamaño de la ventana
dc.SetWindowExt(600,400);
//Tamaño del Área de Dibujo (Ventana Grafica)
dc.SetViewportExt(cx,-cy);
//Establecer el origen de coordenadas
dc.SetViewportOrg(0,cy);//(0,0)=esquina inf.izq
dc.DPtopLP(&rect);
for(x=0;x<rect.rigth

Ing. Daniel Osorio Maldonado 29/11/2019 98


Modos de dibujo
Para cambiar el estilo, el ancho y el color de las líneas que dibuje, puede
definir una pluma personalizada como vimos en el apartado “Objetos
GDI”pero, piense cómo puede afectar lo que dibuja, si lo hace encima de
un gráfico
existente.
La función SetROP2 permite elegir entre 16 modos de dibujo dados por sus
respectivos códigos ROP.
Los modos más utilizados son los siguientes:
Modo de dibujo Significado
R2NOTCOPYPEN El píxel es el inverso al de la pluma.
R2_NOT El píxel es el inverso al de la pantalla. Este
modo es útil siempre que no se conozca el
color de fondo.
R2XORPEN El píxel es el resultado de la operación XQR
entre la pluma y la pantalla.
R2NOTXORPEN Esta operación es la inversa de XQR.
R2NOp No dibuja; la salida permanece igual.
R2COPYPEN El píxei es el mismo de la pluma. Es el valor
que se toma por omisión.

Ing. Daniel Osorio Maldonado 29/11/2019 99


Una vez establecido uno de los dieciséis modos posibles, Windows
aplicará la operacion ROP sobre cada píxel del patrón utilizado y
su correspondiente píxel del fondo, cada vez que se ejecute una
función gráfica. Por ejemplo, con XQR;
Pluma dibujando un píxel Destino. Un pixel Píxel resultante
del patrón utilizado existente en la pantalla en la pantalla
1111 XOR 0011 = 1100

COLOREAR FIGURAS
Una figura puede ser rellenada utilizando un pincel de un color
sólido o un pincel según Un determinado patrón. Para crear un
pincel de un color sólido, vimos en el capítulo 6 la función
CreateSolidBrush En cambio, para crear un pincel que rellene
según un determinado patrón, utilizaremos la función miembro
CreateHatchBrush de la clase CBrush:
BOOL CreateHatchBrush( int nEstilo, COLORREF crColor );
Los valores posibles para nEstilo se indican en la tabla siguiente. El
parámetro crColor es el color de las líneas que forman el patrón.

Ing. Daniel Osorio Maldonado 29/11/2019 100


ESTILO SIGNIFICADO
HS_HORIZONTAL Líneas horizontales
HS:VERTICAL Líneas verticales
HS_BDIAGINAL Diagonales ascendentes
HS_FDIAGONAL Diagonales descendentes
HS_CROSS Líneas verticales y horizontales cruzadas
HS_DIACGROSS Diagonales cruzadas
ESTILOS DE LA PLUMA
Cualquier pluma de ancho mayor de un píxel, independientemente de su estilo,
centra su traza sobre el contorno que se desea dibujar, excepto para el estilo
PS_INSIDEFRAME; en este caso, la traza se dibuja totalmente dentro del
contorno. Por ejemplo, la siguiente figura dibuja tres cuadrados de lado iüo
unidades lógicas. El primer cuadrado esta dibujado con una pluma de ancho 20
y-estilo PS_JNSIDEFRAME; el segundo está dibujado con una pluma de ancho
1 y estilo PS_SOLJD; y el tercero con una pluma de ancho 20 y también de
estilo
PSSOLID. Observe que la traza de la pluma en el primer cuadrado está dentro
del contorno (el contorno lo muestra la segunda figura) y que en el cuadrado ter-
cero está centrada sobre el contorno. Para ver todos los estilos de plÚmas vea
en la ayuda, el constructor CPen.
Ing. Daniel Osorio Maldonado 29/11/2019 101
DIBUJAR FIGURAS

La clase CDC de la biblioteca MIFC proporciona funciones para dibujar


contornos de figuras rellenas de color que podemos clasificar así:
Rectángulos:
BOOL Rectangle (int xl, int y), int x2, int y2);
BOOL Rectangle( LPCRECT lpRect);
Rectangle pinta un rectángulo utilizando la pluma actual. El interior del
rectángulo es coloreado utilizando el pincel actual. Los argumentos
(x1, y1) y (x2. y2) se corresponden, respectivamente, con las
coordenadas lógicas de las esquinas superior izquierda e inferior
derecha del rectángulo.
BOOL RoundRect ( int x1, int y1, int x2, int y2, int x3, int y3);
BOOL RoundRect (LPCRECT lpRect, POINT punto);
RoundRect pinta un rectángulo con las esquinas redondeadas utilizando
la pluma actual. El interior del rectángulo es coloreado utilizando el
pincel actual. Los argumentos (xl, y1) y (x2, y2) se corresponden,
respectivamente, con las coordenadas lógicas de las esquinas
superior izquierda e inferior derecha del rectángulo. Los argumentos
x3 e y3 se corresponden, respectivamente, con las medidas (en
unidades lógicas) de los diámetros X e Y de la elipse utilizada para
redondear las esquinas.

Ing. Daniel Osorio Maldonado 29/11/2019 102


Elipses:
BOOL Elipse (int xl, int y1, int x2, int y2);
BOOL Ellipse( LPCRECT lpRect);
Ellipse pinta una elipse utilizando la pluma actual. El interior de la elipse es
coloreado utilizando el pincel actual. Los argumentos (x1, y1) y (x2, y2) se
corresponden, respectivamente, con las coordenadas lógicas de las
esquinas superior izquierda e inferior derecha del rectángulo, que
circunscribe a la elipse.
Polígonos:
BOOL Polygon( LPPOINT lpPuntos, int nP untos);
Polygon pinta un polígono de dos o más vértices utilizando la pluma actual.
El interior del polígono es coloreado utilizando el pincel actual. El argumento
lpPuntos apunta a un array de objetos CPoint o de estructuras POINT
correspondientes a los vértices del polígono (para cerrar el polígono no es
necesario llegar de nuevo al punto de partida como ocurnía con
Polyline), y nPuntoS indica el número de vértices del polígono.
BOOL PolyPolygofl( LPPOLNT lpPuntos, LPINT lpPuntosPoli, INIT Poligonos);
PolyPolygon pinta dos o más polígonos de dos o más vértices cada uno utili-
zando la pluma actual. El interior de cada polígono es coloreado
utilizando el pincel actual. El argumento lpPuntos apunta a un array de
objetos CPoint o de estructuras POINT correspondientes a los puntos de los
polígonos, lpPuntosPOli apunta a un array de enteros, cada uno de los
cuales especifica el núm~JXLde puntos de cada polígono y nPoligonos.

Ing. Daniel Osorio Maldonado 29/11/2019 103


REGIONES
Una región es un objeto GDI que describe un área de la pantalla.
Se forma combinando rectángulos, elipses y polígonos.
Una región seleccionada para un contexto de dispositivo, se puede utilizar
para dibujar o para recortar.
Utilizándola para recortar, restringe el dibujo a una parte específica del área
de cliente.
Las regiones pueden ser creadas utilizando las funciones miembro de la clase
CRgn.
El tipo más simple de región describe un rectángulo y la función para crearla
puede ser alguna de las siguientes:
BOOL createRectRgn( int x1, int y1, int x2, int y2);
BOOL createReçtRgnIndirect( LPCRECT lpRect);
BOOL CreateRoundRgnIndirect( int x1, int y1, int x2, int y2, int x3, int y3);

También es posible crear regiones elípticas:


BOOL CreateEllipticRgn( int x1, int y1, int x2, int y1);
BOOL CreateEllipticRgnIndirect( LPCRECT lpRect);

También se pueden crear regiones poligonales:


BOOL CreatePolygonRgn( LPPOINT lpPuntos, int nPuntos,int nModoRelleno);
BOOL CreatePolyPolygonRgn( LPPOINT lpPuntos, LPINT lpPuntosPoli,
int nPoligonos, int nModoRelleno);

Ing. Daniel Osorio Maldonado 29/11/2019 104


Las regiones se expresan siempre en coordenadas de dispositivo.
Las regiones vistas desde las MFC son objetos GDI que se pueden
alterar con las funciones miembro CombineRgfl y OffsetRgn.

int OffsetRgn(int x,int y);


int OffsetRgn( POINT punto);
La función OffsetRgn desplaza la región almacenada en el objeto
CRgn, x unidades sobre el eje X e y unidades sobre el eje Y.

int CombineRgn( CRgn* pRgn1, CRgn* pRgn2, int nModoCombinar);


La función CombineRgn crea una nueva región combinando dos
regiones existentes. El parámetro nModo Combinar indica cómo se
combinan las dos regiones:

ModoCombinar La nueva región es:


RGN_AND Intersección de las dos regiones
RGN_COPY Copia la región 2 en la región 1
RGN_DJFF Toda la región 1 que no está en la región 2
RGN_OR Unión de las dos regiones
RGN XOR Unión menos intersección de las dos regiones
Ing. Daniel Osorio Maldonado 29/11/2019 105
El valor devuelto por la función CombineRgn especifica el tipo de región
resultante.
Este valor puede ser uno de los siguientes:
Valor devuelto La nueva región:
COMPLEXREGION Tiene bordes solapados (se trata de una combinación
de rectángulos, elipses o polígonos)
ERROR No se creó NULLREGION Está vacía
NULREGION VACIA
SIMPLEREGION No tiene bordes solapados (se trata de un rectángulo,
elipse o polígono simple)
Para recuperar las coordenadas del rectángulo que contiene la región
almacenada en el objeto CRgn, utilice la función:
int GetRgnBox( LPRECT lpRect) const;
Para saber si un punto dado perténece a la región almacenada en un
objeto
CRgn, utilice la función:
BOOL PtlnRegion( int x, int y) const;
BOOL PtlnRegion( POINT punto) const;
Para saber si cualquier parte de un rectángulo dado pertenece a la
región almacenada en un objeto CRgn. utilice la función:
BOOL RectlnRegion( LPCRECT lpRect) const;
Una vez que la región ha sido creada, se pueden utilizar las siguientes
funciones de la clase CDC con los propósitos que se enuncian a
continuación: FillRgn
Ing. Daniel Osorio Maldonado 29/11/2019 106

Potrebbero piacerti anche