Windows/MFC
CNiceSliderCtrl
aucd29
2013. 10. 2. 18:14
[code]#include "stdafx.h"
#include "NiceSlider.h"
IMPLEMENT_DYNAMIC(CNiceSliderCtrl, CSliderCtrl)
BEGIN_MESSAGE_MAP(CNiceSliderCtrl, CSliderCtrl)
//{{AFX_MSG_MAP(CNiceSliderCtrl)
ON_WM_LBUTTONDOWN()
ON_WM_MOUSEMOVE()
ON_WM_LBUTTONUP()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
void CNiceSliderCtrl::OnLButtonDown(UINT nFlags, CPoint point)
{
m_bDragging = true;
m_bDragChanged = false;
SetCapture();
SetFocus();
if (SetThumb(point))
{
m_bDragChanged = true;
PostMessageToParent(TB_THUMBTRACK);
}
/*CString szTest;
szTest.Format(L"%d", GetPos());
AfxMessageBox(szTest);*/
}
void CNiceSliderCtrl::OnMouseMove(UINT nFlags, CPoint point)
{
if (m_bDragging)
{
if (SetThumb(point))
{
m_bDragChanged = true;
PostMessageToParent(TB_THUMBTRACK);
}
}
else
{
CSliderCtrl::OnMouseMove(nFlags, point);
}
}
void CNiceSliderCtrl::OnLButtonUp(UINT nFlags, CPoint point)
{
if(m_bDragging)
{
m_bDragging = false;
::ReleaseCapture();
if (SetThumb(point))
{
PostMessageToParent(TB_ENDTRACK);
m_bDragChanged = true;
}
if (m_bDragChanged)
{
PostMessageToParent(TB_THUMBPOSITION);
m_bDragChanged = false;
}
}
else
{
CSliderCtrl::OnLButtonUp(nFlags, point);
}
}
bool CNiceSliderCtrl::SetThumb(const CPoint& point)
{
const int nMin = GetRangeMin();
const int nMax = GetRangeMax()+1;
CRect rc;
GetChannelRect(rc);
double dPos;
double dCorrectionFactor = 0.0;
if (GetStyle() & TBS_VERT)
{
// note: there is a bug in GetChannelRect, it gets the orientation of the rectangle mixed up
dPos = (double)(point.y - rc.left)/(rc.right - rc.left);
}
else
{
dPos = (double)(point.x - rc.left)/(rc.right - rc.left);
}
// This correction factor is needed when you click inbetween tick marks
// so that the thumb will move to the nearest one
dCorrectionFactor = 0.5 *(1-dPos) - 0.5 *dPos;
int nNewPos = (int)(nMin + (nMax-nMin)*dPos + dCorrectionFactor);
const bool bChanged = (nNewPos != GetPos());
if(bChanged)
{
SetPos(nNewPos);
}
return bChanged;
}
void CNiceSliderCtrl::PostMessageToParent(const int nTBCode) const
{
CWnd* pWnd = GetParent();
if(pWnd)
{
if(GetStyle() & TBS_VERT)
pWnd->PostMessage(WM_VSCROLL, (WPARAM)((GetPos() << 16) | nTBCode), (LPARAM)GetSafeHwnd());
else
pWnd->PostMessage(WM_HSCROLL, (WPARAM)((GetPos() << 16) | nTBCode), (LPARAM)GetSafeHwnd());
}
}
[/code]
[code]
#ifndef NiceSlider_h
#define NiceSlider_h
// Class that provides better mouse click handling for the standard windows slider control
class CNiceSliderCtrl : public CSliderCtrl
{
public:
DECLARE_DYNAMIC(CNiceSliderCtrl)
CNiceSliderCtrl() : m_bDragging(false), m_bDragChanged(false) {}
protected:
//{{AFX_MSG(CRoundSliderCtrl)
afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
afx_msg void OnMouseMove(UINT nFlags, CPoint point);
afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
private:
bool SetThumb(const CPoint& pt);
void PostMessageToParent(const int nTBCode) const;
bool m_bDragging;
bool m_bDragChanged;
};
#endif // NiceSlider_h
[/code]
#include "NiceSlider.h"
IMPLEMENT_DYNAMIC(CNiceSliderCtrl, CSliderCtrl)
BEGIN_MESSAGE_MAP(CNiceSliderCtrl, CSliderCtrl)
//{{AFX_MSG_MAP(CNiceSliderCtrl)
ON_WM_LBUTTONDOWN()
ON_WM_MOUSEMOVE()
ON_WM_LBUTTONUP()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
void CNiceSliderCtrl::OnLButtonDown(UINT nFlags, CPoint point)
{
m_bDragging = true;
m_bDragChanged = false;
SetCapture();
SetFocus();
if (SetThumb(point))
{
m_bDragChanged = true;
PostMessageToParent(TB_THUMBTRACK);
}
/*CString szTest;
szTest.Format(L"%d", GetPos());
AfxMessageBox(szTest);*/
}
void CNiceSliderCtrl::OnMouseMove(UINT nFlags, CPoint point)
{
if (m_bDragging)
{
if (SetThumb(point))
{
m_bDragChanged = true;
PostMessageToParent(TB_THUMBTRACK);
}
}
else
{
CSliderCtrl::OnMouseMove(nFlags, point);
}
}
void CNiceSliderCtrl::OnLButtonUp(UINT nFlags, CPoint point)
{
if(m_bDragging)
{
m_bDragging = false;
::ReleaseCapture();
if (SetThumb(point))
{
PostMessageToParent(TB_ENDTRACK);
m_bDragChanged = true;
}
if (m_bDragChanged)
{
PostMessageToParent(TB_THUMBPOSITION);
m_bDragChanged = false;
}
}
else
{
CSliderCtrl::OnLButtonUp(nFlags, point);
}
}
bool CNiceSliderCtrl::SetThumb(const CPoint& point)
{
const int nMin = GetRangeMin();
const int nMax = GetRangeMax()+1;
CRect rc;
GetChannelRect(rc);
double dPos;
double dCorrectionFactor = 0.0;
if (GetStyle() & TBS_VERT)
{
// note: there is a bug in GetChannelRect, it gets the orientation of the rectangle mixed up
dPos = (double)(point.y - rc.left)/(rc.right - rc.left);
}
else
{
dPos = (double)(point.x - rc.left)/(rc.right - rc.left);
}
// This correction factor is needed when you click inbetween tick marks
// so that the thumb will move to the nearest one
dCorrectionFactor = 0.5 *(1-dPos) - 0.5 *dPos;
int nNewPos = (int)(nMin + (nMax-nMin)*dPos + dCorrectionFactor);
const bool bChanged = (nNewPos != GetPos());
if(bChanged)
{
SetPos(nNewPos);
}
return bChanged;
}
void CNiceSliderCtrl::PostMessageToParent(const int nTBCode) const
{
CWnd* pWnd = GetParent();
if(pWnd)
{
if(GetStyle() & TBS_VERT)
pWnd->PostMessage(WM_VSCROLL, (WPARAM)((GetPos() << 16) | nTBCode), (LPARAM)GetSafeHwnd());
else
pWnd->PostMessage(WM_HSCROLL, (WPARAM)((GetPos() << 16) | nTBCode), (LPARAM)GetSafeHwnd());
}
}
[/code]
[code]
#ifndef NiceSlider_h
#define NiceSlider_h
// Class that provides better mouse click handling for the standard windows slider control
class CNiceSliderCtrl : public CSliderCtrl
{
public:
DECLARE_DYNAMIC(CNiceSliderCtrl)
CNiceSliderCtrl() : m_bDragging(false), m_bDragChanged(false) {}
protected:
//{{AFX_MSG(CRoundSliderCtrl)
afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
afx_msg void OnMouseMove(UINT nFlags, CPoint point);
afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
private:
bool SetThumb(const CPoint& pt);
void PostMessageToParent(const int nTBCode) const;
bool m_bDragging;
bool m_bDragChanged;
};
#endif // NiceSlider_h
[/code]