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)