📄 progressbar.cpp
字号:
// ProgressBar.cpp : implementation file
//
#include "stdafx.h"
#include "Controls.h"
#include "ProgressBar.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CProgressBar
CProgressBar::CProgressBar()
{
m_nMin = 0;
m_nMax = 100;
m_nPos = 0;
m_bUsePercent = true;
m_strBarText = _T("");
m_hDrawEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
m_clrBar = RGB (0x00, 0x00, 0xff);
m_clrBackGnd = GetSysColor (COLOR_ACTIVEBORDER);
m_clrBarText = RGB (0xff, 0xff, 0xff);
m_clrBackText = RGB (0x00, 0x00, 0x00);
AfxBeginThread (UpdateThread, (LPVOID) this);
}
CProgressBar::~CProgressBar()
{
}
//
// The draw code for the progress bar happens in the
// background. This makes it possible to update the
// bar while other processing is going on.
UINT CProgressBar::UpdateThread(void *pParam)
{
CProgressBar &Bar = (*(CProgressBar *) pParam);
HANDLE hDraw = Bar.m_hDrawEvent;
while (1)
{
DWORD dwResult = WaitForSingleObject (hDraw, 1000);
switch (dwResult)
{
case WAIT_OBJECT_0:
Bar.DoRedraw ();
break;
case WAIT_TIMEOUT:
continue;
}
}
return (0);
}
//
// Update() sets the event, triggering a redraw of
// the progress bar.
//
void CProgressBar::Update()
{
SetEvent (m_hDrawEvent);
}
BEGIN_MESSAGE_MAP(CProgressBar, CStatic)
//{{AFX_MSG_MAP(CProgressBar)
ON_WM_PAINT()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CProgressBar message handlers
void CProgressBar::OnPaint()
{
CPaintDC dc(this); // device context for painting
DrawBar ((CWindowDC *) &dc);
}
void CProgressBar::DoRedraw()
{
CWindowDC dc(this);
DrawBar (&dc);
}
void CProgressBar::DrawBar(CWindowDC *pDC)
{
CRect rc;
GetWindowRect (rc);
if ((rc.right - rc.left) < (rc.bottom - rc.top))
{
DrawVerticalBar (pDC);
return;
}
CPen pen;
CBrush brushBack;
CString strText = _T("");
brushBack.CreateSolidBrush (m_clrBackGnd);
//
// Get the window rectangle and draw a 3D rectangle
// Then shrink the rectangle by one point so it will
// fit inside the 3D rectangle.
//
GetWindowRect (rc);
ScreenToClient (rc);
pDC->Draw3dRect (rc, GetSysColor (COLOR_3DDKSHADOW), GetSysColor (COLOR_3DHIGHLIGHT));
rc.left += 1;
rc.right -= 1;
rc.top += 1;
rc.bottom -= 1;
//
// Fill the inner rectangle with the background
// brush to erase any previous drawing.
//
pDC->FillRect (rc, &brushBack);
// int nPos = m_nPos * 100 / m_nMax;
int nPos = (m_nPos - m_nMin) * 100 / (m_nMax - m_nMin);
CRect rcBar = rc;
rcBar.right = (rcBar.right - rcBar.left) * nPos / 100;
CRect rcRest = rc;
rcRest.left = rcBar.right;
if (nPos)
{
CBrush brushBar;
CPen penBar;
brushBar.CreateSolidBrush (m_clrBar);
pDC->SelectObject (&brushBar);
penBar.CreatePen (PS_SOLID, 1, m_clrBar);
pDC->SelectObject (&penBar);
pDC->Rectangle (rcBar);
}
else
rcBar.right = rcBar.left;
if (m_Font.m_hObject == NULL)
{
CFont *font = GetFont ();
LOGFONT lf;
font->GetLogFont (&lf);
lf.lfHeight = (rc.bottom - rc.top) * 80 / 100;
lf.lfWeight = FW_BOLD;
strcpy (lf.lfFaceName, "Arial");
m_Font.CreateFontIndirect (&lf);
}
pDC->SelectObject (&m_Font);
pDC->SetBkMode (TRANSPARENT);
//
// Output the text, clipping the right side of
// the control so the text within the bar can
// be a different color than the text outside.
//
if (m_bUsePercent)
strText.Format ("%d%%", nPos);
else
strText = m_strBarText;
CSize sz = pDC->GetTextExtent ((LPCSTR) strText, strText.GetLength ());
rc.top = (rc.bottom - rc.top - sz.cy) / 2;
if (nPos)
{
pDC->SaveDC ();
pDC->ExcludeClipRect(rcRest);
pDC->SetTextColor (m_clrBarText);
pDC->DrawText (strText, rc, DT_CENTER | DT_NOPREFIX);
pDC->RestoreDC (-1);
}
pDC->SaveDC ();
//
// Clip the other part of the control and redraw
// the text in the background text color.
//
pDC->ExcludeClipRect(rcBar);
pDC->SetTextColor (m_clrBackText);
pDC->DrawText (strText, rc, DT_CENTER | DT_NOPREFIX);
pDC->RestoreDC (-1);
}
void CProgressBar::DrawVerticalBar(CWindowDC *pDC)
{
CPen pen;
CRect rc;
CBrush brushBack;
CString strText = _T("");
brushBack.CreateSolidBrush (m_clrBackGnd);
//
// Get the window rectangle and draw a 3D rectangle
// Then shrink the rectangle by one point so it will
// fit inside the 3D rectangle.
//
GetWindowRect (rc);
ScreenToClient (rc);
pDC->FillRect (rc, &brushBack);
pDC->Draw3dRect (rc, GetSysColor (COLOR_3DDKSHADOW), GetSysColor (COLOR_3DHIGHLIGHT));
rc.left += 1;
rc.right -= 1;
rc.top += 1;
rc.bottom -= 1;
//
// Fill the inner rectangle with the background
// brush to erase any previous drawing.
//
int nPos = (m_nPos - m_nMin) * 100 / (m_nMax - m_nMin);
// int nPos = m_nPos * 100 / m_nMax;
CRect rcBar = rc;
rcBar.top = rcBar.bottom - (rcBar.bottom - rcBar.top) * nPos / 100;
CRect rcRest = rc;
rcRest.bottom = rcBar.top;
if (nPos)
{
CBrush brushBar;
CPen penBar;
brushBar.CreateSolidBrush (m_clrBar);
pDC->SelectObject (&brushBar);
penBar.CreatePen (PS_SOLID, 1, m_clrBar);
pDC->SelectObject (&penBar);
pDC->Rectangle (rcBar);
}
else
rcBar.bottom = rcBar.top;
if (m_Font.m_hObject == NULL)
{
CFont *font = GetFont ();
LOGFONT lf;
font->GetLogFont (&lf);
lf.lfHeight = (rc.right - rc.left) * 80 / 100;
strcpy (lf.lfFaceName, "Arial");
lf.lfHeight *= -1;
lf.lfEscapement = lf.lfOrientation = 901;
lf.lfWeight = FW_BOLD;
m_Font.CreateFontIndirect (&lf);
}
pDC->SelectObject (&m_Font);
pDC->SetBkMode (TRANSPARENT);
//
// Output the text, clipping the right side of
// the control so the text within the bar can
// be a different color than the text outside.
//
if (m_bUsePercent)
strText.Format ("%d%%", nPos);
else
strText = m_strBarText;
CSize sz = pDC->GetTextExtent ((LPCSTR) strText, strText.GetLength());
int cxText = (rc.right - sz.cy) / 2;
if (nPos)
{
pDC->SaveDC ();
pDC->ExcludeClipRect(rcRest);
pDC->SetTextColor (m_clrBarText);
pDC->TextOut (cxText, rc.bottom / 2 + sz.cx / 2, (LPCSTR) strText, strText.GetLength());
pDC->RestoreDC (-1);
}
pDC->SaveDC ();
//
// Clip the other part of the control and redraw
// the text in the background text color.
//
pDC->ExcludeClipRect(rcBar);
pDC->SetTextColor (m_clrBackText);
pDC->SetTextAlign (TA_LEFT);
pDC->TextOut (cxText, rc.bottom / 2 + sz.cx / 2, (LPCSTR) strText, strText.GetLength());
pDC->RestoreDC (-1);
}
///////////////////////////////////////////////
// Functions to set progress bar parameters.
//
void CProgressBar::SetMinMax(UINT nMin, UINT nMax)
{
if (nMax <= nMin)
return;
m_nMin = nMin;
if (nMax > 0)
m_nMax = nMax;
else
m_nMax = 1;
if (m_nPos < m_nMin)
m_nPos = m_nMin;
if (m_nPos > m_nMax)
m_nPos = m_nMax;
}
UINT CProgressBar::SetPosition(UINT nPos)
{
UINT oldPos = m_nPos;
if (nPos > m_nMax)
m_nPos = m_nMax;
else if (nPos < m_nMin)
m_nPos = m_nMin;
else
m_nPos = nPos;
return (oldPos);
}
void CProgressBar::SetBarText(char *szText)
{
m_strBarText = szText;
}
void CProgressBar::SetBarText(CString strText)
{
m_strBarText = strText;
}
//
// If m_bUsePercent is true, the ratio or the bar
// to the full width times 100 will be displayed in
// the progress bar along with a % sign. If false,
// the text in m_strBarText is used.
//
void CProgressBar::UsePercent(bool bUsePct)
{
m_bUsePercent = bUsePct;
}
//
// Set custom color information for the progress bar.
//
COLORREF CProgressBar::SetBarColor(COLORREF clrBar)
{
COLORREF clrOld = m_clrBar;
m_clrBar = clrBar;
return (clrOld);
}
COLORREF CProgressBar::SetBarTextColor(COLORREF clrBarText)
{
COLORREF clrOld = m_clrBarText;
m_clrBarText = clrBarText;
return (clrOld);
}
COLORREF CProgressBar::SetBackColor(COLORREF clrBack)
{
COLORREF clrOld = m_clrBackGnd;
m_clrBackGnd = clrBack;
return (clrOld);
}
COLORREF CProgressBar::SetBackTextColor(COLORREF clrBackText)
{
COLORREF clrOld = m_clrBackText;
m_clrBackText = clrBackText;
return (clrOld);
}
int CProgressBar::GetPosition()
{
return (m_nPos);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -