⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 barchart.cpp

📁 a bar chart,a good refernce for the control
💻 CPP
📖 第 1 页 / 共 4 页
字号:

void CBarChart::CChartBar::ShowBarText(int nType, BOOL bShow)
{
	m_bShowBarText = bShow;
	m_nBarTextType = nType;
}

void CBarChart::CChartBar::DisplayToolTip(CPoint& point, CRect& rcBound, 
										  CRect& rcMemPic, BOOL bScale, CString& szTip)
{
	if (bScale)
	{
		m_dAlpha = (double)rcBound.Width()/ (double)(m_sBarPicSize.cx+m_rMargin*2);
	}
	else
	{
		m_dAlpha = (double)rcMemPic.Width()/ (double)(m_sBarPicSize.cx+m_rMargin*2);
	}
 	m_dIndex = (int) ( (double)(point.x - m_rMargin*m_dAlpha) / 
						 (double)((m_nBarWidth*m_dAlpha) + (m_nBarGap*m_dAlpha)) );

	if (m_dIndex<0.0 || (int)m_dIndex>=m_chartData.GetCount())
	{
		szTip = "";
	}
	else
	{
		szTip.Format("%s\n%0.04f\n%0.02f%%\n", 
			m_chartData.GetLabel((int)m_dIndex),m_chartData.GetValue((int)m_dIndex),
			(m_chartData.GetValue((int)m_dIndex)*100)/m_chartData.GetMaxValue());
	}
}

BOOL CBarChart::CChartBar::IsLabelVisible()
{
	return m_bShowLabel;
}
 ///////////////////////////////////////////////////////////////////////
 // CChartGCalc Class
 //
 //
 //			A set of handy GDI functions for manipulating
 //			pixel colors, etc.
 //
 ///////////////////////////////////////////////////////////////////////

UINT CChartGCalc::GABS (const int& nmbr)
{
	return (nmbr>0)?nmbr:-nmbr;
}

COLORREF CChartGCalc::DifColor(COLORREF color, UINT nDist)
{
	return RGB(
				GABS(GetRValue(color)-nDist),
				GABS(GetGValue(color)-nDist),
				GABS(GetBValue(color)-nDist)
				);
}

COLORREF CChartGCalc::OrColor(COLORREF colFore, COLORREF colBK, UINT nForePercent)
{
	return RGB (
	( GetRValue(colBK)*100 + ( nForePercent*(GetRValue(colFore)-GetRValue(colBK)) ) ) /100,
	( GetGValue(colBK)*100 + ( nForePercent*(GetGValue(colFore)-GetGValue(colBK)) ) ) /100,
	( GetBValue(colBK)*100 + ( nForePercent*(GetBValue(colFore)-GetBValue(colBK)) ) ) /100 );
}

// Refer to the following article in 'CodeProject.com' By 'Roger Allen'
// 'Printing tips and tricks from the trenches' 
// And goto topic: 'Use DIB's instead of DDB's'

