CEditNumber adalah kelas turunan dari CEdit. Ditujukan agar input hanya bisa menerima angka, tanda minus dan separator desimal. Pun ada auto format dengan menggunakan local regional setting pada windows.
EditNumber.h
#if !defined(AFX_EDITNUMBER_H__1F33E9E6_0079_4051_B3F1_A592F3E8F186__INCLUDED_)
#define AFX_EDITNUMBER_H__1F33E9E6_0079_4051_B3F1_A592F3E8F186__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
// EditNumber.h : header file
//
/////////////////////////////////////////////////////////////////////////////
// CEditNumber window
class CEditNumber : public CEdit
{
// Construction
public:
CEditNumber();
// Attributes
public:
// Operations
public:
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CEditNumber)
public:
virtual BOOL PreTranslateMessage(MSG* pMsg);
//}}AFX_VIRTUAL
// Implementation
void SetDecimanLength(UINT pr_ndec);
void SetCNumberString(const char* p);
void GetCNumberString(CString& p);
static void NumberFormat(CString& res, char sep_dec, int n_dec, char sep_thousand, const char* val);
public:
virtual ~CEditNumber();
// Generated message map functions
protected:
//{{AFX_MSG(CEditNumber)
afx_msg void OnKillFocus(CWnd* pNewWnd);
afx_msg void OnSetFocus(CWnd* pOldWnd);
afx_msg void OnChange();
afx_msg void OnChar(UINT nChar, UINT nRepCnt, UINT nFlags);
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
private:
char m_dec;
char m_thousand;
UINT n_dec;
};
/////////////////////////////////////////////////////////////////////////////
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_EDITNUMBER_H__1F33E9E6_0079_4051_B3F1_A592F3E8F186__INCLUDED_)
EditNumber.cpp
// EditNumber.cpp : implementation file
//
#include "stdafx.h"
#include "stdataadmin.h"
#include "EditNumber.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CEditNumber
CEditNumber::CEditNumber()
{
char dec[10];
if (! GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SDECIMAL, dec, 10)) {
sprintf(dec, ".");
}
m_dec = *dec;
char thousand[10];
if (! GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_STHOUSAND, thousand, 10)) {
sprintf(thousand, ",");
}
m_thousand = *thousand;
n_dec = 4;
}
CEditNumber::~CEditNumber()
{
}
BEGIN_MESSAGE_MAP(CEditNumber, CEdit)
//{{AFX_MSG_MAP(CEditNumber)
ON_WM_KILLFOCUS()
ON_WM_SETFOCUS()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CEditNumber message handlers
BOOL CEditNumber::PreTranslateMessage(MSG* pMsg)
{
// TODO: Add your specialized code here and/or call the base class
if (pMsg->message == WM_CHAR) {
int nVirtKey = (int) pMsg->wParam;
if ((nVirtKey >= 32) && (nVirtKey <= 126)) {
UINT maxlen = GetLimitText();
char* buf = (char* ) malloc (maxlen+2);
GetWindowText(buf, maxlen+1);
if (nVirtKey == m_dec) {
if (strchr(buf, m_dec)) {
pMsg->wParam = 0;
}
}
else
if (nVirtKey == '-') {
if ((strlen(buf) > 0) && (*buf == '-')) {
pMsg->wParam = 0;
}
else {
CPoint p = GetCaretPos();
int n = CharFromPos(p);
int nLineIndex = HIWORD(n);
int nCharIndex = LOWORD(n);
if (nCharIndex > 0) {
pMsg->wParam = 0;
}
}
}
else
if (nVirtKey == '0') {
if (strlen(buf)) {
if (*buf != m_dec) {
CPoint p = GetCaretPos();
int n = CharFromPos(p);
int nLineIndex = HIWORD(n);
int nCharIndex = LOWORD(n);
if (nCharIndex == 0) {
pMsg->wParam = 0;
}
else
if (nCharIndex == 1) {
if ((*buf == '-') || (*buf == '0')) {
pMsg->wParam = 0;
}
}
}
}
}
else
if (nVirtKey < '0') {
pMsg->wParam = 0;
}
else
if (nVirtKey > '9') {
pMsg->wParam = 0;
}
free(buf);
}
}
return CEdit::PreTranslateMessage(pMsg);
}
void CEditNumber::OnKillFocus(CWnd* pNewWnd)
{
CEdit::OnKillFocus(pNewWnd);
// TODO: Add your message handler code here
CString ret;
GetWindowText(ret);
NumberFormat(ret, m_dec, n_dec, m_thousand, ret.GetBuffer(0));
SetWindowText(ret.GetBuffer(0));
}
void CEditNumber::SetDecimanLength(UINT pr_ndec) {
n_dec = pr_ndec;
}
void CEditNumber::NumberFormat(CString& res, char sep_dec, int n_dec, char sep_thousand, const char* val) {
if (n_dec < 0) return;
CString s = CString(val); // satuan tanpa separator
CString dec = CString(""); // decimal
s.TrimLeft(" ");
s.TrimRight(" ");
if (s.GetLength() == 0) {
res = "0";
res += sep_dec;
for(int i=0; i < n_dec; i++) {
res += "0";
}
return;
}
// pisahkan satuan dan decimal
int pos = s.Find(sep_dec, 0);
if (pos > -1) {
dec = s.Right(s.GetLength()-pos-1);
s = s.Left(pos);
}
// chek panjang n_dec
if (dec.GetLength() > n_dec) {
dec = dec.Left(n_dec);
}
else
while (dec.GetLength() < n_dec) {
dec += "0";
}
// tambahkan sep_dec
res = "";
if (sep_thousand == 0) {
res = s;
}
else
while(1) {
if (s.GetLength() < 3) {
res.Insert(0, s.Right(s.GetLength()));
break;
}
res.Insert(0, s.Right(3));
if (s.GetLength() > 3) {
res.Insert(0, sep_thousand);
}
s = s.Left(s.GetLength()-3);
}
if (n_dec > 0) {
res.Insert(res.GetLength(), sep_dec);
res.Insert(res.GetLength(), dec);
}
}
void CEditNumber::OnSetFocus(CWnd* pOldWnd)
{
CEdit::OnSetFocus(pOldWnd);
// TODO: Add your message handler code here
UINT maxlen = GetLimitText();
CString s;
GetWindowText(s);
char temp[2];
sprintf(temp,"%c", m_thousand);
s.Replace(temp, "");
int ndec = maxlen-s.GetLength();
if (ndec > ((int) n_dec)) {
ndec = n_dec;
}
else
if (ndec < 0) {
ndec = 0;
}
NumberFormat(s, m_dec, ndec, 0, s.GetBuffer(0));
SetWindowText(s.GetBuffer(0));
}
void CEditNumber::SetCNumberString(const char* p) {
char temp[2];
sprintf(temp,"%c", m_dec);
CString s;
s.Replace(".", temp);
NumberFormat(s, m_dec, n_dec, m_thousand, p);
SetWindowText(s.GetBuffer(0));
}
void CEditNumber::GetCNumberString(CString& p) {
GetWindowText(p);
char temp[2];
sprintf(temp,"%c", m_thousand);
p.Replace(temp, "");
sprintf(temp,"%c", m_dec);
p.Replace(temp, ".");
}

Comments 1
??
Posted 22 Aug 2008 at 8:00 am ¶Post a Comment