优化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;
}