用Duilib界面库开发的一个日历控件
博客园精华区 原文 http://www.cnblogs.com/sunsmile/archive/2013/03/04/ningmengxiu1.html
最近应领导要求,再搞一个基于安全的办公自动化系统,基于一些考虑,需要使用C/S架构实现,估考虑使用Duilib这一免费开源的利器,在业务功能实现上,办公自动化少不了日历控件的使用,在网上寻了半天,没有好的开源的日历控件,更多的是web版的日历控件,估决定参考web版的日历控件,使用duilib实现一个winform版的日历,在网上找到的比较炫的一个日历如下:
做web开发的朋友可以在这里找到此控件:
http://www.open-open.com/ajax/ajax20091109225817.htm
下面我们使用Duilib实现winform版的日历控件:
a、将其web版的资源文件,主要是图片,下载到本地;
b、编写duilib需要使用到的xml文件,Calendar.xml;
View Code
1 23 4 885 6 7 8 249 2210 11 12 13 14 15 16 17 18 19 20 21 23 25 26 27 28 29 30 31 32 3334 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 7879 80 81 82 83 84 85 86 87
c、代码实现如下:
View Code
1 // App.cpp : Defines the entry point for the application. 2 // 3 4 #include "stdafx.h" 5 //#include "systdate.h" 6 #include7 8 class CFrameWindowWnd : public CWindowWnd, public INotifyUI 9 { 10 public: 11 CFrameWindowWnd() { }; 12 LPCTSTR GetWindowClassName() const { return _T("UIMainFrame"); }; 13 //UINT GetClassStyle() const { return UI_CLASSSTYLE_FRAME | CS_DBLCLKS; }; 14 UINT GetClassStyle() const { return CS_DBLCLKS; }; 15 void OnFinalMessage(HWND /*hWnd*/) { delete this; }; 16 17 void Init() {} 18 19 void OnPrepare() 20 { 21 ::GetLocalTime(&m_sysTime); 22 DrawCalendar(m_sysTime); 23 } 24 25 void Notify(TNotifyUI& msg) 26 { 27 if( msg.sType == _T("windowinit") ) OnPrepare(); 28 else if( msg.sType == _T("return") ) 29 { 30 m_sysTime.wYear = SetTxtYear(0); 31 m_sysTime.wMonth = GetCmbMonth(); 32 DrawCalendar(m_sysTime); 33 } 34 else if( msg.sType == _T("click") ) 35 { 36 CControlUI* pOne = static_cast (m_pm.FindControl(msg.ptMouse)); 37 if (_tcsicmp(pOne->GetClass(), _T("ButtonUI")) == 0) 38 { 39 //上一月 40 if (_tcsicmp(pOne->GetName(), _T("BTN_UP_MONTH")) == 0) 41 { 42 m_sysTime.wMonth = m_sysTime.wMonth-1 == 0 ? 12 : m_sysTime.wMonth-1; 43 DrawCalendar(m_sysTime); 44 } 45 //上一年 46 else if (_tcsicmp(pOne->GetName(), _T("BTN_UP_YEAR")) == 0) 47 { 48 m_sysTime.wYear = SetTxtYear(-1); 49 m_sysTime.wMonth = GetCmbMonth(); 50 DrawCalendar(m_sysTime); 51 } 52 //下一年 53 else if (_tcsicmp(pOne->GetName(), _T("BTN_DOWN_YEAR")) == 0) 54 { 55 m_sysTime.wYear = SetTxtYear(1); 56 m_sysTime.wMonth = GetCmbMonth(); 57 DrawCalendar(m_sysTime); 58 } 59 } 60 } 61 else if( msg.sType == _T("itemselect") ) { 62 if (_tcsicmp(msg.pSender->GetName(), _T("CMB_MONTH")) == 0) 63 { 64 m_sysTime.wMonth = GetCmbMonth(); 65 DrawCalendar(m_sysTime); 66 } 67 } 68 } 69 70 LRESULT HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam) 71 { 72 if( uMsg == WM_CREATE ) { 73 m_pm.Init(m_hWnd); 74 CDialogBuilder builder; 75 CControlUI* pRoot = builder.Create(_T("Calendar1.xml"), (UINT)0, NULL, &m_pm); 76 ASSERT(pRoot && "Failed to parse XML"); 77 m_pm.AttachDialog(pRoot); 78 m_pm.AddNotifier(this); 79 Init(); 80 return 0; 81 } 82 else if( uMsg == WM_DESTROY ) { 83 ::PostQuitMessage(0L); 84 } 85 else if( uMsg == WM_ERASEBKGND ) { 86 return 1; 87 } 88 LRESULT lRes = 0; 89 if( m_pm.MessageHandler(uMsg, wParam, lParam, lRes) ) return lRes; 90 return CWindowWnd::HandleMessage(uMsg, wParam, lParam); 91 } 92 93 //绘制日历 94 void DrawCalendar(SYSTEMTIME m_sysTime) 95 { 96 int iDay = 0; 97 char cDay[3] = {0}; 98 //int iStartDay = m_sysTime.wDayOfWeek; 99 m_sysTime.wDay = 1;100 int iStartDay = GetDayOfWeek(m_sysTime);101 //上月天数102 int iLastMonthStartDays = 31 - iStartDay;103 if(m_sysTime.wMonth>1)104 iLastMonthStartDays = GetMonthDays(m_sysTime.wYear,m_sysTime.wMonth - 1) - iStartDay;105 //本月天数106 int iMonthDays = GetMonthDays(m_sysTime.wYear,m_sysTime.wMonth);107 //下月天数108 int iNextMonthDays = 0;109 110 CControlUI* pButtonUI;111 CContainerUI* pControl = static_cast (m_pm.FindControl(_T("ContainerUI3")));112 for(int i = 0;i < 42;i++)113 {114 pButtonUI = m_pm.FindSubControlByClass(pControl,_T("ButtonUI"),i);115 //上月116 if(i SetText(cDay);121 DrawBtnBackImage(pButtonUI,false);122 }123 else if(i>iStartDay-1&&iDay SetText(cDay);128 DrawBtnBackImage(pButtonUI,true);129 } 130 else 131 {132 iNextMonthDays ++;133 sprintf(cDay,"%d",iNextMonthDays);134 pButtonUI->SetText(cDay);135 DrawBtnBackImage(pButtonUI,false);136 }137 }138 }139 140 void DrawBtnBackImage(CControlUI* pButtonUI,bool isEnable)141 {142 if(isEnable)143 {144 pButtonUI->SetEnabled(true);145 pButtonUI->ApplyAttributeList(146 _T("normalp_w_picpath=\"file='cells.png' source='0,0,81,81'\" ")\147 _T("hotp_w_picpath=\"file='cells.png' source='0,81,81,162'\" "));148 }149 else150 {151 pButtonUI->SetBkImage(_T("calpad.jpg"));152 pButtonUI->ApplyAttributeList(153 _T("normalp_w_picpath=\"file='calpad.jpg'\" ")\154 _T("hotp_w_picpath=\"file='calpad.jpg'\" "));155 }156 }157 158 int GetMonthDays(int iY,int iM)159 {160 int iTotalDay = 31; 161 if(iM == 2) 162 {163 //闰年可以被4或者400整除 但是不能被100整除164 if(iY % 4 ==0 && iY % 100 !=0 || iY % 400 ==0) 165 iTotalDay= 29;166 else167 iTotalDay=28;168 }169 else if(iM==4 || iM==6 || iM==9||iM==11)170 iTotalDay = 30;171 return iTotalDay;172 }173 174 int GetDayOfWeek(SYSTEMTIME m_sysTime)175 {176 cTime.SetDate(m_sysTime.wYear,m_sysTime.wMonth,m_sysTime.wDay);177 return cTime.GetDayOfWeek()-1;178 }179 180 int GetCmbMonth()181 {182 CComboUI* pCmb = static_cast (m_pm.FindControl(_T("CMB_MONTH")));183 CDuiString cCurMonth = pCmb->GetText();184 return atoi(cCurMonth.Left(cCurMonth.GetLength()-1));185 }186 187 int SetTxtYear(int iY)188 {189 CEditUI* pTxt = static_cast (m_pm.FindControl(_T("TXT_YEAR")));190 CDuiString cCurYear = pTxt->GetText();191 int iCurYear= 0;192 iCurYear = atoi(cCurYear) + iY;193 cCurYear.Format("%d",iCurYear);194 pTxt->SetText(cCurYear);195 return iCurYear;196 }197 198 199 public:200 CPaintManagerUI m_pm;201 SYSTEMTIME m_sysTime;202 COleDateTime cTime;203 };204 205 206 int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/, LPSTR /*lpCmdLine*/, int nCmdShow)207 {208 CPaintManagerUI::SetInstance(hInstance);209 CPaintManagerUI::SetResourcePath(CPaintManagerUI::GetInstancePath());210 211 HRESULT Hr = ::CoInitialize(NULL);212 if( FAILED(Hr) ) return 0;213 214 CFrameWindowWnd* pFrame = new CFrameWindowWnd();215 if( pFrame == NULL ) return 0;216 // pFrame->Create(NULL, _T("日历控件测试"), UI_WNDSTYLE_FRAME, WS_EX_WINDOWEDGE);217 pFrame->Create(NULL, _T("日历控件测试"), UI_WNDSTYLE_DIALOG, WS_EX_STATICEDGE | WS_EX_APPWINDOW, 0, 0, 600, 320); //禁止双击放大218 pFrame->CenterWindow();219 pFrame->ShowWindow(true);220 CPaintManagerUI::MessageLoop();221 222 ::CoUninitialize();223 return 0;224 }
d、运行看一下效果吧!
暂时没有实现阴历的显示,待项目开发完毕,有时间实现完给大家开源。