PropertyGridExtItemDate.cpp 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430
  1. #include "stdafx.h"
  2. #include "PropertyGridInplaceEdit.h"
  3. #include "PropertyGridInplaceButton.h"
  4. #include "PropertyGridInplaceList.h"
  5. #include "PropertyGridItem.h"
  6. #include "PropertyGridExtItemDate.h"
  7. #include "PropertyGrid.h"
  8. /////////////////////////////////////////////////////////////////////////////
  9. // CInplaceDateEdit
  10. /////////////////////////////////////////////////////////////////////////////
  11. CInplaceDateEdit::CInplaceDateEdit()
  12. : m_pItem(0)
  13. , m_pGrid(0)
  14. {
  15. }
  16. CInplaceDateEdit::~CInplaceDateEdit()
  17. {
  18. }
  19. BEGIN_MESSAGE_MAP(CInplaceDateEdit, CDateEdit)
  20. //{{AFX_MSG_MAP(CInplaceDateEdit)
  21. ON_WM_CTLCOLOR_REFLECT()
  22. ON_CONTROL_REFLECT(EN_KILLFOCUS, OnEnKillfocus)
  23. ON_CONTROL_REFLECT(EN_SETFOCUS, OnEnSetfocus)
  24. ON_WM_GETDLGCODE()
  25. ON_WM_KEYDOWN()
  26. ON_WM_CHAR()
  27. //}}AFX_MSG_MAP
  28. END_MESSAGE_MAP()
  29. void CInplaceDateEdit::SetValue(CString strValue)
  30. {
  31. m_strValue = strValue;
  32. }
  33. void CInplaceDateEdit::Create(CPropertyGridExtItemDate* pItem, CRect rect)
  34. {
  35. ASSERT(pItem && pItem->GetGrid());
  36. m_pGrid = pItem->GetGrid();
  37. m_pItem = pItem;
  38. if (!m_hWnd)
  39. {
  40. CDateEdit::Create(WS_CHILD|ES_AUTOHSCROLL, rect, m_pGrid, 0);
  41. }
  42. SetWindowText(m_strValue);
  43. SetWindowPos(0, rect.left, rect.top, rect.Width(), rect.Height(), SWP_NOZORDER|SWP_SHOWWINDOW);
  44. }
  45. HBRUSH CInplaceDateEdit::CtlColor(CDC* pDC, UINT /*nCtlColor*/)
  46. {
  47. pDC->SetTextColor(GetStyle() & ES_READONLY ? GetSysColor(COLOR_GRAYTEXT): ((CPropertyGridView*)m_pGrid)->m_clrFore);
  48. COLORREF clr = ((CPropertyGridView*)m_pGrid)->m_clrBack;
  49. if (clr != m_clrBack || !m_brBack.GetSafeHandle())
  50. {
  51. m_brBack.DeleteObject();
  52. m_brBack.CreateSolidBrush(clr);
  53. m_clrBack = clr;
  54. }
  55. pDC->SetBkColor(m_clrBack);
  56. return m_brBack;
  57. }
  58. void CInplaceDateEdit::OnEnSetfocus()
  59. {
  60. ASSERT(m_pItem && m_pGrid);
  61. m_pGrid->Invalidate(FALSE);
  62. }
  63. void CInplaceDateEdit::OnEnKillfocus()
  64. {
  65. if (m_pItem)
  66. {
  67. m_pItem->OnValidateEdit();
  68. m_pGrid->Invalidate(FALSE);
  69. }
  70. }
  71. UINT CInplaceDateEdit::OnGetDlgCode()
  72. {
  73. return DLGC_WANTALLKEYS;
  74. }
  75. void CInplaceDateEdit::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
  76. {
  77. if (nChar == VK_TAB) return;
  78. if (nChar == VK_ESCAPE || nChar == VK_RETURN)
  79. {
  80. m_pGrid->SetFocus();
  81. return;
  82. }
  83. CDateEdit::OnChar(nChar, nRepCnt, nFlags);
  84. }
  85. void CInplaceDateEdit::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
  86. {
  87. if (nChar == VK_TAB)
  88. {
  89. CWnd* pParent = m_pGrid->GetParent();
  90. if (!pParent || !pParent->GetParent())
  91. {
  92. ASSERT(FALSE);
  93. return;
  94. }
  95. CWnd* pWndNext = pParent->GetParent()->GetNextDlgTabItem( pParent, ::GetKeyState(VK_SHIFT) < 0 );
  96. if (pWndNext != NULL)
  97. {
  98. pWndNext->SetFocus();
  99. }
  100. return;
  101. }
  102. else if (nChar == VK_ESCAPE)
  103. {
  104. SetWindowText(m_strValue);
  105. return;
  106. }
  107. else if (nChar == VK_RETURN)
  108. {
  109. return;
  110. }
  111. CDateEdit::OnKeyDown(nChar, nRepCnt, nFlags);
  112. }
  113. void CInplaceDateEdit::DestroyItem()
  114. {
  115. // reset variables to defaults.
  116. m_pItem = NULL;
  117. m_pGrid = NULL;
  118. m_strValue.Empty();
  119. m_brBack.DeleteObject();
  120. // destroy the window.
  121. DestroyWindow( );
  122. }
  123. /////////////////////////////////////////////////////////////////////////////
  124. // CInplaceMonthCal
  125. /////////////////////////////////////////////////////////////////////////////
  126. CInplaceMonthCal::CInplaceMonthCal()
  127. : m_pItem(0)
  128. {
  129. }
  130. CInplaceMonthCal::~CInplaceMonthCal()
  131. {
  132. }
  133. BEGIN_MESSAGE_MAP(CInplaceMonthCal, CMonthCalCtrl)
  134. //{{AFX_MSG_MAP(CInplaceMonthCal)
  135. ON_NOTIFY_REFLECT(MCN_SELECT, OnSelect)
  136. ON_WM_KEYDOWN()
  137. ON_WM_KILLFOCUS()
  138. ON_WM_MOUSEACTIVATE()
  139. //}}AFX_MSG_MAP
  140. END_MESSAGE_MAP()
  141. void CInplaceMonthCal::Create(CPropertyGridExtItemDate* pItem)
  142. {
  143. ASSERT(pItem && pItem->GetGrid());
  144. m_pItem = pItem;
  145. CWnd* pGrid = m_pItem->GetGrid();
  146. // 创建日历控件
  147. if (m_hWnd == NULL)
  148. {
  149. CreateEx(0, MONTHCAL_CLASS, NULL, WS_CHILD | WS_BORDER, CRect(0, 0, 1, 1), pGrid, 0);
  150. SetOwner(pGrid);
  151. }
  152. // 计算日历控件的位置
  153. CRect rcItem= m_pItem->GetItemRect();
  154. pGrid->ClientToScreen(&rcItem);
  155. CRect rect;
  156. GetMinReqRect(&rect);
  157. rect.SetRect(rcItem.right - rect.Width(), rcItem.bottom, rcItem.right, rcItem.bottom + rect.Height());
  158. CRect rcWork;
  159. ::SystemParametersInfo(SPI_GETWORKAREA, NULL, &rcWork, 0);
  160. if (rect.bottom > rcWork.bottom) rect.OffsetRect(0, - rect.Height() - rcItem.Height() - 1);
  161. if (rect.top < rcWork.top) rect.OffsetRect(0, rcWork.top - rect.top);
  162. if (rect.left < rcWork.left) rect.OffsetRect(rcWork.left - rect.left, 0);
  163. if (rect.right > rcWork.right) rect.OffsetRect(rcWork.right - rect.right, 0);
  164. // 以子窗口方式创建内置日历控件,然后再执行下面这段代码,内置日历
  165. // 控件将以弹出窗口方式显示,并得到输入焦点,但当前窗口保持不变
  166. SetFocus();
  167. ::SetWindowLong(m_hWnd, GWL_HWNDPARENT, NULL);
  168. ModifyStyle(WS_CHILD, WS_POPUP);
  169. ::SetWindowLong(m_hWnd, GWL_HWNDPARENT, (LONG)pGrid->m_hWnd);
  170. SetWindowPos(0, rect.left, rect.top, rect.Width(), rect.Height(), SWP_NOZORDER|SWP_SHOWWINDOW|SWP_NOACTIVATE);
  171. // 要在显示日历控件后再选择日期,因为属性项处于编辑状态时,
  172. // 编辑控件在激活日历控件时失去焦点,从而更新属性值
  173. SetCurSel( m_pItem->GetDate() );
  174. CPGMouseMonitor::SetupHook(this);
  175. }
  176. void CInplaceMonthCal::OnSelect(NMHDR* pNMHDR, LRESULT* pResult)
  177. {
  178. // 更新属性项
  179. Apply();
  180. *pResult = 0;
  181. }
  182. void CInplaceMonthCal::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
  183. {
  184. switch (nChar)
  185. {
  186. case VK_RETURN:
  187. Apply();
  188. break;
  189. case VK_ESCAPE:
  190. Cancel();
  191. }
  192. CMonthCalCtrl::OnKeyDown(nChar, nRepCnt, nFlags);
  193. }
  194. void CInplaceMonthCal::OnKillFocus(CWnd* pNewWnd)
  195. {
  196. CMonthCalCtrl::OnKillFocus(pNewWnd);
  197. // 如果不是内置控件导致的事件,则删除窗口
  198. if (!IsChild(pNewWnd))
  199. {
  200. CPGMouseMonitor::SetupHook(NULL);
  201. DestroyItem();
  202. }
  203. }
  204. int CInplaceMonthCal::OnMouseActivate(CWnd* pDesktopWnd, UINT nHitTest, UINT message)
  205. {
  206. // 用鼠标点击内置日历控件时,不改变当前窗口
  207. return MA_NOACTIVATE;
  208. }
  209. void CInplaceMonthCal::Apply()
  210. {
  211. SYSTEMTIME st;
  212. GetCurSel(&st);
  213. COleDateTime dt;
  214. dt.SetDate(st.wYear, st.wMonth, st.wDay);
  215. CString str = CDateEdit::DateToString(dt);
  216. if (str != m_pItem->GetValue())
  217. m_pItem->OnValueChanged(str);
  218. GetOwner()->SetFocus();
  219. }
  220. void CInplaceMonthCal::Cancel()
  221. {
  222. GetOwner()->SetFocus();
  223. }
  224. void CInplaceMonthCal::DestroyItem()
  225. {
  226. m_pItem = NULL;
  227. DestroyWindow( );
  228. }
  229. /////////////////////////////////////////////////////////////////////////////
  230. // CPropertyGridExtItemDate
  231. /////////////////////////////////////////////////////////////////////////////
  232. CPropertyGridExtItemDate::CPropertyGridExtItemDate(CString strCaption, COleDateTime dtDate /* = 当前日期 */ )
  233. : CPropertyGridItem(strCaption)
  234. {
  235. m_wndDateEdit.m_pItem = this;
  236. m_wndMonthCal.m_pItem = this;
  237. m_pBindDate = NULL;
  238. m_nFlags = pgitemHasEdit | pgitemHasComboButton;
  239. SetDate(dtDate);
  240. }
  241. CPropertyGridExtItemDate::CPropertyGridExtItemDate(UINT nID, COleDateTime dtDate /* = 当前日期 */ )
  242. : CPropertyGridItem(nID)
  243. {
  244. m_wndDateEdit.m_pItem = this;
  245. m_wndMonthCal.m_pItem = this;
  246. m_pBindDate = NULL;
  247. m_nFlags = pgitemHasEdit | pgitemHasComboButton;
  248. SetDate(dtDate);
  249. }
  250. CPropertyGridExtItemDate::~CPropertyGridExtItemDate()
  251. {
  252. m_wndDateEdit.DestroyItem();
  253. m_wndMonthCal.DestroyItem();
  254. }
  255. void CPropertyGridExtItemDate::SetDate(COleDateTime dtDate)
  256. {
  257. // 如果参数dtDate不合法,则使用缺省构造函数产生的日期做为属性值
  258. if (dtDate.GetStatus() == COleDateTime::valid)
  259. m_dtDate = dtDate;
  260. else
  261. m_dtDate = COleDateTime();
  262. CPropertyGridItem::SetValue( CDateEdit::DateToString(m_dtDate) );
  263. if (m_pBindDate)
  264. *m_pBindDate = m_dtDate;
  265. }
  266. COleDateTime CPropertyGridExtItemDate::GetDate()
  267. {
  268. return m_dtDate;
  269. }
  270. void CPropertyGridExtItemDate::SetValue(CString strValue)
  271. {
  272. SetDate(CDateEdit::StringToOleDateTime(strValue));
  273. }
  274. void CPropertyGridExtItemDate::OnValidateEdit()
  275. {
  276. if (m_wndDateEdit.GetSafeHwnd())
  277. {
  278. m_wndDateEdit.ShowWindow(SW_HIDE);
  279. CString strValue;
  280. m_wndDateEdit.GetWindowText(strValue);
  281. if (m_strValue != strValue)
  282. {
  283. // 如果输入的日期合法,则更新属性值,否则发出错误提示音
  284. COleDateTime dt= CDateEdit::StringToOleDateTime(strValue);
  285. if (dt.GetStatus() == COleDateTime::valid)
  286. {
  287. OnValueChanged(strValue);
  288. m_pGrid->Invalidate(FALSE);
  289. }
  290. else
  291. {
  292. ::MessageBeep( (UINT)-1 );
  293. // 内置编辑控件恢复原来的属性值
  294. SetEditText(m_strValue);
  295. }
  296. }
  297. }
  298. }
  299. void CPropertyGridExtItemDate::SetEditText(CString str)
  300. {
  301. if (!m_pGrid) return;
  302. if (m_wndDateEdit.GetSafeHwnd())
  303. m_wndDateEdit.SetWindowText(str);
  304. }
  305. void CPropertyGridExtItemDate::OnSelect()
  306. {
  307. ASSERT(m_bVisible);
  308. if (!m_bReadOnly && (m_nFlags & (pgitemHasComboButton | pgitemHasExpandButton)))
  309. {
  310. GetInplaceButton().Create(this, GetItemRect());
  311. }
  312. if (m_nFlags & pgitemHasEdit)
  313. {
  314. m_wndDateEdit.SetValue(m_strValue);
  315. m_wndDateEdit.Create(this, GetValueRect());
  316. m_wndDateEdit.SetReadOnly(m_bReadOnly);
  317. m_wndDateEdit.SetFont(GetGrid()->GetFont());
  318. m_wndDateEdit.SetMargins(3, 0);
  319. }
  320. }
  321. BOOL CPropertyGridExtItemDate::OnChar(UINT nChar)
  322. {
  323. if (m_nFlags & pgitemHasEdit)
  324. {
  325. OnSelect();
  326. m_wndDateEdit.SetFocus();
  327. m_wndDateEdit.MaskSelectAll();
  328. if (nChar != VK_TAB) m_wndDateEdit.SendMessage(WM_CHAR, nChar);
  329. return TRUE;
  330. }
  331. return FALSE;
  332. }
  333. void CPropertyGridExtItemDate::OnLButtonDblClk()
  334. {
  335. if (HasChilds())
  336. {
  337. if(m_bExpanded) Collapse(); else Expand();
  338. }
  339. else
  340. {
  341. OnSelect();
  342. if (m_nFlags & pgitemHasEdit)
  343. {
  344. m_wndDateEdit.SetFocus();
  345. m_wndDateEdit.MaskSelectAll();
  346. }
  347. }
  348. }
  349. void CPropertyGridExtItemDate::BindToDate(COleDateTime* pBindDate)
  350. {
  351. m_pBindDate = pBindDate;
  352. if (m_pBindDate)
  353. SetDate(*m_pBindDate);
  354. }
  355. void CPropertyGridExtItemDate::OnInplaceButtonDown()
  356. {
  357. m_wndMonthCal.Create(this);
  358. }