1 // SpinEdit.cpp: 实现文件
2 //
3
4 #include "stdafx.h"
5 #include "SpinEdit.h"
6
7 #define SPIN_ID 3100
8 // CSpinEdit
9
IMPLEMENT_DYNAMIC(CSpinEdit,CEdit)10 IMPLEMENT_DYNAMIC(CSpinEdit, CEdit)
11
12 CSpinEdit::CSpinEdit()
13 {
14
15 }
16
~CSpinEdit()17 CSpinEdit::~CSpinEdit()
18 {
19 }
20
SetRange(short lower,short upper,short step)21 void CSpinEdit::SetRange(short lower, short upper, short step)
22 {
23 m_step = step;
24 if (m_spin.GetSafeHwnd() != NULL)
25 m_spin.SetRange(lower, upper);
26 }
27
SetValue(int value)28 void CSpinEdit::SetValue(int value)
29 {
30 ASSERT(m_step != 0); // 应当先设置Range
31 if (m_spin.GetSafeHwnd() != NULL)
32 m_spin.SetPos(value);
33 }
34
GetValue()35 int CSpinEdit::GetValue()
36 {
37 if (m_spin.GetSafeHwnd() != NULL)
38 return m_spin.GetPos();
39 else
40 return 0;
41 }
42
43
SetMouseWheelEnable(bool enable)44 void CSpinEdit::SetMouseWheelEnable(bool enable)
45 {
46 m_mouse_wheel_enable = enable;
47 }
48
49
BEGIN_MESSAGE_MAP(CSpinEdit,CEdit)50 BEGIN_MESSAGE_MAP(CSpinEdit, CEdit)
51 ON_MESSAGE(WM_TABLET_QUERYSYSTEMGESTURESTATUS, &CSpinEdit::OnTabletQuerysystemgesturestatus)
52 ON_NOTIFY(UDN_DELTAPOS, SPIN_ID, &CSpinEdit::OnDeltaposSpin)
53 ON_WM_KILLFOCUS()
54 ON_WM_ENABLE()
55 ON_WM_SIZE()
56 END_MESSAGE_MAP()
57
58
59
60 // CSpinEdit 消息处理程序
61
62 void CSpinEdit::PreSubclassWindow()
63 {
64 // TODO: 在此添加专用代码和/或调用基类
65
66 // 要求文本左对齐,右侧会被spin控件覆盖
67 // WS_CLIPCHILDREN在绘制中排除子窗口区域,避免重叠的控件绘制闪烁
68 ModifyStyle(ES_CENTER | ES_RIGHT, ES_LEFT | WS_CLIPCHILDREN);
69 // 将spin创建为edit的子控件,因为CTabDlg不一定能正常滚动动态创建的子控件(Spin)
70 // 准确的说是CWnd::ScrollWindow在窗口可见/不可见时对动态创建的子控件移动行为不一致(多半是这样)(具体参考wincore.cpp的实现)(在CTabDlg::OnTabEntered随意滚一下再滚回来窗口就能正常)
71 // 我试着在这里保持与edit为兄弟关系的spin始终跟随edit但没有成功,只好将spin作为edit的子控件(子窗口受限于父窗口的ClientRect所以不能使用UDS_ALIGNRIGHT)
72 m_spin.Create(WS_CHILD | WS_VISIBLE | UDS_ARROWKEYS | UDS_HOTTRACK | UDS_SETBUDDYINT, CRect(), this, SPIN_ID);
73 // 获取spin控件宽度
74 CRect rect;
75 m_spin.GetWindowRect(&rect);
76 m_spin_width = rect.Width();
77 // 设置spin控件区域(作为CEdit的子控件,ClientRect区域外的部分会被裁剪)
78 GetClientRect(&rect);
79 rect.left = rect.right - m_spin_width;
80 m_spin.MoveWindow(&rect);
81 // 设置Edit控件为关联控件
82 m_spin.SetBuddy(this);
83 // 设置默认范围
84 m_spin.SetRange(0, 999);
85 CEdit::PreSubclassWindow();
86 }
87
88
PreTranslateMessage(MSG * pMsg)89 BOOL CSpinEdit::PreTranslateMessage(MSG* pMsg)
90 {
91 // TODO: 在此添加专用代码和/或调用基类
92
93 //如果m_mouse_wheel_enable为false,则不响应鼠标滚轮消息
94 if (pMsg->message == WM_MOUSEWHEEL && !m_mouse_wheel_enable)
95 {
96 //将鼠标滚轮消息发送给父窗口
97 CWnd* pParent = GetParent();
98 pParent->SendMessage(WM_MOUSEWHEEL, pMsg->wParam, pMsg->lParam);
99 return true;
100 }
101
102 return CEdit::PreTranslateMessage(pMsg);
103 }
104
105
OnTabletQuerysystemgesturestatus(WPARAM wParam,LPARAM lParam)106 afx_msg LRESULT CSpinEdit::OnTabletQuerysystemgesturestatus(WPARAM wParam, LPARAM lParam)
107 {
108 return 0;
109 }
110
111
OnDeltaposSpin(NMHDR * pNMHDR,LRESULT * pResult)112 void CSpinEdit::OnDeltaposSpin(NMHDR* pNMHDR, LRESULT* pResult)
113 {
114 //这里响应微调按钮(spin button)点击上下按钮时的事件
115 LPNMUPDOWN pNMUpDown = reinterpret_cast<LPNMUPDOWN>(pNMHDR);
116
117 int value = GetValue();
118 value += pNMUpDown->iDelta * m_step;
119 value /= m_step;
120 value *= m_step;
121 SetValue(value);
122 pNMUpDown->iDelta = 0;
123 *pResult = 0;
124 }
125
126
OnKillFocus(CWnd * pNewWnd)127 void CSpinEdit::OnKillFocus(CWnd* pNewWnd)
128 {
129 CEdit::OnKillFocus(pNewWnd);
130
131 // TODO: 在此处添加消息处理程序代码
132 CString str;
133 GetWindowTextW(str);
134 int value = _ttoi(str.GetString());
135 SetValue(value); // m_spin会检查并限制值范围以及更新CEdit控件文本
136 }
137
138
OnEnable(BOOL bEnable)139 void CSpinEdit::OnEnable(BOOL bEnable)
140 {
141 CEdit::OnEnable(bEnable);
142 m_spin.EnableWindow(bEnable);
143 }
144
145
OnSize(UINT nType,int cx,int cy)146 void CSpinEdit::OnSize(UINT nType, int cx, int cy)
147 {
148 CEdit::OnSize(nType, cx, cy);
149 CRect rect;
150 GetClientRect(&rect);
151 rect.left = rect.right - m_spin_width;
152 m_spin.MoveWindow(&rect);
153 }
154