// DDBToDIB      - Creates a DIB from a DDB
// bitmap        - Device dependent bitmap
// dwCompression - Type of compression - see BITMAPINFOHEADER
// pPal          - Logical palette
HANDLE CChartGCalc::DDBToDIB( CBitmap* bitmap, DWORD dwCompression, CPalette* pPal ) 
{
    BITMAP            bm;
    BITMAPINFOHEADER    bi;
    LPBITMAPINFOHEADER     lpbi;
    DWORD			dwLen;
    HANDLE          hDIB;
    HANDLE          handle;
    HDC             hDC;
    HPALETTE        hPal;


    ASSERT( bitmap->GetSafeHandle() );

    // The function has no arg for bitfields
    if( dwCompression == BI_BITFIELDS )
        return NULL;

    // If a palette has not been supplied use default palette
    hPal = (HPALETTE) pPal->GetSafeHandle();
    if (hPal==NULL)
        hPal = (HPALETTE) GetStockObject(DEFAULT_PALETTE);

    // Get bitmap information
    bitmap->GetObject(sizeof(bm),(LPSTR)&bm);

    // Initialize the bitmapinfoheader
    bi.biSize        = sizeof(BITMAPINFOHEADER);
    bi.biWidth       = bm.bmWidth;
    bi.biHeight      = bm.bmHeight;
    bi.biPlanes      = 1;
    bi.biBitCount    = (unsigned short)(bm.bmPlanes * bm.bmBitsPixel) ;
    bi.biCompression = dwCompression;
    bi.biSizeImage   = 0;
    bi.biXPelsPerMeter  = 0;
    bi.biYPelsPerMeter  = 0;
    bi.biClrUsed        = 0;
    bi.biClrImportant   = 0;

    // Compute the size of the  infoheader and the color table
    int nColors = 0;
    if(bi.biBitCount <= 8)
	{
        nColors = (1 << bi.biBitCount);
	}
    dwLen  = bi.biSize + nColors * sizeof(RGBQUAD);

    // We need a device context to get the DIB from
    hDC = ::GetDC(NULL);
    hPal = SelectPalette(hDC,hPal,FALSE);
    RealizePalette(hDC);

    // Allocate enough memory to hold bitmapinfoheader and color table
    hDIB = GlobalAlloc(GMEM_FIXED,dwLen);

    if (!hDIB){
        SelectPalette(hDC,hPal,FALSE);
        ::ReleaseDC(NULL,hDC);
        return NULL;
    }

    lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB);

    *lpbi = bi;

    // Call GetDIBits with a NULL lpBits param, so the device driver 
    // will calculate the biSizeImage field 
    GetDIBits(hDC, (HBITMAP)bitmap->GetSafeHandle(), 0L, (DWORD)bi.biHeight,
            (LPBYTE)NULL, (LPBITMAPINFO)lpbi, (DWORD)DIB_RGB_COLORS);

    bi = *lpbi;

    // If the driver did not fill in the biSizeImage field, then compute it
    // Each scan line of the image is aligned on a DWORD (32bit) boundary
    if (bi.biSizeImage == 0){
        bi.biSizeImage = ((((bi.biWidth * bi.biBitCount) + 31) & ~31) / 8) 
                        * bi.biHeight;

        // If a compression scheme is used the result may infact be larger
        // Increase the size to account for this.
        if (dwCompression != BI_RGB)
            bi.biSizeImage = (bi.biSizeImage * 3) / 2;
    }

    // Realloc the buffer so that it can hold all the bits
    dwLen += bi.biSizeImage;
    handle = GlobalReAlloc(hDIB, dwLen, GMEM_MOVEABLE) ;
    if (handle != NULL)
        hDIB = handle;
    else
        {
        GlobalFree(hDIB);

        // Reselect the original palette
        SelectPalette(hDC,hPal,FALSE);
        ::ReleaseDC(NULL,hDC);
        return NULL;
        }

    // Get the bitmap bits
    lpbi = (LPBITMAPINFOHEADER)hDIB;

    // FINALLY get the DIB
    BOOL bGotBits = GetDIBits( hDC, (HBITMAP)bitmap->GetSafeHandle(),
                0L,                      // Start scan line
                (DWORD)bi.biHeight,      // # of scan lines
                (LPBYTE)lpbi             // address for bitmap bits
                + (bi.biSize + nColors * sizeof(RGBQUAD)),
                (LPBITMAPINFO)lpbi,      // address of bitmapinfo
                (DWORD)DIB_RGB_COLORS);  // Use RGB for color table

    if( !bGotBits )
    {
        GlobalFree(hDIB);
        
        SelectPalette(hDC,hPal,FALSE);
        ::ReleaseDC(NULL,hDC);
        return NULL;
    }

    SelectPalette(hDC,hPal,FALSE);
    ::ReleaseDC(NULL,hDC);
    return hDIB;
}

 ///////////////////////////////////////////////////////////////////////
 // CChartData Class									
 //													
 //		Holds data of a chart and let the chart to do
 //			reqauered operations on it					
 //
 ///////////////////////////////////////////////////////////////////////
CBarChart::CChartData::CChartData()
{
	m_udMax = 0;
}

void CBarChart::CChartData::CalculateMaximum()
{
	for (int i=0;i<m_arr.GetSize();i++)
	{
		if (m_udMax<((data*)m_arr.GetAt(i))->m_udValue)
		{
			m_udMax = ((data*)m_arr.GetAt(i))->m_udValue;
		}
	}
}

void CBarChart::CChartData::RemoveAll()
{
	data* pData;
	for (int i=0;i<m_arr.GetSize();i++ ){
		if (  (pData=(data*)m_arr.GetAt(i))!=NULL ) {
			delete pData;
		}
	}

	m_arr.RemoveAll();
	m_udMax = 0;
}

void CBarChart::CChartData::RemoveAt(int nIndex)
{
	if (m_arr.GetSize()==0)
		return;

	if (nIndex>=m_arr.GetSize() || nIndex<0)
	{
		return;
	}

	delete (data*) m_arr.GetAt(nIndex);
	m_arr.RemoveAt(nIndex);

	CalculateMaximum();
}

int CBarChart::CChartData::GetCount()
{
	return m_arr.GetSize();
}

void CBarChart::CChartData::Add (CString& szLabel, double udValue, COLORREF color)
{
	data *pData;

	pData = new data;
	pData->m_szLabel = szLabel;
	pData->m_udValue = udValue;
	pData->m_color = color;

	m_arr.Add((CObject*)pData);

	if (m_udMax<udValue)
	{
		m_udMax = udValue;
	}
}

