CDateTimeCtrl编辑短年格式

时间:2015-05-05 07:05:00

标签: c++ mfc

如果CDateTimeCtrl的格式设置为“dd.MM.yy”,则日期控件在运行时以“05.05.15”格式正确显示日期

但是如果用户将光标放入控件的年份部分, 年份从“15”切换到“2015”

通过离开年度部分(例如将光标放在日期部分),它会从“2015”重新更改为“15”

是否有可能暂停此活动?

年份部分应始终保持2位数。

1 个答案:

答案 0 :(得分:1)

我认为必须从CDateTimeCtrl推导出这种行为。

实现显示非常简单。 我已经实现了CDateTimeCtrl2Digit来代替标准组件,就像你要做的样本一样。编辑更复杂,我只是一个非常简单的。

CDateTimeCtrl2Digit m_DateTime;
m_DateTime.SetFormat( _T("dd.MM.XX"));

格式XX由CDateTimeCtrl2Digitas作为回调字段管理:

来自MSDN:

  

回调字段除标准格式字符串和正文外   在文本中,您还可以将显示的某些部分定义为Callback   领域。这些字段可用于向用户查询信息。至   声明一个回调字段,包含一个或多个" X"字符(ASCII   代码88)格式字符串中的任何位置。您可以创建回调字段   通过重复" X"具有独特的身份。字符。就这样   格式字符串" XX dddd MMM dd',' yyy XXX"包含两个独特的回调   领域," XX"和" XXX"。与其他DTP控制字段一样,回调字段   根据它们在中的位置以从左到右的顺序显示   格式字符串。当DTP控件解析格式字符串时   遇到一个回调字段,它发送DTN_FORMAT和DTN_FORMATQUERY   通知代码。对应的格式字符串元素   回调字段包含在通知中以允许   接收应用程序以确定正在使用哪个回调字段   查询。控件的所有者必须响应这些通知   确保正确显示自定义信息。

因此,您必须处理此回调字段以显示年份的两位数和所有特殊编辑。 这是一个部分工作的样本:我的意思是所有编辑都缺失,这里是一个非常简单的编辑(我不处理箭头键,只处理数字)。

我在stackoverflow中发布代码非常新,所以请原谅我,如果有100%的工作只需复制并粘贴我写的东西!!!

但这就是我所做的:

class CDateTimeCtrl2Digit : public CDateTimeCtrl
{
    DECLARE_DYNAMIC(CDateTimeCtrl2Digit )
public:
    CDateTimeCtrl2Digit ();
    virtual ~CDateTimeCtrl2Digit ();

protected:
    int nDigit;
    DECLARE_MESSAGE_MAP()
public:
    afx_msg void OnDtnFormat(NMHDR *pNMHDR, LRESULT *pResult);
    afx_msg void OnDtnFormatquery(NMHDR *pNMHDR, LRESULT *pResult);
    afx_msg void OnDtnWmkeydown(NMHDR *pNMHDR, LRESULT *pResult);
};

和.cpp

#include "stdafx.h"
#include "MFCApplication1.h"
#include "DateTimeCtrl2Digit.h"

#define GetWindowFont(hwnd) FORWARD_WM_GETFONT((hwnd), SNDMSG)
#define FORWARD_WM_GETFONT(hwnd, fn) (HFONT)(UINT_PTR)(fn)((hwnd), WM_GETFONT, 0L, 0L)

IMPLEMENT_DYNAMIC(CDateTimeCtrl2Digit , CDateTimeCtrl)

CDateTimeCtrl2Digit ::CDateTimeCtrl2Digit ()
{
    nDigit = 0;
}

CDateTimeCtrl2Digit ::~CDateTimeCtrl2Digit ()
{
}

BEGIN_MESSAGE_MAP(CDateTimeCtrl2Digit , CDateTimeCtrl)
    ON_NOTIFY_REFLECT(DTN_FORMAT, &CDateTimeCtrl2Digit::OnDtnFormat)
    ON_NOTIFY_REFLECT(DTN_FORMATQUERY, &CDateTimeCtrl2Digit::OnDtnFormatquery)
    ON_NOTIFY_REFLECT(DTN_WMKEYDOWN, &CDateTimeCtrl2Digit::OnDtnWmkeydown)
END_MESSAGE_MAP()

void CDateTimeCtrl2Digit ::OnDtnFormat(NMHDR *pNMHDR, LRESULT *pResult)
{
    LPNMDATETIMEFORMAT pDTFormat = reinterpret_cast<LPNMDATETIMEFORMAT>(pNMHDR);

    COleDateTime dt;
    CDateTimeCtrl::GetTime(dt);
    CString year = dt.Format(_T("%y"));
    _tcscpy_s( pDTFormat->szDisplay, year);

    *pResult = 0;
}

void CDateTimeCtrl2Digit ::OnDtnFormatquery(NMHDR *pNMHDR, LRESULT *pResult)
{
    LPNMDATETIMEFORMATQUERY pDTFmtQuery = reinterpret_cast<LPNMDATETIMEFORMATQUERY>(pNMHDR);

    HDC hdc;
    HFONT hFont, hOrigFont;
    hdc = ::GetDC(m_hWnd);
    hFont = FORWARD_WM_GETFONT(m_hWnd, ::SendMessage);
    if(!hFont) hFont = (HFONT)::GetStockObject(DEFAULT_GUI_FONT);
    hOrigFont = (HFONT)::SelectObject(hdc, hFont);
    ::GetTextExtentPoint32 (hdc, _T("88"), 2, &pDTFmtQuery->szMax);
    ::SelectObject(hdc,hOrigFont);
    ::ReleaseDC(m_hWnd, hdc);

    *pResult = 0;
}

void CMyDateTimeCtrl::OnDtnWmkeydown(NMHDR *pNMHDR, LRESULT *pResult)
{
    COleDateTime oCurTime;
    GetTime(oCurTime);
    int century = static_cast<int>( oCurTime.GetYear() / 100 ) * 100;
    int decade = oCurTime.GetYear() - century;
    LPNMDATETIMEWMKEYDOWN pDTKeyDown = reinterpret_cast<LPNMDATETIMEWMKEYDOWN>(pNMHDR);
    if( ( pDTKeyDown->nVirtKey >= 48 ) && ( pDTKeyDown->nVirtKey <= 57 ) )
    {
        if( nDigit == 0 )
        {
            nDigit = 1;
            pDTKeyDown->st.wYear = century + pDTKeyDown->nVirtKey - 48;
        }
        else 
        {
            nDigit = 0;
            pDTKeyDown->st.wYear = century + decade * 10 + pDTKeyDown->nVirtKey - 48;
        }
    }

    *pResult = 0;
}