PropertyGridItem.cpp 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483
  1. #include "StdAfx.h"
  2. #include "PropertyGrid_Defines.h"
  3. #include "PropertyGridInplaceEdit.h"
  4. #include "PropertyGridInplaceButton.h"
  5. #include "PropertyGridInplaceList.h"
  6. #include "PropertyGridItem.h"
  7. #include "PropertyGrid.h"
  8. /////////////////////////////////////////////////////////////////////////////
  9. // CPropertyGridItem
  10. CPropertyGridItem::CPropertyGridItem(CString strCaption, LPCTSTR strValue, UINT nMaxLength)
  11. {
  12. Init();
  13. SetCaption(strCaption);
  14. m_nMaxLength = nMaxLength;
  15. m_strValue = AdjustValue(strValue);
  16. }
  17. CPropertyGridItem::CPropertyGridItem(UINT nID, LPCTSTR strValue, UINT nMaxLength)
  18. {
  19. Init();
  20. m_nID = nID;
  21. CString strText;
  22. if (strText.LoadString(nID))
  23. {
  24. int nIndex = strText.Find( _T('\n') );
  25. if (nIndex == -1)
  26. {
  27. m_strCaption = strText;
  28. } else
  29. {
  30. m_strCaption = strText.Left(nIndex);
  31. m_strDescription = strText.Mid(nIndex + 1);
  32. }
  33. }
  34. m_nMaxLength = nMaxLength;
  35. m_strValue = AdjustValue(strValue);
  36. }
  37. CPropertyGridItem::~CPropertyGridItem(void)
  38. {
  39. while (!m_lstChilds.IsEmpty())
  40. {
  41. delete m_lstChilds.RemoveTail();
  42. }
  43. if ( ::IsWindow( GetInplaceButton().m_hWnd ) )
  44. {
  45. GetInplaceButton().DestroyItem( );
  46. }
  47. if ( ::IsWindow( GetInplaceList().m_hWnd ) )
  48. {
  49. GetInplaceList().DestroyItem( );
  50. }
  51. if ( ::IsWindow( GetInplaceEdit().m_hWnd ) )
  52. {
  53. GetInplaceEdit().DestroyItem( );
  54. }
  55. }
  56. void CPropertyGridItem::Init()
  57. {
  58. m_bExpanded = FALSE;
  59. m_nIndex = -1;
  60. m_bVisible = FALSE;
  61. m_pParent = 0;
  62. m_pGrid = NULL;
  63. m_nIndent = 0;
  64. m_strValue = _T("");
  65. m_bReadOnly = FALSE;
  66. m_bCategory = FALSE;
  67. m_nID = 0;
  68. m_nFlags = pgitemHasEdit;
  69. m_dwItemData = 0;
  70. m_pBindString = NULL;
  71. }
  72. CString CPropertyGridItem::AdjustValue(CString strValue)
  73. {
  74. if (m_nMaxLength > 0 && strValue.GetLength() > (int)m_nMaxLength)
  75. return strValue.Left(m_nMaxLength);
  76. else
  77. return strValue;
  78. }
  79. CPropertyGridItem* CPropertyGridItem::AddChildItem(CPropertyGridItem* pItem)
  80. {
  81. m_lstChilds.AddTail(pItem);
  82. pItem->m_pGrid = m_pGrid;
  83. ASSERT(pItem->m_pParent == NULL);
  84. pItem->m_pParent = this;
  85. pItem->m_nIndent = m_nIndent + 1;
  86. pItem->OnAddChildItem();
  87. if (m_bVisible)
  88. {
  89. if (m_bExpanded)
  90. m_pGrid->SetPropertySort(m_pGrid->m_properetySort, TRUE);
  91. else if (m_pGrid->GetSafeHwnd() && m_lstChilds.GetCount() == 1)
  92. // 如果父项处于折叠状态,且添加的是第一个子项,则刷新窗口以显示父项左边的"+"
  93. m_pGrid->Invalidate(FALSE);
  94. }
  95. else
  96. {
  97. // 如果属性表按字母排序或者不排序,此时属性分类不可见,但为属性分类添加的子项要显示出来
  98. if (m_bCategory && m_pGrid->m_properetySort != pgsortCategorized)
  99. m_pGrid->SetPropertySort(m_pGrid->m_properetySort, TRUE);
  100. }
  101. return pItem;
  102. }
  103. void CPropertyGridItem::Collapse()
  104. {
  105. if (!m_bExpanded) return;
  106. if (m_bVisible)
  107. {
  108. m_pGrid->_DoCollapse(this);
  109. // 下面这4行代码是为了解决第30号Bug
  110. CPropertyGridItem* pItem = m_pGrid->GetSelectedItem();
  111. if (m_pGrid->m_pSelected) m_pGrid->m_pSelected->OnDeselect();
  112. if (pItem) pItem->OnSelect();
  113. m_pGrid->m_pSelected = pItem;
  114. }
  115. m_bExpanded = FALSE;
  116. }
  117. void CPropertyGridItem::Expand()
  118. {
  119. if (m_bExpanded) return;
  120. if (m_bVisible)
  121. {
  122. m_pGrid->_DoExpand(this, m_nIndex);
  123. m_pGrid->_RefreshIndexes();
  124. // 下面这4行代码是为了解决第30号Bug
  125. CPropertyGridItem* pItem = m_pGrid->GetSelectedItem();
  126. if (m_pGrid->m_pSelected) m_pGrid->m_pSelected->OnDeselect();
  127. if (pItem) pItem->OnSelect();
  128. m_pGrid->m_pSelected = pItem;
  129. }
  130. m_bExpanded = TRUE;
  131. }
  132. BOOL CPropertyGridItem::HasParent(CPropertyGridItem* pParent)
  133. {
  134. if (m_pParent == NULL) return FALSE;
  135. if (m_pParent == pParent) return TRUE;
  136. return m_pParent->HasParent(pParent);
  137. }
  138. void CPropertyGridItem::SetReadOnly(BOOL bReadOnly)
  139. {
  140. m_bReadOnly = bReadOnly;
  141. if (m_pGrid && m_pGrid->GetSafeHwnd())
  142. {
  143. // 判断属性项是否处于选中状态
  144. if (m_pGrid->GetSelectedItem() == this)
  145. {
  146. OnDeselect();
  147. OnSelect();
  148. }
  149. m_pGrid->Invalidate(FALSE);
  150. }
  151. }
  152. void CPropertyGridItem::Select()
  153. {
  154. ASSERT(m_pGrid);
  155. if (m_bVisible)
  156. {
  157. m_pGrid->SetCurSel(m_nIndex);
  158. m_pGrid->OnSelectionChanged();
  159. }
  160. }
  161. void CPropertyGridItem::OnDeselect()
  162. {
  163. GetInplaceButton().HideWindow();
  164. OnValidateEdit();
  165. }
  166. void CPropertyGridItem::OnValidateEdit()
  167. {
  168. GetInplaceEdit().HideWindow();
  169. if (GetInplaceEdit().GetSafeHwnd() && GetInplaceEdit().m_pItem == this)
  170. {
  171. CString strValue;
  172. GetInplaceEdit().GetWindowText(strValue);
  173. if (m_strValue != strValue)
  174. {
  175. OnValueChanged(strValue);
  176. m_pGrid->Invalidate(FALSE);
  177. }
  178. }
  179. }
  180. void CPropertyGridItem::SetEditText(CString str)
  181. {
  182. if (!m_pGrid) return;
  183. if (GetInplaceEdit().GetSafeHwnd() && GetInplaceEdit().m_pItem == this)
  184. {
  185. GetInplaceEdit().SetWindowText(str);
  186. }
  187. }
  188. void CPropertyGridItem::SetValue(CString strValue)
  189. {
  190. m_strValue = AdjustValue(strValue);
  191. SetEditText(m_strValue);
  192. // 更新绑定的字符串对象
  193. if (m_pBindString)
  194. *m_pBindString = m_strValue;
  195. // 在设置完属性值后,强制刷新窗口
  196. if (m_pGrid && m_pGrid->m_hWnd) m_pGrid->Invalidate(FALSE);
  197. }
  198. void CPropertyGridItem::OnValueChanged(CString strValue)
  199. {
  200. SetValue(strValue);
  201. // 发送属性值改变的通知消息
  202. int nID = m_pGrid->GetParent()->GetDlgCtrlID();
  203. WPARAM wParam = MAKEWPARAM(nID, PGN_ITEMVALUE_CHANGED);
  204. m_pGrid->GetParent()->GetOwner()->SendMessage(PGWM_PROPERTYGRID_NOTIFY, wParam, (LPARAM)this);
  205. }
  206. void CPropertyGridItem::OnSelect()
  207. {
  208. ASSERT(m_bVisible);
  209. if (!m_bReadOnly && (m_nFlags & (pgitemHasComboButton | pgitemHasExpandButton)))
  210. {
  211. GetInplaceButton().Create(this, GetItemRect());
  212. }
  213. if (m_nFlags & pgitemHasEdit)
  214. {
  215. GetInplaceEdit().SetValue(m_strValue);
  216. GetInplaceEdit().Create(this, GetValueRect(), m_nMaxLength);
  217. GetInplaceEdit().SetReadOnly(m_bReadOnly);
  218. }
  219. else
  220. {
  221. GetInplaceEdit().HideWindow();
  222. }
  223. }
  224. void CPropertyGridItem::OnInplaceButtonDown()
  225. {
  226. if ((m_nFlags & pgitemHasComboButton) && !m_lstContraints.IsEmpty())
  227. {
  228. GetInplaceList().Create(this, GetItemRect());
  229. m_pGrid->Invalidate(FALSE);
  230. }
  231. }
  232. CRect CPropertyGridItem::GetValueRect()
  233. {
  234. ASSERT(m_bVisible);
  235. CRect rc = GetItemRect();
  236. CRect rcValue(m_pGrid->GetDividerPos() + 1, rc.top + 1, rc.right, rc.bottom - 1);
  237. if (m_nFlags & (pgitemHasComboButton | pgitemHasExpandButton))
  238. {
  239. if (GetInplaceButton().m_pItem == this && GetInplaceButton().GetStyle() & WS_VISIBLE)
  240. {
  241. rcValue.right -= 15;
  242. }
  243. }
  244. return rcValue;
  245. }
  246. CRect CPropertyGridItem::GetItemRect()
  247. {
  248. CRect rc;
  249. m_pGrid->GetItemRect(m_nIndex, rc);
  250. return rc;
  251. }
  252. BOOL CPropertyGridItem::OnChar(UINT nChar)
  253. {
  254. if (m_nFlags & pgitemHasEdit)
  255. {
  256. OnSelect();
  257. GetInplaceEdit().SetFocus();
  258. GetInplaceEdit().SetSel(0, -1);
  259. if (nChar != VK_TAB) GetInplaceEdit().SendMessage(WM_CHAR, nChar);
  260. return TRUE;
  261. }
  262. return FALSE;
  263. }
  264. void CPropertyGridItem::OnLButtonDblClk()
  265. {
  266. if (HasChilds())
  267. {
  268. if(m_bExpanded) Collapse(); else Expand();
  269. }
  270. else
  271. {
  272. OnSelect();
  273. if (m_nFlags & pgitemHasEdit)
  274. {
  275. if (!GetReadOnly() && GetInplaceEdit().SelectConstraint(+1, TRUE))
  276. {
  277. OnValidateEdit();
  278. }
  279. else
  280. {
  281. GetInplaceEdit().SetFocus();
  282. GetInplaceEdit().SetSel(0, -1);
  283. }
  284. }
  285. else if (!GetReadOnly())
  286. {
  287. CPGItemConstraints* pList = GetConstraints();
  288. if (pList->IsEmpty())
  289. return ;
  290. int nIndex = pList->FindConstraint(m_strValue);
  291. nIndex += +1;
  292. if (nIndex >= pList->GetCount()) nIndex = 0;
  293. POSITION pos = pList->FindIndex(nIndex);
  294. OnValueChanged(pList->GetAt(pos));
  295. }
  296. }
  297. }
  298. BOOL CPropertyGridItem::OnLButtonDown(UINT, CPoint point)
  299. {
  300. ASSERT(GetItemRect().PtInRect(point));
  301. m_pGrid->SetFocus();
  302. Select();
  303. // if(point.x <= PGI_EXPAND_BORDER)
  304. // {
  305. // if(m_bExpanded) Collapse(); else Expand();
  306. // }
  307. // 原来的代码只考虑了列表项为根结点的情况,没有
  308. // 考虑为子节点的情况,新代码修正了这个问题
  309. int nOffset = 0;
  310. if (m_nIndent > 1)
  311. nOffset = (m_nIndent - 1) * PGI_EXPAND_BORDER;
  312. if(point.x >= nOffset && point.x <= PGI_EXPAND_BORDER + nOffset)
  313. {
  314. if(m_bExpanded) Collapse(); else Expand();
  315. }
  316. CRect rc = GetValueRect();
  317. if ((m_nFlags & pgitemHasEdit) && rc.PtInRect(point))
  318. {
  319. mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);
  320. }
  321. return TRUE;
  322. }
  323. CPropertyGridInplaceEdit& CPropertyGridItem::GetInplaceEdit()
  324. {
  325. ASSERT(m_pGrid);
  326. return m_pGrid->m_wndEdit;
  327. }
  328. CPropertyGridInplaceButton& CPropertyGridItem::GetInplaceButton()
  329. {
  330. ASSERT(m_pGrid);
  331. return m_pGrid->m_wndButton;
  332. }
  333. CPropertyGridInplaceList& CPropertyGridItem::GetInplaceList()
  334. {
  335. ASSERT(m_pGrid);
  336. return m_pGrid->m_wndListBox;
  337. }
  338. /////////////////////////////////////////////////////////////////////////////
  339. // CPGListItems
  340. void CPGListItems::Sort()
  341. {
  342. CPGListItems lstSorted;
  343. POSITION pos = GetHeadPosition();
  344. while (pos)
  345. {
  346. CPropertyGridItem* pItem = GetNext(pos);
  347. BOOL bFound = FALSE;
  348. POSITION posInsert = lstSorted.GetHeadPosition();
  349. while (posInsert)
  350. {
  351. if (lstSorted.GetNext(posInsert)->GetCaption() > pItem->GetCaption())
  352. {
  353. bFound = TRUE;
  354. break;
  355. }
  356. }
  357. if (bFound)
  358. {
  359. if (posInsert)
  360. lstSorted.GetPrev(posInsert);
  361. else
  362. posInsert = lstSorted.GetTailPosition();
  363. lstSorted.InsertBefore(posInsert, pItem);
  364. }
  365. else
  366. {
  367. lstSorted.AddTail(pItem);
  368. }
  369. }
  370. RemoveAll();
  371. AddTail(&lstSorted);
  372. }
  373. CPropertyGridItem* CPGListItems::FindItem(CString strCaption)
  374. {
  375. POSITION pos = GetHeadPosition();
  376. while (pos)
  377. {
  378. CPropertyGridItem* pItem = GetNext(pos);
  379. if (pItem->GetCaption() == strCaption)
  380. return pItem;
  381. CPropertyGridItem* pChild = pItem->m_lstChilds.FindItem(strCaption);
  382. if (pChild) return pChild;
  383. }
  384. return NULL;
  385. }
  386. CPropertyGridItem* CPGListItems::FindItem(UINT nID)
  387. {
  388. POSITION pos = GetHeadPosition();
  389. while (pos)
  390. {
  391. CPropertyGridItem* pItem = GetNext(pos);
  392. if (pItem->GetID() == nID)
  393. return pItem;
  394. CPropertyGridItem* pChild = pItem->m_lstChilds.FindItem(nID);
  395. if (pChild) return pChild;
  396. }
  397. return NULL;
  398. }
  399. /////////////////////////////////////////////////////////////////////////////
  400. // CPGItemConstraints
  401. int CPGItemConstraints::FindConstraint(CString str)
  402. {
  403. POSITION pos = GetHeadPosition();
  404. int nIndex = 0;
  405. while (pos)
  406. {
  407. CString strNext = GetNext(pos);
  408. if (str == strNext)
  409. return nIndex;
  410. nIndex++;
  411. }
  412. return -1;
  413. }