// ------------------------------------------------------------------------ // T O P O F F I L E // ------------------------------------------------------------------------ // // Filename - hlmeter.cpp // // Description - Horizontal Linear Meter using ChartDirector // // Author - Steve Valliere // // Create Date - May 15, 2018 // // Revision History -- (QVCS Keywords) ------------------------------------ // // $Date: Thursday, May 17, 2018 11:50:10 AM $ // // $Revision: 1.1 $ // // $Log: Q:\Source\RMCS\EV11\hlmeter.dqq $ // // Added new linear meter objects // // Revision 1.1 by: seven Rev date: 5/17/2018 1:31:28 PM // work-in-progress checkpoint (program compiles & runs) // // Revision 1.0 by: seven Rev date: 5/16/2018 1:56:03 PM // Initial Revision // // $Endlog$ // // ------------------------------------------------------------------------ #define _INCLUDE_NLS #include #include #include #include #include #include typedef struct EV11LMeterStyle_s { ULONGLONG Horizontal : 1; ULONGLONG LogScale : 1; ULONGLONG HideValue : 1; ULONGLONG HideLabel : 1; ULONGLONG HideUnits : 1; } EV11LMeterStyle; #pragma comment(lib, "chartdir60.lib") // ------------------------------------------------------------------------ /* BOOL tio_SetODRegion( int tly, int tlx, int bry, int brx, TIO_OWNERDRAWFCN fcnOwnerDraw, DWORD dwOwnerData ); BOOL tio_GetODRect ( int row, int col, LPRECT pr ); */ // ------------------------------------------------------------------------ /* Required meter data: log flag scale min value alert limit value high limit value scale max value current value area background color (i.e. condition color) */ extern "C" int ev11_HLMeter( HDC hdc, RECT *rMeter, EV11LMeterStyle style, double rdMin, double rdAlert, double rdHigh, double rdMax, double rdPeakLo, double rdValue, double rdPeakHi, int bgColor, int borderColor, int exteriorColor, char *szLabel, char *szUnits ) { double rdPlotMin ; double rdPlotAlert ; double rdPlotHigh ; double rdPlotMax ; double rdPlotValue ; double rdPlotPeakLo; double rdPlotPeakHi; int zoneCount; SIZE sMeter; char szValue[64]; BOOL bShowAlarmZones = TRUE; // stepColor Scale items: // { rdMin, GREEN, rdAlert, YELLOW, rdHigh, RED, rdMax }, count = 7 // if no ALERT, skip rdAlert, YELLOW members count = 5 // if no HIGH, skip rdHigh, RED members count = 5 // if no ALARMS, { rdMin, GREEN, rdMax } count = 3 double zoneColorScale[] = {0, 0, 0, 0, 0, 0, 0}; if( (DBL_MAX == rdAlert) && (DBL_MAX == rdHigh) ) { bShowAlarmZones = FALSE; } if( style.LogScale ) { // Convert plot values from log to linear rdPlotMin = round(log10(rdMin)); rdPlotAlert = log10(rdAlert ); rdPlotHigh = log10(rdHigh ); rdPlotMax = round(log10(rdMax)); rdPlotValue = log10(rdValue ); rdPlotPeakLo = log10(rdPeakLo); rdPlotPeakHi = log10(rdPeakHi); } else { rdPlotMin = rdMin ; rdPlotAlert = rdAlert ; rdPlotHigh = rdHigh ; rdPlotMax = rdMax ; rdPlotValue = rdValue ; rdPlotPeakLo = rdPeakLo; rdPlotPeakHi = rdPeakHi; } if( (rdMin < rdAlert) && (rdAlert < rdHigh) && (rdHigh < rdMax) ) { // All limits present... zoneColorScale[0] = rdPlotMin; zoneColorScale[1] = 0x00CC00; // green zoneColorScale[2] = rdPlotAlert; zoneColorScale[3] = 0xCCCC00; // yellow zoneColorScale[4] = rdPlotHigh; zoneColorScale[5] = 0xCC0000; // red zoneColorScale[6] = rdPlotMax; zoneCount = 7; } else if( (rdAlert <= rdMin) || (rdHigh <= rdAlert) ) { // no alert if( (rdHigh <= rdMin) || (rdMax <= rdHigh) ) { zoneColorScale[0] = rdPlotMin; zoneColorScale[1] = 0x00CC00; // green zoneColorScale[2] = rdPlotMax; zoneCount = 3; } else { zoneColorScale[0] = rdPlotMin; zoneColorScale[1] = 0x00CC00; // green zoneColorScale[2] = rdPlotHigh; zoneColorScale[3] = 0xCC0000; // red zoneColorScale[4] = rdPlotMax; zoneCount = 5; } } else if( (rdHigh <= rdAlert) || (rdMax <= rdHigh) ) { // ho high if( (rdAlert <= rdMin) || (rdMax <= rdAlert) ) { zoneColorScale[0] = rdPlotMin; zoneColorScale[1] = 0x00CC00; // green zoneColorScale[2] = rdPlotMax; zoneCount = 3; } else { zoneColorScale[0] = rdPlotMin; zoneColorScale[1] = 0x00CC00; // green zoneColorScale[2] = rdPlotAlert; zoneColorScale[3] = 0xCCCC00; // yellow zoneColorScale[4] = rdPlotMax; zoneCount = 5; } } sMeter.cx = rMeter->right - rMeter->left; sMeter.cy = rMeter->bottom - rMeter->top; // Create a LinearMeter object of size 250 x 75 pixels with a 3-pixel thick rounded frame LinearMeter *m = new LinearMeter(sMeter.cx, sMeter.cy, bgColor, borderColor); m->setRoundedFrame(exteriorColor);//Chart::Transparent); m->setThickFrame(3); #define XC(V) MulDiv((V),sMeter.cx,250) #define YC(V) MulDiv((V),sMeter.cy,75) // Set the scale region top-left corner at (14, 23), with size of 218 x 20 pixels. The scale // labels are located on the top (implies horizontal meter) m->setMeter(XC(14), YC(23), XC(218), YC(20), Chart::Top); //static int tickLength = -20; //m->setTickLength( tickLength ); // Set meter scale from 0 - 100, with a tick every 10 units m->setScale(rdPlotMin, rdPlotMax, 1); //m->setLabelStyle( "arialbd.ttf", 10 ); //m->setLabelPos( false, 2 ); //if( bShowAlarmZones ) //{ // Add the color zones at the default position m->addColorScale(DoubleArray(zoneColorScale, zoneCount)); //} if( (rdMin <= rdPeakLo) && (rdPeakLo <= rdMax) ) { // Add a black (0x000000) outline pointer at the specified value m->addPointer(rdPlotPeakLo, Chart::Transparent, 0x000000); } if( (rdMin <= rdPeakHi) && (rdPeakHi <= rdMax) ) { // Add a black (0x000000) outline pointer at the specified value m->addPointer(rdPlotPeakHi, Chart::Transparent, 0x000000); } if( (rdMin <= rdValue) && (rdValue <= rdMax) ) { // Add a blue (0x0000cc) pointer at the specified value m->addPointer(rdPlotValue, 0x0000cc); // Add a text box right aligned to (235, 61). Display the value using white (0xffffff) 8pt Arial // Bold font on a black (0x000000) background with depressed rounded border. sprintf( szValue, "%.2E", rdValue ); } else if( (1.0e-19 <= rdValue) && (rdValue <= 9.99e+19) ) { // Add a text box right aligned to (235, 61). Display the value using white (0xffffff) 8pt Arial // Bold font on a black (0x000000) background with depressed rounded border. sprintf( szValue, "%.2E", rdValue ); } else { strcpy( szValue, "unknown" ); } if( 0 == style.HideValue ) { TextBox *t = m->addText(XC(235), YC(61), szValue, "arialbd.ttf", YC(10), 0xffffff, Chart::Right); t->setBackground(0x000000, 0x000000, -1); t->setRoundedCorners(3); } if( 0 == style.HideLabel ) { // Add a label left aligned to (10, 61) using 10pt Arial Bold font m->addText(XC(10), YC(61), szLabel, "arialbd.ttf", YC(10), Chart::TextColor, Chart::Left); } if( 0 == style.HideUnits ) { // Add a label center aligned to (87, 61) using 10pt Arial Bold font m->addText(XC(125), YC(61), szUnits, "arialbd.ttf", YC(10), Chart::TextColor, Chart::Center); } // Output the chart as BMP MemBlock bmp = m->makeChart( Chart::BMP ); // The BITMAPINFOHEADER is 14 bytes offset from the beginning LPBITMAPINFO header = (LPBITMAPINFO)(bmp.data + 14); // The bitmap data LPBYTE bitData = (LPBYTE)(bmp.data) + ((LPBITMAPFILEHEADER)(bmp.data))->bfOffBits; // Output to screen device context StretchDIBits( hdc, rMeter->left, rMeter->top, header->bmiHeader.biWidth, header->bmiHeader.biHeight, 0, 0, header->bmiHeader.biWidth, header->bmiHeader.biHeight, bitData, header, DIB_RGB_COLORS, SRCCOPY ); //free up resources delete m; return 0; } // ------------------------------------------------------------------------ // E N D O F F I L E // ------------------------------------------------------------------------