Código fuente de la página de propiedades de Vc
El control de gráfico se refiere a mschart.ocx (versión 5.0) o mschrt 20. ocx (¿versión 6.0? ¿Es visual?). Un control ActiveX que viene con Studio tiene muchas propiedades y eventos y es muy poderoso. Se pueden realizar gráficos de barras, gráficos de tendencias de curvas, gráficos circulares, etc. , incluso puede ser un gráfico híbrido, puede ser bidimensional o tridimensional, con o sin sistema de coordenadas, y el color y fuente de cada elemento se pueden configurar libremente. ?
¿Uno? Instalación y uso del control de gráfico
Instale el control de gráfico en el proyecto que lo utiliza: ¿Desde Proyecto -> Suplemento? ¿A dónde ir? Proyecto -> Componente? Entonces qué. Control->¿Registrado? ¿iniciativa? Xcontrols, seleccione el control de gráfico, ¿entonces? ClassWizard generará la clase C++ correspondiente, donde CMSChart se deriva de CWnd, ¿cuál es Chart? La clase principal del control, otras clases se derivan de COleDispatchDriver, controlan los objetos correspondientes en el control y completan las funciones relacionadas de cada parte. Por ejemplo, la clase CvcAxis es el código fuente que implementa funciones relacionadas con los ejes de coordenadas. Al mismo tiempo, aparecerá un botón que representa el control del gráfico en la caja de herramientas de control del proyecto. Para usarlo, arrastre el botón de control del gráfico desde la caja de herramientas al cuadro de diálogo y cambie su tamaño. ?
El control de gráfico tiene al menos 45 propiedades, 9 métodos y 49 eventos, que no se enumeran aquí. ?
En diseño, podemos modificar el valor de propiedad de cada propiedad en la página de propiedades principal: haga clic derecho en el control del gráfico en la ventana de diálogo, seleccione el elemento del menú "Propiedades" y el cuadro de diálogo de la página de propiedades principal Aparecerá un cuadro emergente para establecer los valores de propiedad. Algunas propiedades no aparecen en la página de propiedades principal y solo se pueden modificar mediante programación. Además, para dibujar gráficos dinámicamente, debes dominar el control de programación de controles. ?
Primero, defina las variables de control en la clase de diálogo para que pueda manipular los controles mediante programación. Por ejemplo, la clase de diálogo se define de la siguiente manera: ¿clase? ¿CAbcDlg? :?¿público? Diálogo {
Público:
CAbcDlg(CWnd*?Obviamente?=?NULL);
//{{AFX_DATA(CAbcDlg)
enum? {?Marcado directo internacional? =?IDD_ABC_DIALOG? };
CMSChartm _ Chart
//}}AFX_DATA
...
};
Las propiedades y métodos de los controles ActiveX corresponden a valores de índice entero únicos dentro del control. Al programar, puede establecer u obtener el valor de propiedad del control a través del índice, o puede establecer u obtener el valor de propiedad del control y llamar al método del control llamando a la función miembro de la clase C++ del control ( en este caso, CMSChart).
Por ejemplo:?
En la implementación de la clase CMSChart, existe el siguiente código:? ¿CString? CMSChart::GetData(){
CString? Resultado;
InvokeHelper(0x9, DISPATCH_PROPERTYGET,
Vermont BSTR?(void*)&result, ?NULL);
¿Regresión? Resultado;
}
¿No válido? CMSChart::SetData(LPCTSTR?lpszNewValue){
¿Electricidad estática? ¿byte? parmetros[]? = VTS _ BSTR;
InvokeHelper(0x9, DISPATCH_PROPERTYPUT
?VT_EMPTY,?NULL,?parms,lpszNewValue);
}
¿Anulado? CMSChart::Refresh(){
InvokeHelper(DISPID_REFRESH,?
DISPATCH_method,?VT_EMPTY,?NULL,?NULL);
}
p>Este código muestra que el valor de índice del atributo "Datos" es 0x9. Podemos llamar a la función SetData para establecer el valor de un determinado punto en el gráfico. ¿Método con valor de índice DISPID_REFRESH? "Actualizar", llámalo actualizar. Por ejemplo:? ¿CString? str = " 34,5
m_chart.SetData(str);
m_chart.
Refresh();
...
Al leer la implementación de la clase CMSChart, encontrará que los valores de algunos atributos no son tipos de datos ordinarios, como BOOL y CString, pero otros ¿Una variable de clase de una clase controlada por control, como? CVcTrama? CMSChart::GetPlot(){
LPDISPATCH? pDispatch
InvokeHelper(0x28, DISPATCH_PROPERTYGET,
VT_DISPATCH,?(void*)&pDispatch,?NULL);
¿Regresar? CVcPlot(pDispatch);
}
En la implementación de la clase CVcPlot, existe el siguiente código:? ¿Eje CVc? CVcPlot::GetAxis
(dragon?axisID,?const?variant&?index){
LPDISPATCH? pDispatch
¿Electricidad estática? ¿byte? parmetros[]? =VTS_I4? VTS _ VARIANT
InvokeHelper(0x1f,?DISPATCH_PROPERTYGET,
VT_DISPATCH,?(void*)&pDispatch,?Palmas?axisID,?&Index);
Regresar ? CVcAxis(pDispatch);
}
La implementación de la clase CVcAxis tiene el siguiente código:? ¿Escala de valor CVc? CVcAxis::GetValueScale(){
LPDISPATCH? pDispatch
InvokeHelper(0x9, DISPATCH_PROPERTYGET,
VT_DISPATCH,?(void*)&pDispatch,?NULL);
¿Regresar? CVcValueScale(pDispatch);
}
Y la implementación de la clase CVcValueScale tiene el siguiente código:? ¿Vacío? CVcValueScale::establecer máximo(¿doble? nuevo valor){
¿Electricidad estática? ¿byte? parmetros[]? = VTS_R8;
InvokeHelper(0x3, DISPATCH_PROPERTYPUT
VT_EMPTY,? NULL,? parms, nuevo valor);
}
Esto es la flexibilidad del control del gráfico. Según el código anterior, realice la siguiente llamada:? ¿variante? var
m _chart. ObtenerPlot(). ObtenerEje(1,?var). GetValueScale()
. SetMaximum(50.0);
La escala máxima de la ordenada se puede establecer en 50.0.
Si necesita manejar eventos desencadenados por controles, como Click, MouseDown, etc., puede definir las funciones de procesamiento correspondientes en la clase de diálogo a través de ClassWizard para implementar funciones de procesamiento relacionadas. ?
¿Dos? Ejemplo de dibujo de gráfico dinámico
En un sistema de recopilación de temperatura, esperamos mostrar los valores de temperatura recopilados en tiempo real y dibujar curvas utilizando controles de gráfico.
Cada elemento de temperatura está representado por una curva de un color diferente;
La abscisa es el tiempo y la ordenada es el valor de la temperatura, ambos deben desplazarse;
Actualiza la pantalla después de cada muestra. ?
¿Ideas de diseño?
A medida que pasa el tiempo, se recopilan más y más datos, que pueden no mostrarse en una pantalla, por lo que el sistema abre una base de datos en tiempo real para almacenar los datos recopilados en tiempo real. Cuando se muestra, los datos del período de tiempo requerido se leen de la base de datos. ?
Al editar recursos de diálogo, agregue barras de desplazamiento horizontales y barras de desplazamiento verticales para coordinar con el control del gráfico para la visualización de desplazamiento.
?
Inicia el cronómetro del diálogo, toma muestras en el intervalo de muestreo y actualiza la visualización en pantalla. ? Los principales códigos relevantes son los siguientes:? ¿Booleano? CAbcDlg::OnInitDialog(){
CDialog::OnInitDialog();
pDataDB? =?¿Nuevo? dbase
//Biblioteca de registro de datos en tiempo real. La clase base de dbase es CDaoRecordset.
pDataDB->Open(dbOpenDynaset, ? "Seleccionar
*? ¿De dónde? datos");
¿Variante? var
m _chart. ObtenerPlot(). ObtenerEje(1,var). ObtenerEscalaValor().
SetAuto(FALSE); //No marcar automáticamente la escala del eje Y.
m_chart. ObtenerPlot(). ObtenerEje(1,?var). ObtenerEscalaValor().
SetMaximum(37); //Escala máxima del eje y
m_chart. ObtenerPlot(). ObtenerEje(1,?var). ObtenerEscalaValor().
set mínimo(32); //Escala mínima del eje Y
m_chart. ObtenerPlot(). ObtenerEje(1,var). ObtenerEscalaValor().
setmajordisdivision(5); //La escala del eje y se divide en 5 partes iguales
m_chart. ObtenerPlot(). ObtenerEje(1,var). ObtenerEscalaValor().
SetMinorDivision(1); //Una marca para cada escala.
m_chart. EstablecerColumnaCount(3);? //3 elementos de temperatura, 3 curvas
m _chart. ObtenerPlot(). ObtenerColecciónSeries(). Obtener artículo (1).
GetPen(). ObtenerVtColor(). set(0,?0,?255);//Color de línea
m_chart. ObtenerPlot(). ObtenerColecciónSeries(). Obtener artículo (2).
GetPen(). ObtenerVtColor(). set(255,?0,?0);
m_chart. ObtenerPlot(). ObtenerColecciónSeries(). Obtener artículo (3).
GetPen(). ObtenerVtColor(). set(0,?255,?0);
m_chart. ObtenerPlot(). ObtenerColecciónSeries().
ObtenerArtículo(1). ObtenerPen(). SetWidth(2); //Ancho de línea
m_chart. ObtenerPlot(). ObtenerColecciónSeries().
ObtenerArtículo(2). ObtenerPen(). SetWidth(2);
m_chart. ObtenerPlot(). ObtenerColecciónSeries().
ObtenerArtículo(3). ObtenerPen(). SetWidth(2);
m_chart. EstablecerRowCount(10);? //Muestra 10 momentos de muestreo en una pantalla.
m_chart. ObtenerPlot(). ObtenerEje(0,var). Obtener escala de categoría().
SetAuto(FALSE); //No marcar automáticamente la escala del eje X.
m_chart. ObtenerPlot(). ObtenerEje(0,var). Obtener escala de categoría().
SetDivisionsPerLabel(1); //Una etiqueta a la vez
m_chart. ObtenerPlot(). ObtenerEje(0,var). Obtener escala de categoría().
SetDivisionsPerTick(1); //Un tick a la vez.
? m_ScrLeft. SetScrollRange(0, 45);
? //Rango desplazable de la barra de desplazamiento vertical (rango de valores de temperatura 0-50,
? Cada vez que el desplazamiento es de 1 grado, la pantalla muestra 5 grados)
m_ScrLeft. SetScrollPos(45-32); //La posición actual de la barra de desplazamiento vertical
m_ScrBottom. SetScrollRange(0, 0); //Rango desplazable de la barra de desplazamiento horizontal
m_ScrBottom. SetScrollPos(0); //La posición actual de la barra de desplazamiento horizontal
SetTimer(23, 300000,?NULL); //Inicia el temporizador con un intervalo de tiempo de 5 minutos.
Sample(); //Llama a la función de muestreo para realizar el primer muestreo y registrar los datos en el almacén.
? ¿devolver? realidad;?
}
¿Anulado? CAbcDlg::OnTimer(UINT?nIDEvent)? {
Sample(); //Muestreo y registro de datos en el almacén.
¿Y si? (pDataDB->GetRecordCount()>10)
theApp.nBottomRange? =?pDataDB->GetRecordCount()-10;
Otro
theApp.nBottomRange? =?0;?
//Utilice variables globales para guardar el valor del rango de la barra de desplazamiento horizontal.
m_ScrBottom. SetScrollRange(0, theapp.nbottomrange);
theApp.nBottomPos? =?theApp.nBottomRange
m_ScrBottom. SetScrollPos(theapp . nbottompos);
//Modifica la visualización de la barra de desplazamiento horizontal.
draw pic(); //Llama a la función para actualizar la visualización de la curva.
CDialog::on timer(nIDEvent);
}
¿No es válido? CAbcDlg::DrawPic()? {
¿Ciel? s[10];
¿UINT? ¿Plan? =?1;
pDataDB-& gt;MoveFirst();
pDataDB->move(theapp . nbottompos);
//Solo de Take extraer los datos de un determinado período de tiempo de la base de datos y mostrarlos.
¿Cuándo? ((!pDataDB->IsEOF())?&&?(Rango?<=?10)){
m_chart. SetRow(fila);
m_chart. SetRowLabel((LPCTSTR)pDataDB
->mDateTime.Format(" % H:% M ");
//Etiqueta el eje X con el tiempo de muestreo. p>
m_chart.set columna(1);
sprintf(s,? "%6.2f", pDataDB->m_no 1);
m_chart.SetData( (LPCSTR)s);
m_chart.
set column(2);
sprintf(s,? "%6.2f", pDataDB->m_No2);
m_chart. SetData((LPCSTR)s);
m_chart. set column(3);
sprintf(s,? "%6.2f", pDataDB->m_No3);
m_chart. SetData((LPCSTR)s);
pDataDB-& gt; MoveNext();
row++;
}
¿Cuándo? ((¿Rango?& lt=?10)){
m _chart. SetRow(fila);
m_chart. setrow label((LPCTSTR)" ");
m_chart. ObtenerDataGrid(). SetData(row, 1,?0,?1);
//Los datos de muestreo son inferiores a 10 puntos. La ubicación correspondiente no se mostrará.
m_chart. ObtenerDataGrid(). SetData(fila, 2,?0,?1);
m_chart. ObtenerDataGrid(). SetData(fila, 3,?0,?1);
fila++;
}
m_chart. Actualizar();
}
¿No es válido? CAbcDlg::on scroll(UINT?nSBCode,?
UINT?NPO,?CScrollBar*?pScrollBar)? {
¿Y si? (pDataDB->GetRecordCount()>10)
theApp.nBottomRange? =?pDataDB->GetRecordCount()-10;
Otro
theApp.nBottomRange? =?0;
m_ScrBottom. SetScrollRange(0, theapp . nbottomrange);
¿Cambiar? (nSBCode){
¿Caso? SB_LINERIGHT:
¿Y si? (theApp.nBottomPos?<?theApp.nBottomRange){
theApp.nBottomPos? =?theApp.nBottomPos? +?1;
m_ScrBottom. SetScrollPos(theapp . nbottompos);
dibujar imagen();
}
Romper
¿Caso? SB_LINELEFT:
¿Y si? (theApp.nBottomPos?& gt?0){
theApp.nBottomPos? =?theApp.nBottomPos? -?1;
m_ScrBottom.
SetScrollPos(theapp . nbottompos);
dibujar imagen();
}
Romper
}
CDialog::on scroll(código nsb,? NPO,? pScrollBar);
}
¿No es válido? CAbcDlg::OnVScroll(UINT?nSBCode,?
UINT?NPO,?CScrollBar*?pScrollBar)? {
¿Variante? var
¿Doble? max1, min1, f;
¿Cambiar? (nSBCode){
¿Caso? SB_LINEDOWN:
¿f? =?m_chart. ObtenerPlot(). ObtenerEje(1,?var).
GetValueScale(). ObtenerMínimo()? -?1;
¿Y si? (f & gt=0)?{//La escala mínima es mayor o igual a 0,? Puedes desplazarte.
m_chart. ObtenerPlot(). ObtenerEje(1,?var). ObtenerEscalaValor().
establecer mínimo(f);
f? =?m_chart. ObtenerPlot(). Getax
(1,?var). ObtenerEscalaValor(). ObtenerMáximo()? -?1;
m _chart. ObtenerPlot(). ObtenerEje(1,?var). ObtenerEscalaValor().
SetMaximum(f);
pScrollBar->SetScrollPos(pScrollBar->GetScrollPos()?+?1);
m _chart . Actualizar();
}
Romper;
¿Caso? SB _Alineación:
f? =?m_chart. ObtenerPlot(). ObtenerEje(1,?var).
GetValueScale(). ObtenerMáximo()? +?1;
¿Y si? (f?<=?50)?{//La escala máxima es menor o igual a 50,? Puedes desplazarte.
m_chart. ObtenerPlot(). Getax
(1,?var). ObtenerEscalaValor(). EstablecerMáximo(f);
f? =?m_chart. ObtenerPlot(). ObtenerEje(1,?var).
GetValueScale(). ObtenerMínimo()? +?1;
m_chart. ObtenerPlot(). ObtenerEje(1,?var). ObtenerEscalaValor().
establecer mínimo(f);
pScrollBar->SetScrollPos(pScrollBar->GetScrollPos()?-?1);
m _ gráfico. Refresh();
}
Romper;
}
CDialog::on scroll(código nsb,? NPO,? pScrollBar );
}
Preste especial atención a las clases de control utilizadas en el programa, como CVcAxis, que deben indicarse al principio del archivo AbcDlg.cpp: # # ¿incluir? "VcAxis.h".?
Limitado por espacio, este artículo es sólo una parte del código para un ejemplo sencillo. En aplicaciones prácticas, generalmente existen más requisitos, como: escalar y mostrar los ejes de coordenadas es posible que no se obtengan valores de muestreo correctos durante el muestreo, la visualización de la curva puede ser discontinua, etc. En este momento, debe escribir el código correspondiente según los requisitos.