旋转按钮SPIN与编辑框的联合
要使Spin与edit更好的成为伙伴关系,实现联动效应,且支持浮点型,Spin还可以以任意精度调整,重新写了这两个类,以后只要加入这两个类的头文件和源文件就可以实现联动效应了。参考大牛们的。名字忘记了,不好意思。
///NumEdit.h
#if!defined(AFX_NUMEDIT_H__7482F7FF_A479_11D2_A6A7_00600844997A__INCLUDED_)
#defineAFX_NUMEDIT_H__7482F7FF_A479_11D2_A6A7_00600844997A__INCLUDED_
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
// NumEdit.h : header file
//
/
// CNumEdit window
#ifndef CLASS_EXPORT
#defineCLASS_EXPORT
#endif
class CLASS_EXPORT CNumEdit : public CEdit
{
DECLARE_DYNAMIC(CNumEdit)
// Construction
public:
CNumEdit();
// Attributes
public:
enum{VALID = 0x00, OUT_OF_RANGE = 0x01, INVALID_CHAR = 0x02};
// Operations
public:
// Overrides
//ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CNumEdit)
//}}AFX_VIRTUAL
// Implementation
public:
virtualvoid ChangeAmount(int step);
virtualfloat GetDelta();
virtualvoid SetDelta(float delta);
virtualvoid GetRange(float &min, float &max)const;
virtualvoid SetRange(float min, float max);
virtualvoid Verbose(BOOL v);
virtualBOOL Verbose()const;
virtualint IsValid()const;
virtualint IsValid(const CString &str)const;
virtualBOOL SetValue(float val);
virtualfloat GetValue()const;
virtual~CNumEdit();
//Generated message map functions
protected:
virtualCString& ConstructFormat(CString &str, float num);
BYTEm_NumberOfNumberAfterPoint;
BOOLm_Verbose;
floatm_Delta, m_MinValue, m_MaxValue;
//{{AFX_MSG(CNumEdit)
afx_msgvoid OnChar(UINT nChar, UINT nRepCnt, UINT nFlags);
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
/
//{{AFX_INSERT_LOCATION}}
// Microsoft Developer Studio will insertadditional declarations immediately before the previous line.
#endif //!defined(AFX_NUMEDIT_H__7482F7FF_A479_11D2_A6A7_00600844997A__INCLUDED_)
///NumEdit.cpp
// NumEdit.cpp : implementation file
//
#include "stdafx.h"
#include "NumEdit.h"
#include "Float.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/
// CNumEdit
IMPLEMENT_DYNAMIC(CNumEdit, CEdit)
CNumEdit::CNumEdit()
{
m_NumberOfNumberAfterPoint= 0;
m_Verbose= FALSE;
m_MinValue= -FLT_MAX;
m_MaxValue= FLT_MAX;
m_Delta= FLT_ROUNDS;
}
CNumEdit::~CNumEdit()
{
}
BEGIN_MESSAGE_MAP(CNumEdit, CEdit)
//{{AFX_MSG_MAP(CNumEdit)
ON_WM_CHAR()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/
// CNumEdit message handlers
float CNumEdit::GetValue() const
{
floatf = 0.0f;
if(IsValid() == VALID)
{
CStringstr;
GetWindowText(str);
sscanf(str,"%f", &f);
}
returnf;
}
BOOL CNumEdit::SetValue(float val)
{
if(val > m_MaxValue || val < m_MinValue) return FALSE;
CStringstr, s;
str.Format(ConstructFormat(s,val), val);
SetWindowText(str);
returnTRUE;
}
int CNumEdit::IsValid() const//此函数不能修改数据成员
{
CStringstr;
GetWindowText(str);
intres = VALID;
floatf;
charlp[10];
if(sscanf(str, "%f%s", &f, lp) != 1) res = INVALID_CHAR;//把
if(f > m_MaxValue || f < m_MinValue) res = OUT_OF_RANGE;
if(m_Verbose && res != VALID)
{
str.Empty();
if(res & OUT_OF_RANGE) str += _T("Given value is out of range.\n");
if(res & INVALID_CHAR) str += _T("Characters must be a number.\n");
AfxMessageBox(str,MB_OK | MB_ICONSTOP);
}
returnres;
}
int CNumEdit::IsValid(const CString&str) const
{
intres = VALID;
floatf;
charlp[10];
if(sscanf(str, "%f%s", &f, lp) != 1) res = INVALID_CHAR;
if(f > m_MaxValue && f < m_MinValue) res = OUT_OF_RANGE;
if(m_Verbose && res != VALID)
{
CStringmsg;
msg.Empty();
if(res & OUT_OF_RANGE) msg += _T("Given value is out of range.\n");
if(res & INVALID_CHAR) msg += _T("Characters must be a number.\n");
AfxMessageBox(str,MB_OK | MB_ICONSTOP);
}
returnres;
}
void CNumEdit::OnChar(UINT nChar, UINTnRepCnt, UINT nFlags)
{
if(nChar == ' ') return;
floatoldValue;
oldValue= GetValue();
CEdit::OnChar(nChar,nRepCnt, nFlags);
if(IsValid() != VALID)
{
SetValue(oldValue);//把先前的字符写入框
SetSel(0,-1);//选中框里的所有内容
MSGmsg;
while(::PeekMessage(&msg, m_hWnd, WM_CHAR, WM_CHAR, PM_REMOVE));
}else
{
CStrings;
ConstructFormat(s,GetValue());
}
}
BOOL CNumEdit::Verbose() const
{
returnm_Verbose;
}
void CNumEdit::Verbose(BOOL v)
{
m_Verbose= v;
}
void CNumEdit::SetRange(float min, floatmax)
{
m_MinValue= min;
m_MaxValue= max;
}
void CNumEdit::GetRange(float & min,float & max) const
{
min= m_MinValue;
max= m_MaxValue;
}
void CNumEdit::SetDelta(float delta)
{
m_Delta= delta;
}
float CNumEdit::GetDelta()
{
returnm_Delta;
}
void CNumEdit::ChangeAmount(int step)
{
floatf = GetValue() + step * m_Delta;
if(f > m_MaxValue) f = m_MaxValue;
elseif (f < m_MinValue) f = m_MinValue;
SetValue(f);
}
CString&CNumEdit::ConstructFormat(CString &str, float num)
{
str.Format("%G",num);//%g选择以%f(小数十进制)或%e(科学计数法)输出。如何选择呢,是选择输出比较短的那个
intn = str.Find('.');//返回以0为基数的序号
if(n >= 0)
{
n= str.GetLength() - n - 1;
if(n > m_NumberOfNumberAfterPoint) m_NumberOfNumberAfterPoint = n;
}
str.Format("%%.%df",m_NumberOfNumberAfterPoint);
returnstr;
}
//NumSpinCtrl.h
#if!defined(AFX_NUMSPINCTRL_H__C2BD95A2_A482_11D2_A6A7_00600844997A__INCLUDED_)
#defineAFX_NUMSPINCTRL_H__C2BD95A2_A482_11D2_A6A7_00600844997A__INCLUDED_
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
// NumSpinCtrl.h : header file
//
/
// CNumSpinCtrl window
#include "NumEdit.h"
#ifndef CLASS_EXPORT
#defineCLASS_EXPORT
#endif
class CLASS_EXPORT CNumSpinCtrl : publicCSpinButtonCtrl
{
DECLARE_DYNAMIC(CNumSpinCtrl)
// Construction
public:
CNumSpinCtrl();
// Attributes
public:
// Operations
public:
// Overrides
//ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CNumSpinCtrl)
//}}AFX_VIRTUAL
// Implementation
public:
virtualvoid SetDelta(float delta);
virtualfloat GetDelta();
virtualvoid SetBuddy(CNumEdit *edit);
virtualCNumEdit* GetBuddy() const;
virtualvoid GetRange(float &lower, float& upper ) const;
virtualvoid SetRange(float nLower, float nUpper );
virtualfloat GetPos();
virtualvoid SetPos(float val);
virtual~CNumSpinCtrl();
//Generated message map functions
protected:
//{{AFX_MSG(CNumSpinCtrl)
afx_msgvoid OnDeltapos(NMHDR* pNMHDR, LRESULT* pResult);
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
/
//{{AFX_INSERT_LOCATION}}
// Microsoft Developer Studio will insertadditional declarations immediately before the previous line.
#endif //!defined(AFX_NUMSPINCTRL_H__C2BD95A2_A482_11D2_A6A7_00600844997A__INCLUDED_)
//NumSpinCtrl.cpp
//NumSpinCtrl.cpp : implementation file
//
#include"stdafx.h"
#include"NumSpinCtrl.h"
#ifdef_DEBUG
#definenew DEBUG_NEW
#undefTHIS_FILE
staticchar THIS_FILE[] = __FILE__;
#endif
/
//CNumSpinCtrl
IMPLEMENT_DYNAMIC(CNumSpinCtrl,CSpinButtonCtrl)
CNumSpinCtrl::CNumSpinCtrl()
{
}
CNumSpinCtrl::~CNumSpinCtrl()
{
}
BEGIN_MESSAGE_MAP(CNumSpinCtrl,CSpinButtonCtrl)
//{{AFX_MSG_MAP(CNumSpinCtrl)
ON_NOTIFY_REFLECT(UDN_DELTAPOS,OnDeltapos)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/
//CNumSpinCtrl message handlers
voidCNumSpinCtrl::SetPos(float val)
{
CSpinButtonCtrl::SetPos(500);
CNumEdit *m_Edit = GetBuddy();
if (m_Edit)
if(m_Edit->IsKindOf(RUNTIME_CLASS(CNumEdit)))
m_Edit->SetValue(val);
}
floatCNumSpinCtrl::GetPos()
{
CNumEdit *m_Edit = GetBuddy();
if (m_Edit)
if(m_Edit->IsKindOf(RUNTIME_CLASS(CNumEdit)))
returnm_Edit->GetValue();
return 0.0f;
}
voidCNumSpinCtrl::SetRange(float nLower, float nUpper)
{
CSpinButtonCtrl::SetRange(0, 1000);
CNumEdit *m_Edit = GetBuddy();
if (m_Edit)
if(m_Edit->IsKindOf(RUNTIME_CLASS(CNumEdit)))
m_Edit->SetRange(nLower,nUpper);
}
voidCNumSpinCtrl::GetRange(float & lower, float & upper) const
{
CNumEdit *m_Edit = GetBuddy();
if (m_Edit)
if(m_Edit->IsKindOf(RUNTIME_CLASS(CNumEdit)))
m_Edit->GetRange(lower,upper);
}
CNumEdit*CNumSpinCtrl::GetBuddy() const
{
return (CNumEdit*)CSpinButtonCtrl::GetBuddy();
}
voidCNumSpinCtrl::SetBuddy(CNumEdit * edit)
{
CSpinButtonCtrl::SetBuddy(edit);
if (edit)
if(edit->IsKindOf(RUNTIME_CLASS(CNumEdit)))
edit->SetValue(0.0f);
}
voidCNumSpinCtrl::OnDeltapos(NMHDR* pNMHDR, LRESULT* pResult)
{
NM_UPDOWN* pNMUpDown =(NM_UPDOWN*)pNMHDR;
// TODO: Add your control notificationhandler code here
if ((pNMUpDown->iPos <=pNMUpDown->iDelta) ||
(pNMUpDown->iPos >= 1000 -pNMUpDown->iDelta)) pNMUpDown->iPos = 500;
CNumEdit *m_Edit = GetBuddy();
if (m_Edit)
if(m_Edit->IsKindOf(RUNTIME_CLASS(CNumEdit)))
m_Edit->ChangeAmount(pNMUpDown->iDelta);
*pResult = 0;
}
floatCNumSpinCtrl::GetDelta()
{
CNumEdit *m_Edit = GetBuddy();
if (m_Edit)
if(m_Edit->IsKindOf(RUNTIME_CLASS(CNumEdit)))
returnm_Edit->GetDelta();
return 0.0f;
}
voidCNumSpinCtrl::SetDelta(float delta)
{
CNumEdit *m_Edit = GetBuddy();
if (m_Edit)
if(m_Edit->IsKindOf(RUNTIME_CLASS(CNumEdit)))
m_Edit->SetDelta(delta);
}