优化duilib中的CDateTimeUI控件-修正XP下无法使用的问题

duilib没有自己实现日期时间选择控件,转而封装了系统原生控件来代替,虽不能完美解决界面美观问题,暂时解决了有无的问题。但是使用过程中,很多朋友反应在Win7以上系统是没问题的,但是在XP系统上出现无法选择日期的问题,今天抽空修复了一下,核心代码如下:

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);
	protected:
		CDateTimeUI* m_pOwner;
		HBRUSH m_hBkBrush;
		bool m_bInit;
		bool m_bDropOpen;
		SYSTEMTIME m_oldSysTime;
	};


	CDateTimeWnd::CDateTimeWnd() : m_pOwner(NULL), m_hBkBrush(NULL), m_bInit(false), m_bDropOpen(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);
		}
		memcpy(&m_oldSysTime, &m_pOwner->m_sysTime, sizeof(SYSTEMTIME));
		::SendMessage(m_hWnd, DTM_SETSYSTEMTIME, 0, (LPARAM)&m_pOwner->m_sysTime);
		::ShowWindow(m_hWnd, SW_SHOWNOACTIVATE);
		::SetFocus(m_hWnd);


		m_bInit = true;    
	}


	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->GetClientPos();
			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)
	{
		if( m_hBkBrush != NULL ) ::DeleteObject(m_hBkBrush);
		if( m_pOwner->GetManager()->IsLayered() ) {
			m_pOwner->GetManager()->RemovePaintChildWnd(hWnd);
		} 
		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_KEYDOWN && wParam == VK_ESCAPE)
		{
			memcpy(&m_pOwner->m_sysTime, &m_oldSysTime, sizeof(SYSTEMTIME));
			m_pOwner->m_nDTUpdateFlag = DT_UPDATE;
			m_pOwner->UpdateText();
			PostMessage(WM_CLOSE);
			return lRes;
		}
		else if(uMsg == OCM_NOTIFY)
		{
			NMHDR* pHeader=(NMHDR*)lParam;
			if(pHeader != NULL && pHeader->hwndFrom == m_hWnd) {
				if(pHeader->code == DTN_DATETIMECHANGE) {
					LPNMDATETIMECHANGE lpChage=(LPNMDATETIMECHANGE)lParam;
					::SendMessage(m_hWnd, DTM_GETSYSTEMTIME, 0, (LPARAM)&m_pOwner->m_sysTime);
					m_pOwner->m_nDTUpdateFlag = DT_UPDATE;
					m_pOwner->UpdateText();
				}
				else if(pHeader->code == DTN_DROPDOWN) {
					m_bDropOpen = true;


				}
				else if(pHeader->code == DTN_CLOSEUP) {
					::SendMessage(m_hWnd, DTM_GETSYSTEMTIME, 0, (LPARAM)&m_pOwner->m_sysTime);
					m_pOwner->m_nDTUpdateFlag = DT_UPDATE;
					m_pOwner->UpdateText();
					PostMessage(WM_CLOSE);
					m_bDropOpen = false;
				}
			}
			bHandled = FALSE;
		}
		else if(uMsg == WM_KILLFOCUS)
		{
			if(!m_bDropOpen) {
				PostMessage(WM_CLOSE);
			}
			bHandled = FALSE;
		}
		else if( uMsg == WM_PAINT) {
			if (m_pOwner->GetManager()->IsLayered()) {
				m_pOwner->GetManager()->AddPaintChildWnd(m_hWnd);
			}
			bHandled = FALSE;
		}
		else bHandled = FALSE;
		if( !bHandled ) return CWindowWnd::HandleMessage(uMsg, wParam, lParam);
		return lRes;
	}

把UIDateTime.cpp中的CDateTimeWnd类替换成以上代码即可解决。

好了,需要的小伙伴赶紧试试吧!

duilib开源项目圈QQ群:261675375 \ 261851826
最新代码托管地址:https://github.com/qdtroy/DuiLib_Ultimate

By Troy (QQ:656067418)

duilib 是一个基于C++的GUI库,用于构建Windows平台上的桌面应用程序。CEF(Chromium Embedded Framework)是一个开源项目,用于将Chromium引擎集成到其他应用程序,实现浏览器功能。在duilib使用CEF控件可以实现在应用程序嵌入一个内置的浏览器。 要在duilib使用CEF控件,首先需要下载CEF的二进制文件,并将相应的头文件和库文件链接到duilib项目。然后在duilibUI布局文件添加一个容器控件用来承载CEF控件,比如一个<Control>标签定义一个名为"browser"的控件。接着在C++代码通过CreateControl()方法创建CEF控件并将其添加到布局的容器控件。 在CEF控件加载网页可以通过调用LoadURL()方法来实现,比如在初始化时可以加载一个初始的网页。同时也可以通过CEF提供的接口来处理网页加载完成、前进后退等事件。另外,也可以在CEF的控件执行JavaScript代码,比如修改网页内容或者与网页交互等。 当应用程序退出时,需要通过调用CEF控件的Close()方法来释放资源并关闭CEF的相关进程。另外,需要确保在适当的时候调用CEF的资源释放方法,比如在窗口销毁前调用Shutdown()方法来释放资源。 在duilib使用CEF控件可以帮助开发者实现嵌入式浏览器功能,比如在应用程序展示在线内容或者实现基于web的功能。同时也能够与duilib的其他控件进行交互,实现更加丰富的用户体验。通过合理的使用和管理,可以让应用程序在集成CEF控件的同时保持稳定性和性能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值