double CBarChart::CChartData::GetMaxValue()
{
	if (m_udMax!=0)
	{
		return m_udMax;
	}
	else
	{
		// Eliminate probability of division by zero
		return 1;
	}
}

double CBarChart::CChartData::GetValue(int nIndex)
{
	if (nIndex<0 || nIndex>=m_arr.GetSize())
	{
		return -1;
	}

	return ((data*)m_arr.GetAt(nIndex))->m_udValue;
}

CString CBarChart::CChartData::GetLabel(int nIndex)
{
	if (nIndex<0 || nIndex>=m_arr.GetSize())
	{
		return "";
	}
	return ((data*)m_arr.GetAt(nIndex))->m_szLabel;
}

COLORREF CBarChart::CChartData::GetColor(int nIndex)
{
	if (nIndex<0 || nIndex>=m_arr.GetSize())
	{
		return RGB(0, 0, 0);
	}

	return ((data*)m_arr.GetAt(nIndex))->m_color;
}
 ///////////////////////////////////////////////////////////////////////
 // CChartPrinter Class										 
 //																 
 //			No need to description(!) This class should print the
 //			Chart using print dialog.							 
 //															 
 ///////////////////////////////////////////////////////////////////////

// Many of the following code, had been stolen shamelessly from ChrisMaunder's Best work: MFCGrid
// Find it in 'www.codeproject.com'
void CBarChart::CChartPrinter::Print(CDC* pDC, CDC *pMemDC, CBitmap* pBmp,
									 CString szTitle, CRect& rcMemPic, BOOL bFit, 
									 BOOL bCompatible)
{
    CDC dc;

    CPrintDialog printDlg(FALSE);
    if (printDlg.DoModal() != IDOK)             // Get printer settings from user
        return;

    dc.Attach(printDlg.GetPrinterDC());         // attach a printer DC

	m_rcMemPic = rcMemPic;
	m_pMemDC = pMemDC;
	m_pBmpMem = pBmp;
	m_bScale = bFit;
    
	DOCINFO di;                                 // Initialise print doc details
    memset(&di, 0, sizeof (DOCINFO));
    di.cbSize = sizeof (DOCINFO);
    di.lpszDocName = szTitle;

    BOOL bPrintingOK = dc.StartDoc(&di);        // Begin a new print job
    CPrintInfo info;
    info.m_rectDraw.SetRect(0,0, dc.GetDeviceCaps(HORZRES), dc.GetDeviceCaps(VERTRES));

	dc.StartPage();                         // begin new page

	if (bCompatible)
	{
		OnPrintCompatible(&dc, &info);
	}
	else
	{
		OnPrint(&dc, &info);
	}

    bPrintingOK = (dc.EndPage() > 0);       // end page

    if (bPrintingOK)
        dc.EndDoc();                            // end a print job
    else
        dc.AbortDoc();                          // abort job.

    dc.Detach();                                // detach the printer DC
}

