// ScrollBarEx.cpp : implementation file
//
#include "stdafx.h"
#include "MemDC.h"
#include "ScrollBarEx.h"
#include "intfCtrlNotifyMsg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#define SCROLLBAREXCLASSNAME "ScrollBarExWnd"
/////////////////////////////////////////////////////////////////////////////
// CScrollBarEx
CScrollBarEx::CScrollBarEx()
{
RegisterWindowClass();
m_nPrecise = 2;
m_dblMin = 0;
m_dblMax = 100;
m_dblCurVal = 50;
m_crSbBk = RGB(212, 208, 200);
m_crTextBk = RGB(126, 136, 171);
m_crCurVal = RGB(255, 255, 255);
m_crMaxMinVal = RGB(255, 0, 0);
m_nLBtnStatus = BTN_NORMAL;
m_nRBtnStatus = BTN_NORMAL;
m_bSBPressed = FALSE;
m_bThumbPressed = FALSE;
// m_bTimerProc = FALSE;
m_bSBLBtnHover = FALSE;
m_bSBRBtnHover = FALSE;
}
CScrollBarEx::~CScrollBarEx()
{
}
BEGIN_MESSAGE_MAP(CScrollBarEx, CWnd)
//{{AFX_MSG_MAP(CScrollBarEx)
ON_WM_PAINT()
ON_WM_LBUTTONDOWN()
ON_WM_LBUTTONUP()
ON_WM_MOUSEMOVE()
ON_WM_TIMER()
ON_WM_LBUTTONDBLCLK()
ON_WM_ERASEBKGND()
ON_WM_GETDLGCODE()
ON_WM_KEYDOWN()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CScrollBarEx message handlers
BOOL CScrollBarEx::RegisterWindowClass(void)
{
WNDCLASS wndcls;
// HINSTANCE hInst = AfxGetInstanceHandle();
HINSTANCE hInst = AfxGetResourceHandle();
if (!(::GetClassInfo(hInst, SCROLLBAREXCLASSNAME, &wndcls)))
{
// otherwise we need to register a new class
wndcls.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
wndcls.lpfnWndProc = ::DefWindowProc;
wndcls.cbClsExtra = wndcls.cbWndExtra = 0;
wndcls.hInstance = hInst;
wndcls.hIcon = NULL;
wndcls.hCursor = AfxGetApp()->LoadStandardCursor(IDC_ARROW);
wndcls.hbrBackground = NULL; // No Background brush (gives flicker)
wndcls.lpszMenuName = NULL;
wndcls.lpszClassName = SCROLLBAREXCLASSNAME;
if (!AfxRegisterClass(&wndcls))
{
AfxThrowResourceException();
return FALSE;
}
}
return TRUE;
}
BOOL CScrollBarEx::Create(DWORD dwStyle, const RECT rect, CWnd *pParentWnd, UINT nID)
{
return CWnd::Create(SCROLLBAREXCLASSNAME, "", dwStyle, rect, pParentWnd, nID);
}
void CScrollBarEx::OnPaint()
{
CPaintDC dc(this); // device context for painting
// TODO: Add your message handler code here
CRect rcClient;
CRgn rgnScrollBar;
CDC MemDC;
CBitmap bm;
CBitmap *pOldBm;
GetClientRect(rcClient);
rgnScrollBar.CreateRectRgnIndirect(&rcClient);
dc.SelectClipRgn(&rgnScrollBar);
MemDC.CreateCompatibleDC(&dc);
bm.CreateCompatibleBitmap(&dc, rcClient.Width(), rcClient.Height());
pOldBm = (CBitmap *)MemDC.SelectObject(&bm);
CalcRect();
DrawBk(&MemDC);
DrawDataText(&MemDC);
DrawLRButton(&MemDC);
DrawScrollZoneButton(&MemDC);
dc.BitBlt(0, 0, rcClient.Width(), rcClient.Height(), &MemDC, 0, 0, SRCCOPY);
MemDC.SelectObject(pOldBm);
MemDC.DeleteDC();
// Do not call CWnd::OnPaint() for painting messages
}
void CScrollBarEx::CalcRect()
{
CRect rcClient, rcClientTxt, rcClientCtrl;
GetClientRect(rcClient);
m_rcClient = rcClientCtrl = rcClientTxt = rcClient;
rcClientTxt.bottom = rcClientTxt.top + rcClientTxt.Height() / 2;
// rcClientTxt.DeflateRect(1, 1);
rcClientTxt.bottom -= 1;
m_rcText = rcClientTxt;
rcClientCtrl.top = rcClientCtrl.top + rcClientCtrl.Height() / 2;
// rcClientCtrl.DeflateRect(1, 1);
rcClientCtrl.top -= 1;
rcClientCtrl.bottom -= 1;
rcClientCtrl.left += 1;
rcClientCtrl.right -= 1;
m_rcScrollBar = m_rcSBLBtn = m_rcSBRBtn = rcClientCtrl;
m_rcSBLBtn.right = m_rcSBLBtn.left + m_rcSBLBtn.Height();
// m_rcSBLBtn.bottom = m_rcSBLBtn.top + 17;
m_rcSBRBtn.left = m_rcSBRBtn.right - m_rcSBRBtn.Height();
// m_rcSBRBtn.bottom = m_rcSBRBtn.top + 17;
m_rcScrollBar.left = m_rcSBLBtn.right;
m_rcScrollBar.right = m_rcSBRBtn.left;
// ���㵱ǰֵ��λ��
int nThumbLen = int(m_rcScrollBar.Width() * 5.0 / 100 + 0.5);
int nThumbRangeMax = m_rcScrollBar.Width() - nThumbLen;
// ������ֵ�ٷֱ�
double dblPercent = (m_dblCurVal - m_dblMin) / (m_dblMax - m_dblMin);
int nLeftPos = int(nThumbRangeMax * dblPercent);
m_rcSBThumb = m_rcScrollBar;
// m_rcSBThumb.top += 1;
m_rcSBThumb.left = m_rcScrollBar.left + nLeftPos;
m_rcSBThumb.right = m_rcSBThumb.left + nThumbLen;
}
void CScrollBarEx::DrawBk(CDC *pDC)
{
pDC->FillSolidRect(m_rcClient, m_crSbBk);
}
void CScrollBarEx::DrawDataText(CDC *pDC)
{
// �������ֵ����Сֵ�Լ���ǰֵ
CString strText;
CString strFmt;
pDC->SetBkMode(TRANSPARENT);
pDC->FillSolidRect(m_rcText, m_crTextBk);
// �������������Сֵ
pDC->SetTextColor(m_crMaxMinVal);
strFmt.Format("%%.%df", m_nPrecise);
strText.Format(strFmt, m_dblMin);
pDC->DrawText(strText, m_rcText, DT_VCENTER | DT_LEFT | DT_SINGLELINE);
strText.Format(strFmt, m_dblMax);
pDC->DrawText(strText, m_rcText, DT_VCENTER | DT_RIGHT | DT_SINGLELINE);
// ���Ƶ�ǰֵ
pDC->SetTextColor(m_crCurVal);
strText.Format(strFmt, m_dblCurVal);
pDC->DrawText(strText, m_rcText, DT_VCENTER | DT_CENTER | DT_SINGLELINE);
}
void CScrollBarEx::DrawLRButton(CDC *pDC)
{
// draw left button
if (m_nLBtnStatus == BTN_NORMAL)
{
pDC->DrawFrameControl(m_rcSBLBtn, DFC_SCROLL, DFCS_SCROLLLEFT);
}
else
{
pDC->DrawFrameControl(m_rcSBLBtn, DFC_SCROLL, DFCS_SCROLLLEFT | DFCS_FLAT);
}
if (m_nRBtnStatus == BTN_NORMAL)
{
pDC->DrawFrameControl(m_rcSBRBtn, DFC_SCROLL, DFCS_SCROLLRIGHT);
}
else
{
pDC->DrawFrameControl(m_rcSBRBtn, DFC_SCROLL, DFCS_SCROLLRIGHT | DFCS_FLAT);
}
}
void CScrollBarEx::DrawScrollZoneButton(CDC *pDC)
{
// draw fill bak color
CPen NewPen;
CPen *pOldPen;
LOGBRUSH LogBrush;
LogBrush.lbStyle = BS_SOLID;
LogBrush.lbColor = RGB(255, 255, 255);
NewPen.CreatePen(PS_GEOMETRIC | PS_DOT | PS_ENDCAP_FLAT, 1, &LogBrush);
pOldPen = pDC->SelectObject(&NewPen);
int j = 0;
for (int i = m_rcScrollBar.top; i < m_rcScrollBar.bottom; i++)
{
if (j % 2)
{
pDC->MoveTo(m_rcScrollBar.left, i);
pDC->LineTo(m_rcScrollBar.right, i);
}
else
{
pDC->MoveTo(m_rcScrollBar.left + 1, i);
pDC->LineTo(m_rcScrollBar.right, i);
}
j++;
}
pDC->SelectObject(pOldPen);
NewPen.DeleteObject();
CRect rcThumb = m_rcSBThumb;
// rcThumb.DeflateRect(0, 1);
pDC->FillSolidRect(rcThumb, GetSysColor(COLOR_BTNFACE));
pDC->DrawEdge(rcThumb, EDGE_RAISED, BF_TOPLEFT | BF_BOTTOMRIGHT);
}
void CScrollBarEx::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
if (GetFocus()->GetSafeHwnd() != GetSafeHwnd())
{
SetFocus();
TRACE("111\n");
}
double dblAdd = (m_dblMax - m_dblMin) * 0.01;
if (dblAdd > 1)
{
dblAdd = 1;
}
SetCapture();
BOOL bSndMsg = FALSE;
// �ж��Ƿ��ڸ��������ڲ�
if (m_rcSBLBtn.PtInRect(point))
{
// TRACE("m_rcSBLBtn %d\n ", GetTickCount());
m_nLBtnStatus = BTN_FLAT;
// m_bLBtnPressed = TRUE;
#if 1
m_dblCurVal -= dblAdd;
if (m_dblCurVal <= m_dblMin)
{
m_dblCurVal = m_dblMin;
}
// bSndMsg = TRUE;
#endif
SetTimer(TIMERID_LEFTBTN, 100, NULL);
}
else if (m_rcSBRBtn.PtInRect(point))
{
// SetTimer(100, 200, NULL);
m_nRBtnStatus = BTN_FLAT;
// m_bRBtnPressed = TRUE;
#if 1
m_dblCurVal += dblAdd;
if (m_dblCurVal >= m_dblMax)
{
m_dblCurVal = m_dblMax;
}
// bSndMsg = TRUE;
#endif
SetTimer(TIMERID_RIGHTBTN, 100, NULL);
}
else if (m_rcSBThumb.PtInRect(point))
{
m_bThumbPressed = TRUE;
m_ClickPoint = point;
}
else if (m_rcScrollBar.PtInRect(point))
{
m_bSBPressed = TRUE;
#if 1
// ���������ӻ��Ǽ���
if (point.x > m_rcSBThumb.right)
{
m_dblCurVal += dblAdd * 2;
}
else if (point.x < m_rcSBThumb.left)
{
m_dblCurVal -= dblAdd * 2;
}
if (m_dblCurVal >= m_dblMax)
{
m_dblCurVal = m_dblMax;
}
if (m_dblCurVal <= m_dblMin)
{
m_dblCurVal = m_dblCurVal;
}
// bSndMsg = TRUE;
#endif
SetTimer(TIMERID_SCROLLBAR, 30, NULL);
}
Invalidate();
if (bSndMsg)
{
SendMsgToParentWnd();
}
// CWnd::OnLButtonDown(nFlags, point);
}
void CScrollBarEx::OnLButtonUp(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
ReleaseCapture();
if (m_bThumbPressed)
{
m_bThumbPressed = FALSE;
}
else
{
Invalidate();
KillTimer(TIMERID_SCROLLBAR);
KillTimer(TIMERID_LEFTBTN);
KillTimer(TIMERID_LEFTBTNHOVER);
KillTimer(TIMERID_RIGHTBTN);
KillTimer(TIMERID_RIGHTBTNHOVER);
m_bSBPressed = FALSE;
m_bSBLBtnHover = FALSE;
m_nLBtnStatus = BTN_NORMAL;
// m_bLBtnPressed = FALSE;
m_bSBRBtnHover = FALSE;
m_nRBtnStatus = BTN_NORMAL;
// m_bRBtnPressed = FALSE;
SendMsgToParentWnd();
}
// CWnd::OnLButtonUp(nFlags, point);
}
void CScrollBarEx::OnMouseMove(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
// TRACE("MouseMove \n");
if (m_bThumbPressed)
{
int nMoveLen = 0;
double dblMoveVal = (point.x - m_ClickPoint.x) * 1.0 / m_rcScrollBar.Width() * (m_dblMax - m_dblMin);
m_dblCurVal += dblMoveVal;
if (m_dblCurVal >= m_dblMax)
{
m_dblCurVal = m_dblMax;
}
if (m_dblCurVal <= m_dblMin)
{
m_dblCurVal = m_dblMin;
}
SendMsgToParentWnd();
m_ClickPoint = point;
Invalidate();
}
// CWnd::OnMouseMove(nFlags, point);
}
double CScrollBarEx::GetScrollBarCurVal()
{
return m_dblCurVal;
}
void CScrollBarEx::SetScrollBarMinMaxVal(double dblMin, double dblMax)
{
m_dblMax = dblMax;
m_dblMin = dblMin;
}
void CScrollBarEx::SetScrollBarMinMaxValColor(COLORREF crMinMaxVal)
{
m_crMaxMinVal = crMinMaxVal;
}
void CScrollBarEx::SetScrollBarCurVal(double dblCurVal)
{
m_dblCurVal = dblCurVal;
}
void CScrollBarEx::SetScrollBarCurValColor(COLORREF crCurVal)
{
m_crCurVal = crCurVal;
}
void CScrollBarEx::SetScrollBarTextBkColor(COLORREF crTextBk)
{
m_crTextBk = crTextBk;
}
void CScrollBarEx::SetPrecise(int nPrec)
{
m_nPrecise = nPrec;
}
void CScrollBarEx::OnTimer(UINT nIDEvent)
{
// TODO: Add your message handler code here and/or call default
POINT MousePoint;
GetCursorPos(&MousePoint);
ScreenToClient(&MousePoint);
BOOL bSndMsg = FALSE;
double dblAdd = (m_dblMax - m_dblMin) * 0.01;
if (dblAdd > 1)
{
dblAdd = 1;
}
switch (nIDEvent)
{
case TIMERID_LEFTBTN:
// if (m_bLBtnPressed)
{
if (m_rcSBLBtn.PtInRect(MousePoint))
{
m_bSBLBtnHover = TRUE;
KillTimer(TIMERID_LEFTBTN);
SetTimer(TIMERID_LEFTBTNHOVER, 30, NULL);
Invalidate();
}
}
break;
case TIMERID_LEFTBTNHOVER:
{
if (m_rcSBLBtn.PtInRect(MousePoint))
{
m_bSBLBtnHover = TRUE;
m_nLBtnStatus = BTN_FLAT;
// m_bLBtnPressed = TRUE;
m_dblCurVal -= dblAdd;
if (m_dblCurVal <= m_dblMin)
{
m_dblCurVal = m_dblMin;
}
Invalidate();
}
else if (m_bSBLBtnHover)
{
m_bSBLBtnHover = FALSE;
// m_bLBtnPressed = FALSE;
m_nLBtnStatus = BTN_NORMAL;
Invalidate();
}
}
break;
case TIMERID_RIGHTBTN:
// if (m_bRBtnPressed)
{
if (m_rcSBRBtn.PtInRect(MousePoint))
{
m_bSBRBtnHover = TRUE;
KillTimer(TIMERID_RIGHTBTN);
SetTimer(TIMERID_RIGHTBTNHOVER, 30, NULL);
Invalidate();
}
}
break;
case TIMERID_RIGHTBTNHOVER:
{
if (m_rcSBRBtn.PtInRect(MousePoint))
{
m_bSBRBtnHover = TRUE;
// m_bRBtnPressed = TRUE;
m_nRBtnStatus = BTN_FLAT;
m_dblCurVal += dblAdd;
if (m_dblCurVal >= m_dblMax)
{
m_dblCurVal = m_dblMax;
}
bSndMsg = TRUE;
Invalidate();
}
else if (m_bSBRBtnHover)
{
TRACE("SBRTNHOVER OUT\n");
m_bSBRBtnHover = FALSE;
// m_bRBtnPressed = FALSE;
m_nRBtnStatus = BTN_NORMAL;
Invalidate();
}
}
break;
case TIMERID_SCROLLBAR:
// if (m_bSBPressed)
{
if (m_rcSBThumb.PtInRect(MousePoint))
{
m_bSBPressed = FALSE;
KillTimer(100);
}
else if (m_rcScrollBar.PtInRect(MousePoint))
{
// ���������ӻ��Ǽ���
if (MousePoint.x > m_rcSBThumb.right)
{
m_dblCurVal += dblAdd * 2;
}
else if (MousePoint.x < m_rcSBThumb.left)
{
m_dblCurVal -= dblAdd * 2;
}
if (m_dblCurVal >= m_dblMax)
{
m_dblCurVal = m_dblMax;
}
if (m_dblCurVal <= m_dblMin)
{
m_dblCurVal = m_dblCurVal;
}
bSndMsg = TRUE;
Invalidate();
}
}
break;
}
if (bSndMsg)
{
SendMsgToParentWnd();
}
CWnd::OnTimer(nIDEvent);
}
void CScrollBarEx::OnLButtonDblClk(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
OnLButtonDown(nFlags, point);
// CWnd::OnLButtonDblClk(nFlags, point);
}
void CScrollBarEx::SendMsgToParentWnd()
{
CWnd *pWnd = GetParent();
::SendMessage(pWnd->m_hWnd, WM_SCROLLBAR_MSG, (WPARAM)GetDlgCtrlID(), (LPARAM)&m_dblCurVal);
}
BOOL CScrollBarEx::OnEraseBkgnd(CDC* pDC)
{
// TODO: Add your message handler code here and/or call default
return TRUE;
return CWnd::OnEraseBkgnd(pDC);
}
UINT CScrollBarEx::OnGetDlgCode()
{
// TODO: Add your message handler code here and/or call default
return DLGC_WANTARROWS;
return CWnd::OnGetDlgCode();
}
void CScrollBarEx::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
// TODO: Add your message handler code here and/or call default
double dblAdd = (m_dblMax - m_dblMin) * 0.01;
if (dblAdd > 1)
{
dblAdd = 1;
}
if (nChar == VK_LEFT)
{
m_dblCurVal -= dblAdd;
if (m_dblCurVal <= m_dblMin)
{
m_dblCurVal = m_dblMin;
}
}
else if (nChar == VK_RIGHT)
{
m_dblCurVal += dblAdd;
if (m_dblCurVal >= m_dblMax)
{
m_dblCurVal = m_dblMax;
}
}
SendMsgToParentWnd();
Invalidate();
CWnd::OnKeyDown(nChar, nRepCnt, nFlags);
}