DropWnd.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554
  1. /////////////////////////////////////////////////////////////////////////////
  2. // DropWnd.cpp : implementation file
  3. //
  4. // CAdvComboBox Control
  5. // Version: 2.1
  6. // Date: September 2002
  7. // Author: Mathias Tunared
  8. // Email: Mathias@inorbit.com
  9. // Copyright (c) 2002. All Rights Reserved.
  10. //
  11. // This code, in compiled form or as source code, may be redistributed
  12. // unmodified PROVIDING it is not sold for profit without the authors
  13. // written consent, and providing that this notice and the authors name
  14. // and all copyright notices remains intact.
  15. //
  16. // This file is provided "as is" with no expressed or implied warranty.
  17. // The author accepts no liability for any damage/loss of business that
  18. // this product may cause.
  19. //
  20. /////////////////////////////////////////////////////////////////////////////
  21. #include "stdafx.h"
  22. #include "DropWnd.h"
  23. #include "AdvComboBox.h"
  24. #include "DropListBox.h"
  25. #include "VisualStylesXP.h"
  26. #ifdef _DEBUG
  27. #define new DEBUG_NEW
  28. #undef THIS_FILE
  29. static char THIS_FILE[] = __FILE__;
  30. #endif
  31. /////////////////////////////////////////////////////////////////////////////
  32. // CDropWnd
  33. CDropWnd::CDropWnd( CWnd* pComboParent, list<LIST_ITEM> &itemlist, DWORD dwACBStyle )
  34. :
  35. m_pComboParent( pComboParent ),
  36. m_list( itemlist ),
  37. m_dwACBStyle( dwACBStyle ),
  38. m_nMaxX(1000), //+++
  39. m_nMaxY(1000) //+++
  40. {
  41. m_bResizing = false;
  42. m_pListFont = new CFont;
  43. LOGFONT logFont;
  44. memset( &logFont, 0, sizeof(LOGFONT) );
  45. _tcscpy( logFont.lfFaceName, _T("MS Sans Serif") );
  46. logFont.lfHeight = 12;
  47. m_pListFont->CreateFontIndirect(&logFont);
  48. }
  49. CDropWnd::~CDropWnd()
  50. {
  51. delete m_pListFont;
  52. delete m_scrollbar;
  53. delete m_listbox;
  54. }
  55. BEGIN_MESSAGE_MAP(CDropWnd, CWnd)
  56. //{{AFX_MSG_MAP(CDropWnd)
  57. ON_WM_CREATE()
  58. ON_WM_MOUSEMOVE()
  59. ON_WM_LBUTTONDOWN()
  60. ON_WM_SIZE()
  61. ON_WM_PAINT()
  62. ON_WM_LBUTTONUP()
  63. ON_WM_SHOWWINDOW()
  64. ON_WM_ACTIVATEAPP()
  65. ON_WM_ERASEBKGND()
  66. //}}AFX_MSG_MAP
  67. ON_MESSAGE( WM_VRC_SETCAPTURE, OnSetCapture )
  68. ON_MESSAGE( WM_VRC_RELEASECAPTURE, OnReleaseCapture )
  69. END_MESSAGE_MAP()
  70. /////////////////////////////////////////////////////////////////////////////
  71. // CDropWnd message handlers
  72. BOOL CDropWnd::PreCreateWindow(CREATESTRUCT& cs)
  73. {
  74. //
  75. // Calc the size of the wnd
  76. return CWnd::PreCreateWindow(cs);
  77. }
  78. #if 0 // -----------------------------------------------------------
  79. BOOL CDropWnd::Create(DWORD dwStyle,
  80. const RECT& rect,
  81. CWnd* pParentWnd,
  82. UINT nID,
  83. CCreateContext* pContext)
  84. {
  85. return CWnd::Create(0, 0, dwStyle, rect, pParentWnd, nID, pContext);
  86. }
  87. #endif // -----------------------------------------------------------
  88. int CDropWnd::OnCreate(LPCREATESTRUCT lpCreateStruct)
  89. {
  90. if (CWnd::OnCreate(lpCreateStruct) == -1)
  91. return -1;
  92. CRect rcWnd;
  93. GetClientRect( &rcWnd );
  94. //
  95. // Because this window doesn't have an owner, there will appear
  96. // a 'blank' button on the taskbar. The following are to hide
  97. // that 'blank' button on the taskbar
  98. ModifyStyleEx( 0, WS_EX_TOOLWINDOW );
  99. SetWindowPos( &wndTopMost, lpCreateStruct->x, lpCreateStruct->y,
  100. lpCreateStruct->cx, lpCreateStruct->cy, SWP_SHOWWINDOW );
  101. //
  102. // Create scrollbar
  103. m_rcScroll = rcWnd;
  104. m_rcScroll.left = m_rcScroll.right - ::GetSystemMetrics(SM_CXVSCROLL);
  105. m_rcScroll.bottom -= ::GetSystemMetrics(SM_CYVSCROLL);
  106. m_scrollbar = new CDropScrollBar;
  107. VERIFY(m_scrollbar->Create( SBS_VERT | SBS_RIGHTALIGN | WS_CHILD, m_rcScroll, this, 100));
  108. //
  109. // Create listbox
  110. m_rcList.SetRect( lpCreateStruct->x, lpCreateStruct->y,
  111. lpCreateStruct->x+lpCreateStruct->cx-::GetSystemMetrics(SM_CXVSCROLL),
  112. lpCreateStruct->y+lpCreateStruct->cy );
  113. ScreenToClient( m_rcList );
  114. m_listbox = new CDropListBox(m_pComboParent, m_scrollbar);
  115. VERIFY(m_listbox->Create( WS_CHILD | LBS_NOINTEGRALHEIGHT
  116. /*| WS_VISIBLE | */ /*| LBS_OWNERDRAWFIXED*/,
  117. m_rcList, this, 101 ) );
  118. m_listbox->SetDLBStyle( m_dwACBStyle );
  119. m_listbox->ShowWindow( SW_SHOW );
  120. //
  121. // Resize this wnd so INTEGRAL_HEIGHT applies!?
  122. CRect rc;
  123. int nH = m_listbox->GetItemHeight(0);
  124. nH = nH*m_list.size()+2;
  125. // Get screen size
  126. int nScrX = GetSystemMetrics( SM_CXSCREEN );
  127. int nScrY = GetSystemMetrics( SM_CYSCREEN );
  128. int nDefaultItems = static_cast<CAdvComboBox*>(m_pComboParent)->GetDefaultVisibleItems();
  129. //
  130. // Check to see if the window should be placed over the combobox
  131. int nY = lpCreateStruct->y;
  132. int nItems = m_list.size();
  133. int nItemHeight = m_listbox->GetItemHeight(0);
  134. int nVisHeight = nScrY - lpCreateStruct->y;
  135. CRect rcCombo;
  136. m_pComboParent->GetWindowRect( &rcCombo );
  137. if( (nVisHeight / nItemHeight) < static_cast<CAdvComboBox*>(m_pComboParent)->GetMinVisibleItems() )
  138. {
  139. int nComboTopY = lpCreateStruct->y - rcCombo.Height();
  140. if( nDefaultItems == -1 || nDefaultItems > nItems )
  141. {
  142. nY = (nComboTopY - nH) < 0 ? 0 : (nComboTopY - nH);
  143. nH = (nY + nH) > nComboTopY ? nComboTopY - nY : nH;
  144. }
  145. else
  146. {
  147. nY = nComboTopY - nItemHeight*nDefaultItems;
  148. nY -= 2;
  149. nY = nY < 0 ? 0 : nY;
  150. nH = nComboTopY - nY;
  151. }
  152. }
  153. else
  154. {
  155. //
  156. // Place the window below the combo
  157. // Check height
  158. if( nDefaultItems == -1 || nDefaultItems > nItems )
  159. {
  160. if( lpCreateStruct->y + nH > nScrY )
  161. {
  162. nH = nScrY - lpCreateStruct->y;
  163. }
  164. else
  165. if( nH < ::GetSystemMetrics(SM_CYVSCROLL) )
  166. {
  167. nH = ::GetSystemMetrics(SM_CYVSCROLL);
  168. }
  169. }
  170. else
  171. {
  172. nH = nDefaultItems * nItemHeight;
  173. nH = (nY+nH) > nScrY ? nScrY-nY : nH;
  174. nH += 2;
  175. }
  176. }
  177. // Calc width
  178. int nW = 0;
  179. CSize size(0,0);
  180. for( m_iter = m_list.begin(); m_iter != m_list.end(); ++m_iter )
  181. {
  182. m_listbox->GetTextSize( m_iter->strText.c_str(), m_iter->strText.length(), size );
  183. nW = (size.cx > nW) ? size.cx : nW;
  184. }
  185. nW += m_rcScroll.Width() + 8;
  186. // Check min width
  187. if( nW < m_rcList.Width() )
  188. {
  189. nW = lpCreateStruct->cx;
  190. }
  191. //+++
  192. if (nW < rcCombo.Width())
  193. nW = rcCombo.Width();
  194. // Check max width
  195. int nX = lpCreateStruct->x;
  196. if( nW > nScrX - lpCreateStruct->x )
  197. {
  198. nX = nScrX - nW;
  199. if( nX < 0 )
  200. nX = 0;
  201. }
  202. if( nX == 0 && nW > nScrX )
  203. nW = nScrX;
  204. //nW += 4; //+++
  205. m_nMaxX = nW + 100; //+++
  206. m_nMaxY = nH + 100; //+++
  207. SetWindowPos( &wndTopMost, nX, nY, nW, nH, SWP_SHOWWINDOW|SWP_NOZORDER );
  208. GetClientRect( &rcWnd );
  209. //
  210. // Create sizehandle
  211. m_rcSizeHandle = rcWnd;
  212. GetClientRect( &m_rcSizeHandle );
  213. m_rcSizeHandle.left = m_rcSizeHandle.right - ::GetSystemMetrics(SM_CXVSCROLL);
  214. m_rcSizeHandle.top = m_rcSizeHandle.bottom - ::GetSystemMetrics(SM_CYVSCROLL);
  215. //
  216. // Add items to listbox
  217. LIST_ITEM item;
  218. for( m_iter = m_list.begin(); m_iter != m_list.end(); ++m_iter )
  219. {
  220. item = *m_iter;
  221. m_listbox->AddListItem( item );
  222. }
  223. //
  224. // Set values in scrollbar
  225. m_scrollbar->SetListBox( m_listbox );
  226. m_scrollbar->ShowScrollBar();
  227. //
  228. //
  229. SetCapture();
  230. return 0;
  231. }
  232. LONG CDropWnd::OnSetCapture( WPARAM /*wParam*/, LPARAM /*lParam*/ )
  233. {
  234. SetCapture();
  235. return FALSE;
  236. }
  237. LONG CDropWnd::OnReleaseCapture( WPARAM /*wParam*/, LPARAM /*lParam*/ )
  238. {
  239. ReleaseCapture();
  240. return FALSE;
  241. }
  242. void CDropWnd::OnMouseMove(UINT nFlags, CPoint point)
  243. {
  244. //
  245. //
  246. if( m_bResizing )
  247. {
  248. CRect rcWnd;
  249. GetWindowRect( &rcWnd );
  250. #if 0 // -----------------------------------------------------------
  251. if( point.x + m_nMouseDiffX >= ::GetSystemMetrics(SM_CXVSCROLL) )
  252. {
  253. rcWnd.right = rcWnd.left + point.x + m_nMouseDiffX +2;
  254. }
  255. else
  256. {
  257. rcWnd.right = rcWnd.left + ::GetSystemMetrics(SM_CXVSCROLL) +1;
  258. }
  259. if( point.y + m_nMouseDiffY >= ::GetSystemMetrics(SM_CYVSCROLL) )
  260. {
  261. rcWnd.bottom = rcWnd.top + point.y + m_nMouseDiffY +2;
  262. }
  263. else
  264. {
  265. rcWnd.bottom = rcWnd.top + ::GetSystemMetrics(SM_CXVSCROLL) +1;
  266. }
  267. #endif // -----------------------------------------------------------
  268. //+++
  269. CRect rcCombo;
  270. m_pComboParent->GetWindowRect( &rcCombo );
  271. if( point.x + m_nMouseDiffX < rcCombo.Width())
  272. {
  273. rcWnd.right = rcWnd.left + rcCombo.Width();
  274. }
  275. else if (point.x + m_nMouseDiffX > m_nMaxX)
  276. {
  277. rcWnd.right = rcWnd.left + m_nMaxX;
  278. }
  279. else
  280. {
  281. rcWnd.right = rcWnd.left + point.x + m_nMouseDiffX;
  282. }
  283. if( point.y + m_nMouseDiffY < :: GetSystemMetrics(SM_CYVSCROLL) )
  284. {
  285. rcWnd.bottom = rcWnd.top + ::GetSystemMetrics(SM_CXVSCROLL) +1;
  286. }
  287. else if ( point.y + m_nMouseDiffY > m_nMaxY )
  288. {
  289. rcWnd.bottom = rcWnd.top + m_nMaxY;
  290. }
  291. else
  292. {
  293. rcWnd.bottom = rcWnd.top + point.y + m_nMouseDiffY +2;
  294. }
  295. MoveWindow( &rcWnd );
  296. return;
  297. }
  298. //
  299. // Check point
  300. if( m_rcList.PtInRect( point ) )
  301. {
  302. HCURSOR hCursor = LoadCursor( NULL, IDC_ARROW );
  303. SetCursor( hCursor );
  304. ReleaseCapture();
  305. m_scrollbar->SendMessage( WM_VRC_RELEASECAPTURE );
  306. m_listbox->SetFocus();
  307. m_listbox->SendMessage( WM_VRC_SETCAPTURE );
  308. }
  309. else
  310. if( m_rcScroll.PtInRect( point ) )
  311. {
  312. HCURSOR hCursor = LoadCursor( NULL, IDC_ARROW );
  313. SetCursor( hCursor );
  314. m_scrollbar->SetFocus();
  315. ReleaseCapture();
  316. m_listbox->SendMessage( WM_VRC_RELEASECAPTURE );
  317. m_scrollbar->SendMessage( WM_VRC_SETCAPTURE );
  318. }
  319. else
  320. {
  321. if( m_rcSizeHandle.PtInRect( point ) )
  322. {
  323. HCURSOR hCursor = LoadCursor( NULL, IDC_SIZENWSE );
  324. SetCursor( hCursor );
  325. }
  326. else
  327. {
  328. HCURSOR hCursor = LoadCursor( NULL, IDC_ARROW );
  329. SetCursor( hCursor );
  330. }
  331. SetCapture();
  332. CWnd::OnMouseMove(nFlags, point);
  333. }
  334. }
  335. void CDropWnd::OnLButtonDown(UINT nFlags, CPoint point)
  336. {
  337. XLISTCTRL_TRACE(_T("in CDropWnd::OnLButtonDown\n"));
  338. if( m_rcSizeHandle.PtInRect( point ) )
  339. {
  340. m_bResizing = true;
  341. m_ptLastResize = point;
  342. CRect rcClient;
  343. GetClientRect( &rcClient );
  344. m_nMouseDiffX = rcClient.Width() - point.x;
  345. m_nMouseDiffY = rcClient.Height() - point.y;
  346. return;
  347. }
  348. //
  349. // Clean up the code below...
  350. //
  351. CRect rc;
  352. CRect rcVScroll(0,0,0,0);
  353. GetClientRect( &rc );
  354. // Take away vertical scroll
  355. if( rc.PtInRect( point ) )
  356. {
  357. }
  358. else
  359. {
  360. //
  361. // Calc the point in the parent(PropertyListBox)
  362. CWnd* pParent = m_pComboParent->GetParent();
  363. CRect rcParentClient;
  364. CRect rcParentWnd;
  365. pParent->GetClientRect( &rcParentClient );
  366. pParent->GetWindowRect( &rcParentWnd );
  367. CPoint pt = point;
  368. ClientToScreen( &pt );
  369. pt.x -= rcParentWnd.left;
  370. pt.y -= rcParentWnd.top;
  371. CAdvComboBox* pList = static_cast<CAdvComboBox*>(m_pComboParent);
  372. if( !pList->PointInWindow( pt ) )
  373. {
  374. ReleaseCapture();
  375. m_pComboParent->PostMessage( WM_DESTROY_DROPLIST );
  376. }
  377. else
  378. {
  379. ReleaseCapture();
  380. m_pComboParent->PostMessage( WM_DESTROY_DROPLIST );
  381. }
  382. }
  383. LPARAM l = MAKELPARAM(point.x, point.y);
  384. m_pComboParent->SendMessage(WM_LBUTTONDOWN, nFlags, l);
  385. CWnd::OnLButtonDown(nFlags, point);
  386. }
  387. void CDropWnd::OnLButtonUp(UINT nFlags, CPoint point)
  388. {
  389. if( m_bResizing )
  390. {
  391. m_bResizing = false;
  392. m_listbox->UnlockWindowUpdate();
  393. m_listbox->RedrawWindow();
  394. }
  395. CWnd::OnLButtonUp(nFlags, point);
  396. }
  397. void CDropWnd::OnSize(UINT nType, int cx, int cy)
  398. {
  399. CWnd::OnSize(nType, cx, cy);
  400. m_rcList.SetRect( 0, 0, cx-::GetSystemMetrics(SM_CXVSCROLL), cy );
  401. CRect rectBorder = m_rcList;
  402. m_rcList.DeflateRect(1, 1);
  403. m_listbox->MoveWindow( &m_rcList );
  404. m_rcScroll.SetRect( cx-::GetSystemMetrics(SM_CXVSCROLL), 0, cx, cy-::GetSystemMetrics(SM_CYVSCROLL) );
  405. m_rcScroll.DeflateRect(1, 1);
  406. m_scrollbar->MoveWindow( &m_rcScroll );
  407. //????? +++
  408. rectBorder.right = m_rcScroll.right + 1;
  409. //CPen pen(PS_SOLID, 1, ::GetSysColor(COLOR_BTNSHADOW));//COLOR_INACTIVECAPTION)); // same as combobox
  410. CPen pen(PS_SOLID, 1, ::GetSysColor(COLOR_3DDKSHADOW));//COLOR_INACTIVECAPTION)); // same as combobox
  411. CDC * pDC = GetDC();
  412. CPen *pOldPen = pDC->SelectObject(&pen);
  413. pDC->Rectangle(&rectBorder);
  414. pDC->SelectObject(pOldPen);
  415. ReleaseDC(pDC);
  416. m_rcSizeHandle.SetRect( cx-::GetSystemMetrics(SM_CXVSCROLL), cy-::GetSystemMetrics(SM_CYVSCROLL), cx, cy );
  417. m_rcSizeHandle.DeflateRect(1, 1);
  418. InvalidateRect( &m_rcSizeHandle );
  419. //
  420. // Fix the scrollbar
  421. SCROLLINFO info;
  422. info.cbSize = sizeof(SCROLLINFO);
  423. if( m_scrollbar->GetScrollInfo( &info, SIF_ALL|SIF_DISABLENOSCROLL ) )
  424. {
  425. info.nPage = m_listbox->GetBottomIndex() - m_listbox->GetTopIndex();
  426. m_scrollbar->SetScrollInfo( &info );
  427. }
  428. }
  429. void CDropWnd::OnPaint()
  430. {
  431. CPaintDC dc(this); // device context for painting
  432. if( g_xpStyle.UseVisualStyles() )
  433. {
  434. HTHEME hTheme = NULL;
  435. hTheme = g_xpStyle.OpenThemeData( m_hWnd, L"SCROLLBAR" );
  436. HRESULT hr = g_xpStyle.DrawThemeBackground( hTheme, dc.m_hDC, SBP_LOWERTRACKVERT, SCRBS_NORMAL, &m_rcSizeHandle, NULL);
  437. hr = g_xpStyle.DrawThemeBackground( hTheme, dc.m_hDC, SBP_SIZEBOX, SZB_RIGHTALIGN, &m_rcSizeHandle, NULL);
  438. hr = g_xpStyle.CloseThemeData( hTheme );
  439. }
  440. else
  441. {
  442. dc.DrawFrameControl(m_rcSizeHandle, DFC_SCROLL, DFCS_SCROLLSIZEGRIP );
  443. }
  444. // Do not call CWnd::OnPaint() for painting messages
  445. }
  446. BOOL CDropWnd::DestroyWindow()
  447. {
  448. ReleaseCapture();
  449. m_listbox->DestroyWindow();
  450. return CWnd::DestroyWindow();
  451. }
  452. void CDropWnd::OnShowWindow(BOOL bShow, UINT nStatus)
  453. {
  454. CWnd::OnShowWindow(bShow, nStatus);
  455. if( bShow )
  456. {
  457. // AnimateWindow( GetSafeHwnd(), 80, AW_VER_POSITIVE | AW_ACTIVATE | AW_SLIDE);
  458. }
  459. else
  460. {
  461. // AnimateWindow( GetSafeHwnd(), 80, AW_VER_NEGATIVE | AW_HIDE | AW_SLIDE);
  462. }
  463. }
  464. //+++
  465. #if (_MSC_VER > 1200)
  466. void CDropWnd::OnActivateApp(BOOL bActive, DWORD dwThreadID)
  467. {
  468. CWnd::OnActivateApp(bActive, dwThreadID);
  469. #else
  470. void CDropWnd::OnActivateApp(BOOL bActive, HTASK hTask)
  471. {
  472. CWnd::OnActivateApp(bActive, hTask);
  473. #endif
  474. if(!bActive)
  475. {
  476. m_pComboParent->PostMessage(WM_DESTROY_DROPLIST);
  477. }
  478. }