void CBarChart::CChartPrinter::OnPrint (CDC *pDC, CPrintInfo* pInfo)
{
	// Do some calculations
	pDC->SetMapMode(MM_ANISOTROPIC);

	pInfo->m_nCurPage = 1;
	pInfo->SetMaxPage(1);
//	UNDONE : SET TRUE MAPPING MODE, AND CALCULATIONS, IN CASE OF NON-SCALED CHART PRINTING
//	if (m_bScale)
//	{
		pDC->StretchBlt(pInfo->m_rectDraw.left, 
			pInfo->m_rectDraw.top, pInfo->m_rectDraw.Width(), pInfo->m_rectDraw.Height(), 
			m_pMemDC, 0, 0, m_rcMemPic.Width(), m_rcMemPic.Height(), 
			SRCCOPY);
//	}
//	else
//	{
//		pDC->BitBlt(pInfo->m_rectDraw.left, 
//			pInfo->m_rectDraw.top, pInfo->m_rectDraw.Width(), pInfo->m_rectDraw.Height(), 
//			m_pMemDC, 0, 0, SRCCOPY);
//	}
}
// Refered to the following article in 'CodeProject.com' By 'Roger Allen'
// 'Printing tips and tricks from the trenches' 
// And in topic: 'Use DIB's instead of DDB's'
// Print function might not work is a DDB blotting is done
void CBarChart::CChartPrinter::OnPrintCompatible (CDC *pDC, CPrintInfo* pInfo)
{
	// Do some calculations
	pDC->SetMapMode(MM_ANISOTROPIC);

	pInfo->m_nCurPage = 1;
	pInfo->SetMaxPage(1);


	CPalette    pal;
	UINT        nSize   = sizeof(LOGPALETTE) + ( sizeof(PALETTEENTRY) * 256 );
	LOGPALETTE* pLP     = (LOGPALETTE*)new BYTE[nSize];
	pLP->palVersion     = 0x300;
	pLP->palNumEntries = (unsigned short)GetSystemPaletteEntries( m_pMemDC->GetSafeHdc(), 0, 255, 
		pLP->palPalEntry );

	// Create the palette
	pal.CreatePalette( pLP );

	// Free memory
	delete[] pLP;

	// Convert the bitmap to a DIB
    HANDLE hDib = DDBToDIB(m_pBmpMem, BI_RGB, &pal );

    BITMAPINFOHEADER    *pBMI ;
    pBMI = (BITMAPINFOHEADER*)GlobalLock(hDib) ;
    int nColors = 0;
    if (pBMI->biBitCount <= 8)
        {
        nColors = (1 << pBMI->biBitCount);
        }
    // print the correct image
    ::StretchDIBits(pDC->m_hDC,
                        pInfo->m_rectDraw.left, 
                        pInfo->m_rectDraw.top, 
                        pInfo->m_rectDraw.Width(), 
						pInfo->m_rectDraw.Height(),
                        0, 
                        0, 
                        pBMI->biWidth,
                        pBMI->biHeight,
                        (LPBYTE)pBMI + (pBMI->biSize + nColors * sizeof(RGBQUAD)),
                        (BITMAPINFO*)pBMI,
                        DIB_RGB_COLORS, 
                        SRCCOPY);
    // free resources
    GlobalUnlock(hDib) ;
    GlobalFree(hDib) ;
}

 ///////////////////////////////////////////////////////////////////////
 // CChartTip Class
 //
 //
 //				Adds tooltip capabilities for bar chart.
 //				Tooltip should show: value, Label and percentage
 //
 ///////////////////////////////////////////////////////////////////////

CChartTip::CChartTip()
{
	if ( m_lpszClass == NULL ) m_lpszClass = AfxRegisterWndClass( CS_SAVEBITS );
	if ( m_lpszClass == NULL ) m_lpszClass = AfxRegisterWndClass( CS_SAVEBITS );
}

CChartTip::~CChartTip()
{
	if (m_brShadow.GetSafeHandle())
	{
		m_brShadow.DeleteObject();
	}

	if (m_brFrame.GetSafeHandle())
	{
		m_brFrame.DeleteObject();
	}

	if (m_brBK.GetSafeHandle())
	{
		m_brBK.DeleteObject();
	}

	if (m_fontBold.GetSafeHandle())
	{
		m_fontBold.DeleteObject();
	}

	if (m_fontNorm.GetSafeHandle())
	{
		m_fontNorm.DeleteObject();
	}
	
	// Shall not do delete m_rgnTip
	// System will delete this rgn whenever doesnot need it any more

	if (m_rgnCopy.GetSafeHandle())
	{
		m_rgnCopy.DeleteObject();
	}

	if (m_bTimer)
	{
		if (m_hWnd != NULL )
		{
			m_bTimer = FALSE;
			KillTimer(TIP_DELAY_TIMER);
		}
	}

	if (m_hWnd)
	{
		if (IsWindowVisible())
		{
			HideWindow();
		}
	}

	if ( m_hWnd != NULL ) DestroyWindow();
}


BEGIN_MESSAGE_MAP(CChartTip, CWnd)
	//{{AFX_MSG_MAP(CChartTip)
	ON_WM_TIMER()
	ON_WM_LBUTTONDOWN()
	ON_WM_MOUSEMOVE()
	ON_WM_ERASEBKGND()
	ON_WM_PAINT()
	ON_WM_CREATE()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()


/////////////////////////////////////////////////////////////////////////////
// CChartTip message handlers
LPCTSTR CChartTip::m_lpszClass = NULL;

BOOL CChartTip::Create(CWnd *pParentWnd, BOOL *pbEnable, CString* lpszTitle, int nDelay)
{
	m_rcClient = CRect(0, 0, 0, 0);

	DWORD dwStyleEx = WS_EX_TOPMOST;
	if ( ! CWnd::CreateEx( dwStyleEx, m_lpszClass, NULL, WS_POPUP,
		m_rcClient, pParentWnd, 0, NULL ) ) return FALSE;

	SetOwner( pParentWnd );
	
	m_pbEnable = pbEnable;
	m_lpszTitle = lpszTitle;
	m_nDelay = nDelay;
	m_bTimer = FALSE;

	
	m_rcClient = CRect(0, 0, 120 , 100);

	// create a brush
	m_brFrame.CreateSolidBrush(TIP_FRAME_COLOR);
	m_brShadow.CreateSolidBrush(TIP_SHADOW_COLOR);
	m_brBK.CreateSolidBrush(TIP_BK_COLOR);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -