zoukankan      html  css  js  c++  java
  • CDateTimeUI类源码分析

    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的初始日期。

  • 相关阅读:
    Java 8与Runtime.getRuntime().availableProcessors()
    nginx配置
    周末完成工作小结
    CentOS 8 安装MySQL 8.0
    centOS8网络获取不了
    IUAP平台新增菜单存储过程
    centOS8安装Docker
    Mybatis里用到的设计模式
    2020,回顾过往,展望未来
    使用 Apache SSI(Server Side Includes) 制作多语言版静态网页
  • 原文地址:https://www.cnblogs.com/Reyzal/p/5137240.html
Copyright © 2011-2022 走看看