CDateTimeUI是duilib里选择日期的控件,继承于CLabelUI控件,用于记录已经选择的日期,选择控件则是调用win32的日期选择控件。
CDateTimeUI包含两个类,一个是CDateTimeUI,另一个是CDateTimeWnd。
CDateTimeWnd是创建win32日期控件的类,父类是CWindowWnd。
实现代码如下:
#define DT_NONE 0 #define DT_UPDATE 1 #define DT_DELETE 2 #define DT_KEEP 3 class CDateTimeWnd : public CWindowWnd { public: CDateTimeWnd(); void Init(CDateTimeUI* pOwner); RECT CalPos(); LPCTSTR GetWindowClassName() const; LPCTSTR GetSuperClassName() const; void OnFinalMessage(HWND hWnd); LRESULT HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam); LRESULT OnKillFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled); protected: CDateTimeUI* m_pOwner; HBRUSH m_hBkBrush; bool m_bInit; }; CDateTimeWnd::CDateTimeWnd() : m_pOwner(NULL), m_hBkBrush(NULL), m_bInit(false) { } void CDateTimeWnd::Init(CDateTimeUI* pOwner) { m_pOwner = pOwner; m_pOwner->m_nDTUpdateFlag = DT_NONE; if (m_hWnd == NULL) { RECT rcPos = CalPos(); UINT uStyle = WS_CHILD; Create(m_pOwner->GetManager()->GetPaintWindow(), NULL, uStyle, 0, rcPos); SetWindowFont(m_hWnd, m_pOwner->GetManager()->GetFontInfo(m_pOwner->GetFont())->hFont, TRUE); } if (m_pOwner->GetText().IsEmpty()) ::GetLocalTime(&m_pOwner->m_sysTime); ::SendMessage(m_hWnd, DTM_SETSYSTEMTIME, 0, (LPARAM)&m_pOwner->m_sysTime); ::ShowWindow(m_hWnd, SW_SHOWNOACTIVATE); ::SetFocus(m_hWnd); m_bInit = true; } //获取控件应该显示的位置,一般是父窗口的位置,如果父窗口不显示则当前win32日期控件也不显示 RECT CDateTimeWnd::CalPos() { CDuiRect rcPos = m_pOwner->GetPos(); CControlUI* pParent = m_pOwner; RECT rcParent; while( pParent = pParent->GetParent() ) { if( !pParent->IsVisible() ) { rcPos.left = rcPos.top = rcPos.right = rcPos.bottom = 0; break; } rcParent = pParent->GetPos(); if( !::IntersectRect(&rcPos, &rcPos, &rcParent) ) { rcPos.left = rcPos.top = rcPos.right = rcPos.bottom = 0; break; } } return rcPos; } LPCTSTR CDateTimeWnd::GetWindowClassName() const { return _T("DateTimeWnd"); } //设置控件类名 LPCTSTR CDateTimeWnd::GetSuperClassName() const { return DATETIMEPICK_CLASS; } void CDateTimeWnd::OnFinalMessage(HWND /*hWnd*/) { // Clear reference and die if( m_hBkBrush != NULL ) ::DeleteObject(m_hBkBrush); m_pOwner->m_pWindow = NULL; delete this; } LRESULT CDateTimeWnd::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam) { LRESULT lRes = 0; BOOL bHandled = TRUE; if( uMsg == WM_NOTIFY) { ::SetFocus(m_hWnd); } if( uMsg == WM_KILLFOCUS ) { //失去焦点就关闭当前win32日期控件 POINT pt; ::GetCursorPos(&pt); RECT rcWnd; ::GetWindowRect(m_hWnd,&rcWnd); if( !( pt.x >= rcWnd.left && pt.x <= rcWnd.right )|| !( pt.x >= rcWnd.top && pt.x <= rcWnd.bottom )) { lRes= OnKillFocus(uMsg,wParam, lParam,bHandled); } } else if (uMsg == WM_KEYUP && (wParam == VK_ESCAPE)) { //esc键按下则不保存当前已选择的日期 LRESULT lRes = ::DefWindowProc(m_hWnd, uMsg, wParam, lParam); m_pOwner->m_nDTUpdateFlag = DT_KEEP; PostMessage(WM_CLOSE); return lRes; } else if (uMsg == WM_KEYUP && (wParam == VK_RETURN)) { //回车键按下就当做失去焦点处理 PostMessage(WM_KILLFOCUS); return 0; } else bHandled = FALSE; if( !bHandled ) return CWindowWnd::HandleMessage(uMsg, wParam, lParam); return lRes; } LRESULT CDateTimeWnd::OnKillFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { LRESULT lRes = ::DefWindowProc(m_hWnd, uMsg, wParam, lParam); if (m_pOwner->m_nDTUpdateFlag == DT_NONE) { ::SendMessage(m_hWnd, DTM_GETSYSTEMTIME, 0, (LPARAM)&m_pOwner->m_sysTime); m_pOwner->m_nDTUpdateFlag = DT_UPDATE; m_pOwner->UpdateText(); } PostMessage(WM_CLOSE); return lRes; }
此类Init代码用来显示win32日期控件,创建一个大小和CDateTimeUI大小一样的控件显示在CDateTimeUI上面。当此控件失去焦点后将选择的日期显示在CDateTimeUI控件上。
CDateTimeUI控件继承于CLabelUI。
头文件:
/// 时间选择控件 class UILIB_API CDateTimeUI : public CLabelUI { friend class CDateTimeWnd; public: CDateTimeUI(); LPCTSTR GetClass() const; LPVOID GetInterface(LPCTSTR pstrName); SYSTEMTIME& GetTime(); void SetTime(SYSTEMTIME* pst); void SetReadOnly(bool bReadOnly); bool IsReadOnly() const; void UpdateText(); void DoEvent(TEventUI& event); protected: SYSTEMTIME m_sysTime; int m_nDTUpdateFlag; bool m_bReadOnly; CDateTimeWnd* m_pWindow; };
源文件:
// // CDateTimeUI::CDateTimeUI() { ::GetLocalTime(&m_sysTime); m_bReadOnly = false; m_pWindow = NULL; m_nDTUpdateFlag=DT_UPDATE; UpdateText(); m_nDTUpdateFlag = DT_NONE; } LPCTSTR CDateTimeUI::GetClass() const { return _T("DateTimeUI"); } LPVOID CDateTimeUI::GetInterface(LPCTSTR pstrName) { if( _tcscmp(pstrName, DUI_CTR_DATETIME) == 0 ) return static_cast<CDateTimeUI*>(this); return CLabelUI::GetInterface(pstrName); } SYSTEMTIME& CDateTimeUI::GetTime() { return m_sysTime; } void CDateTimeUI::SetTime(SYSTEMTIME* pst) { m_sysTime = *pst; Invalidate(); } void CDateTimeUI::SetReadOnly(bool bReadOnly) { m_bReadOnly = bReadOnly; Invalidate(); } bool CDateTimeUI::IsReadOnly() const { return m_bReadOnly; } void CDateTimeUI::UpdateText() { if (m_nDTUpdateFlag == DT_DELETE) SetText(_T("")); else if (m_nDTUpdateFlag == DT_UPDATE) { CDuiString sText; sText.SmallFormat(_T("%4d-%02d-%02d"), m_sysTime.wYear, m_sysTime.wMonth, m_sysTime.wDay, m_sysTime.wHour, m_sysTime.wMinute); SetText(sText); } } void CDateTimeUI::DoEvent(TEventUI& event) { if( !IsMouseEnabled() && event.Type > UIEVENT__MOUSEBEGIN && event.Type < UIEVENT__MOUSEEND ) { if( m_pParent != NULL ) m_pParent->DoEvent(event); else CLabelUI::DoEvent(event); return; } if( event.Type == UIEVENT_SETCURSOR && IsEnabled() ) { ::SetCursor(::LoadCursor(NULL, MAKEINTRESOURCE(IDC_IBEAM))); return; } if( event.Type == UIEVENT_WINDOWSIZE ) { if( m_pWindow != NULL ) m_pManager->SetFocusNeeded(this); } if( event.Type == UIEVENT_SCROLLWHEEL ) { if( m_pWindow != NULL ) return; } if( event.Type == UIEVENT_SETFOCUS && IsEnabled() ) { //有焦点了就显示日期选择窗口 if( m_pWindow ) return; m_pWindow = new CDateTimeWnd(); ASSERT(m_pWindow); m_pWindow->Init(this); m_pWindow->ShowWindow(); } if( event.Type == UIEVENT_KILLFOCUS && IsEnabled() ) { Invalidate(); } if( event.Type == UIEVENT_BUTTONDOWN || event.Type == UIEVENT_DBLCLICK || event.Type == UIEVENT_RBUTTONDOWN) { //鼠标按下就显示日期选择窗口 if( IsEnabled() ) { GetManager()->ReleaseCapture(); if( IsFocused() && m_pWindow == NULL ) { m_pWindow = new CDateTimeWnd(); ASSERT(m_pWindow); } if( m_pWindow != NULL ) { m_pWindow->Init(this); m_pWindow->ShowWindow(); } } return; } if( event.Type == UIEVENT_MOUSEMOVE ) { return; } if( event.Type == UIEVENT_BUTTONUP ) { return; } if( event.Type == UIEVENT_CONTEXTMENU ) { return; } if( event.Type == UIEVENT_MOUSEENTER ) { return; } if( event.Type == UIEVENT_MOUSELEAVE ) { return; } CLabelUI::DoEvent(event); }
当控件获得焦点时则调用CDateTimeWnd类,然后显示出来,根据控件内的文字设置CDateTimeWnd的初始日期。