Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

741 lines
19 KiB

  1. #include "ctlspriv.h"
  2. #pragma hdrstop
  3. #include "usrctl32.h"
  4. #include "combo.h"
  5. //---------------------------------------------------------------------------//
  6. //
  7. #define RECALC_CYDROP -1
  8. //---------------------------------------------------------------------------//
  9. VOID ComboBox_CalcControlRects(PCBOX pcbox, LPRECT lprcList)
  10. {
  11. CONST TCHAR szOneChar[] = TEXT("0");
  12. HDC hdc;
  13. HANDLE hOldFont = NULL;
  14. int dyEdit, dxEdit;
  15. MEASUREITEMSTRUCT mis;
  16. SIZE size;
  17. HWND hwnd = pcbox->hwnd;
  18. //
  19. // Determine height of the edit control. We can use this info to center
  20. // the button with recpect to the edit/static text window. For example
  21. // this will be useful if owner draw and this window is tall.
  22. //
  23. hdc = GetDC(hwnd);
  24. if (pcbox->hFont)
  25. {
  26. hOldFont = SelectObject(hdc, pcbox->hFont);
  27. }
  28. //
  29. // Add on CYEDGE just for some extra space in the edit field/static item.
  30. // It's really only for static text items, but we want static & editable
  31. // controls to be the same height.
  32. //
  33. GetTextExtentPoint(hdc, szOneChar, 1, &size);
  34. dyEdit = size.cy + GetSystemMetrics(SM_CYEDGE);
  35. if (hOldFont)
  36. {
  37. SelectObject(hdc, hOldFont);
  38. }
  39. ReleaseDC(hwnd, hdc);
  40. if (pcbox->OwnerDraw)
  41. {
  42. //
  43. // This is an ownerdraw combo. Have the owner tell us how tall this
  44. // item is.
  45. //
  46. int iOwnerDrawHeight;
  47. iOwnerDrawHeight = pcbox->editrc.bottom - pcbox->editrc.top;
  48. if (iOwnerDrawHeight)
  49. {
  50. dyEdit = iOwnerDrawHeight;
  51. }
  52. else
  53. {
  54. //
  55. // No height has been defined yet for the static text window. Send
  56. // a measure item message to the parent
  57. //
  58. mis.CtlType = ODT_COMBOBOX;
  59. mis.CtlID = GetWindowID(pcbox->hwnd);
  60. mis.itemID = (UINT)-1;
  61. mis.itemHeight = dyEdit;
  62. mis.itemData = 0;
  63. SendMessage(pcbox->hwndParent, WM_MEASUREITEM, mis.CtlID, (LPARAM)&mis);
  64. dyEdit = mis.itemHeight;
  65. }
  66. }
  67. //
  68. // Set the initial width to be the combo box rect. Later we will shorten it
  69. // if there is a dropdown button.
  70. //
  71. pcbox->cyCombo = 2*GetSystemMetrics(SM_CYFIXEDFRAME) + dyEdit;
  72. dxEdit = pcbox->cxCombo - (2 * GetSystemMetrics(SM_CXFIXEDFRAME));
  73. if (pcbox->cyDrop == RECALC_CYDROP)
  74. {
  75. RECT rcWindow;
  76. //
  77. // recompute the max height of the dropdown listbox -- full window
  78. // size MINUS edit/static height
  79. //
  80. GetWindowRect(pcbox->hwnd, &rcWindow);
  81. pcbox->cyDrop = max((rcWindow.bottom - rcWindow.top) - pcbox->cyCombo, 0);
  82. if (!TESTFLAG(GET_STATE2(pcbox), WS_S2_WIN40COMPAT) && (pcbox->cyDrop == 23))
  83. {
  84. //
  85. // This is VC++ 2.1's debug/release dropdown that they made super
  86. // small -- let's make 'em a wee bit bigger so the world can
  87. // continue to spin -- jeffbog -- 4/19/95 -- B#10029
  88. //
  89. pcbox->cyDrop = 28;
  90. }
  91. }
  92. //
  93. // Determine the rectangles for each of the windows... 1. Pop down button 2.
  94. // Edit control or generic window for static text or ownerdraw... 3. List
  95. // box
  96. //
  97. //
  98. // Is there a button?
  99. //
  100. if (pcbox->CBoxStyle & SDROPPABLE)
  101. {
  102. INT cxBorder, cyBorder;
  103. //
  104. // Determine button's rectangle.
  105. //
  106. if (pcbox->hTheme && SUCCEEDED(GetThemeInt(pcbox->hTheme, 0, CBXS_NORMAL, TMT_BORDERSIZE, &cxBorder)))
  107. {
  108. cyBorder = cxBorder;
  109. }
  110. else
  111. {
  112. cxBorder = g_cxEdge;
  113. cyBorder = g_cyEdge;
  114. }
  115. pcbox->buttonrc.top = cyBorder;
  116. pcbox->buttonrc.bottom = pcbox->cyCombo - cyBorder;
  117. if (pcbox->fRightAlign)
  118. {
  119. pcbox->buttonrc.left = cxBorder;
  120. pcbox->buttonrc.right = pcbox->buttonrc.left + GetSystemMetrics(SM_CXVSCROLL);
  121. }
  122. else
  123. {
  124. pcbox->buttonrc.right = pcbox->cxCombo - cxBorder;
  125. pcbox->buttonrc.left = pcbox->buttonrc.right - GetSystemMetrics(SM_CXVSCROLL);
  126. }
  127. //
  128. // Reduce the width of the edittext window to make room for the button.
  129. //
  130. dxEdit = max(dxEdit - GetSystemMetrics(SM_CXVSCROLL), 0);
  131. }
  132. else
  133. {
  134. //
  135. // No button so make the rectangle 0 so that a point in rect will always
  136. // return false.
  137. //
  138. SetRectEmpty(&pcbox->buttonrc);
  139. }
  140. //
  141. // So now, the edit rect is really the item area.
  142. //
  143. pcbox->editrc.left = GetSystemMetrics(SM_CXFIXEDFRAME);
  144. pcbox->editrc.right = pcbox->editrc.left + dxEdit;
  145. pcbox->editrc.top = GetSystemMetrics(SM_CYFIXEDFRAME);
  146. pcbox->editrc.bottom = pcbox->editrc.top + dyEdit;
  147. //
  148. // Is there a right-aligned button?
  149. //
  150. if ((pcbox->CBoxStyle & SDROPPABLE) && (pcbox->fRightAlign))
  151. {
  152. pcbox->editrc.right = pcbox->cxCombo - GetSystemMetrics(SM_CXEDGE);
  153. pcbox->editrc.left = pcbox->editrc.right - dxEdit;
  154. }
  155. lprcList->left = 0;
  156. lprcList->top = pcbox->cyCombo;
  157. lprcList->right = max(pcbox->cxDrop, pcbox->cxCombo);
  158. lprcList->bottom = pcbox->cyCombo + pcbox->cyDrop;
  159. }
  160. //---------------------------------------------------------------------------//
  161. //
  162. // ComboBox_SetDroppedSize()
  163. //
  164. // Compute the drop down window's width and max height
  165. //
  166. VOID ComboBox_SetDroppedSize(PCBOX pcbox, LPRECT lprc)
  167. {
  168. pcbox->fLBoxVisible = TRUE;
  169. ComboBox_HideListBoxWindow(pcbox, FALSE, FALSE);
  170. MoveWindow(pcbox->hwndList, lprc->left, lprc->top,
  171. lprc->right - lprc->left, lprc->bottom - lprc->top, FALSE);
  172. }
  173. //---------------------------------------------------------------------------//
  174. //
  175. // ComboBox_NcCreateHandler
  176. //
  177. // Allocates space for the CBOX structure and sets the window to point to it.
  178. //
  179. LONG ComboBox_NcCreateHandler(PCBOX pcbox, HWND hwnd)
  180. {
  181. ULONG ulStyle;
  182. ULONG ulExStyle;
  183. ULONG ulMask;
  184. pcbox->hwnd = hwnd;
  185. pcbox->pww = (PWW)GetWindowLongPtr(hwnd, GWLP_WOWWORDS);
  186. ulStyle = GET_STYLE(pcbox);
  187. ulExStyle = GET_EXSTYLE(pcbox);
  188. //
  189. // Save the style bits so that we have them when we create the client area
  190. // of the combo box window.
  191. //
  192. pcbox->styleSave = ulStyle & (WS_VSCROLL|WS_HSCROLL);
  193. if (!(ulStyle & (CBS_OWNERDRAWFIXED | CBS_OWNERDRAWVARIABLE)))
  194. {
  195. //
  196. // Add in CBS_HASSTRINGS if the style is implied...
  197. //
  198. SetWindowState(hwnd, CBS_HASSTRINGS);
  199. }
  200. ClearWindowState(hwnd, WS_VSCROLL|WS_HSCROLL|WS_BORDER);
  201. //
  202. // If the window is 4.0 compatible or has a CLIENTEDGE, draw the combo
  203. // in 3D. Otherwise, use a flat border.
  204. //
  205. if (TESTFLAG(GET_STATE2(pcbox), WS_S2_WIN40COMPAT) || TESTFLAG(ulExStyle, WS_EX_CLIENTEDGE))
  206. {
  207. pcbox->f3DCombo = TRUE;
  208. }
  209. ulMask = WS_EX_WINDOWEDGE | WS_EX_CLIENTEDGE;
  210. if ( (ulExStyle & ulMask) != 0 )
  211. {
  212. SetWindowLong(hwnd, GWL_EXSTYLE, ulExStyle & (~ ulMask));
  213. }
  214. return (LONG)TRUE;
  215. }
  216. //---------------------------------------------------------------------------//
  217. //
  218. // ComboBox_CreateHandler
  219. //
  220. // Creates all the child controls within the combo box
  221. // Returns -1 if error
  222. //
  223. LRESULT ComboBox_CreateHandler(PCBOX pcbox, HWND hwnd)
  224. {
  225. RECT rcList;
  226. RECT rcWindow;
  227. HWND hwndList;
  228. HWND hwndEdit;
  229. ULONG ulStyle;
  230. ULONG ulExStyle;
  231. ULONG ulStyleT;
  232. pcbox->hwndParent = GetParent(hwnd);
  233. pcbox->hTheme = OpenThemeData(pcbox->hwnd, L"Combobox");
  234. //
  235. // Break out the style bits so that we will be able to create the listbox
  236. // and editcontrol windows.
  237. //
  238. ulStyle = GET_STYLE(pcbox);
  239. if ((ulStyle & CBS_DROPDOWNLIST) == CBS_DROPDOWNLIST)
  240. {
  241. pcbox->CBoxStyle = SDROPDOWNLIST;
  242. pcbox->fNoEdit = TRUE;
  243. }
  244. else if ((ulStyle & CBS_DROPDOWN) == CBS_DROPDOWN)
  245. {
  246. pcbox->CBoxStyle = SDROPDOWN;
  247. }
  248. else
  249. {
  250. pcbox->CBoxStyle = SSIMPLE;
  251. }
  252. pcbox->fRtoLReading = TESTFLAG(GET_EXSTYLE(pcbox), WS_EX_RTLREADING);
  253. pcbox->fRightAlign = TESTFLAG(GET_EXSTYLE(pcbox), WS_EX_RIGHT);
  254. if (ulStyle & CBS_UPPERCASE)
  255. {
  256. pcbox->fCase = UPPERCASE;
  257. }
  258. else if (ulStyle & CBS_LOWERCASE)
  259. {
  260. pcbox->fCase = LOWERCASE;
  261. }
  262. else
  263. {
  264. pcbox->fCase = 0;
  265. }
  266. //
  267. // Listbox item flags.
  268. //
  269. if (ulStyle & CBS_OWNERDRAWVARIABLE)
  270. {
  271. pcbox->OwnerDraw = OWNERDRAWVAR;
  272. }
  273. if (ulStyle & CBS_OWNERDRAWFIXED)
  274. {
  275. pcbox->OwnerDraw = OWNERDRAWFIXED;
  276. }
  277. //
  278. // Get the size of the combo box rectangle.
  279. //
  280. // Get control sizes.
  281. GetWindowRect(hwnd, &rcWindow);
  282. pcbox->cxCombo = rcWindow.right - rcWindow.left;
  283. pcbox->cyDrop = RECALC_CYDROP;
  284. pcbox->cxDrop = 0;
  285. ComboBox_CalcControlRects(pcbox, &rcList);
  286. //
  287. // We need to do this because listboxes, as of VER40, have stopped
  288. // reinflating themselves by CXBORDER and CYBORDER.
  289. //
  290. if (!TESTFLAG(GET_STATE2(pcbox), WS_S2_WIN40COMPAT))
  291. {
  292. InflateRect(&rcList, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER));
  293. }
  294. //
  295. // Note that we have to create the listbox before the editcontrol since the
  296. // editcontrol code looks for and saves away the listbox pwnd and the
  297. // listbox pwnd will be NULL if we don't create it first. Also, hack in
  298. // some special +/- values for the listbox size due to the way we create
  299. // listboxes with borders.
  300. //
  301. ulStyleT = pcbox->styleSave;
  302. ulStyleT |= WS_CHILD | WS_VISIBLE | LBS_NOTIFY | LBS_COMBOBOX | WS_CLIPSIBLINGS;
  303. if (ulStyle & WS_DISABLED)
  304. {
  305. ulStyleT |= WS_DISABLED;
  306. }
  307. if (ulStyle & CBS_NOINTEGRALHEIGHT)
  308. {
  309. ulStyleT |= LBS_NOINTEGRALHEIGHT;
  310. }
  311. if (ulStyle & CBS_SORT)
  312. {
  313. ulStyleT |= LBS_SORT;
  314. }
  315. if (ulStyle & CBS_HASSTRINGS)
  316. {
  317. ulStyleT |= LBS_HASSTRINGS;
  318. }
  319. if (ulStyle & CBS_DISABLENOSCROLL)
  320. {
  321. ulStyleT |= LBS_DISABLENOSCROLL;
  322. }
  323. if (pcbox->OwnerDraw == OWNERDRAWVAR)
  324. {
  325. ulStyleT |= LBS_OWNERDRAWVARIABLE;
  326. }
  327. else if (pcbox->OwnerDraw == OWNERDRAWFIXED)
  328. {
  329. ulStyleT |= LBS_OWNERDRAWFIXED;
  330. }
  331. if (pcbox->CBoxStyle & SDROPPABLE)
  332. {
  333. ulStyleT |= WS_BORDER;
  334. }
  335. ulExStyle = GET_EXSTYLE(pcbox) & (WS_EX_RIGHT | WS_EX_RTLREADING | WS_EX_LEFTSCROLLBAR);
  336. hwndList = CreateWindowEx(
  337. ulExStyle | ((pcbox->CBoxStyle & SDROPPABLE) ? WS_EX_TOOLWINDOW : WS_EX_CLIENTEDGE),
  338. WC_COMBOLBOX,
  339. NULL,
  340. ulStyleT,
  341. rcList.left,
  342. rcList.top,
  343. rcList.right - rcList.left,
  344. rcList.bottom - rcList.top,
  345. hwnd,
  346. (HMENU)CBLISTBOXID,
  347. GetWindowInstance(hwnd),
  348. NULL);
  349. pcbox->hwndList = hwndList;
  350. if (!pcbox->hwndList)
  351. {
  352. return -1;
  353. }
  354. //
  355. // Override the listbox's theme with combobox
  356. //
  357. SetWindowTheme(pcbox->hwndList, L"Combobox", NULL);
  358. //
  359. // Create either the edit control or the static text rectangle.
  360. //
  361. if (pcbox->fNoEdit)
  362. {
  363. //
  364. // No editcontrol so we will draw text directly into the combo box
  365. // window.
  366. //
  367. // Don't lock the combobox window: this would prevent WM_FINALDESTROY
  368. // being sent to it, so pwnd and pcbox wouldn't get freed (zombies)
  369. // until thread cleanup. (IanJa) LATER: change name from spwnd to pwnd.
  370. // Lock(&(pcbox->spwndEdit), pcbox->spwnd); - caused a 'catch-22'
  371. //
  372. pcbox->hwndEdit = pcbox->hwnd;
  373. }
  374. else
  375. {
  376. ulStyleT = WS_CHILD | WS_VISIBLE | ES_COMBOBOX | ES_NOHIDESEL;
  377. if (ulStyle & WS_DISABLED)
  378. {
  379. ulStyleT |= WS_DISABLED;
  380. }
  381. if (ulStyle & CBS_AUTOHSCROLL)
  382. {
  383. ulStyleT |= ES_AUTOHSCROLL;
  384. }
  385. if (ulStyle & CBS_OEMCONVERT)
  386. {
  387. ulStyleT |= ES_OEMCONVERT;
  388. }
  389. if (pcbox->fCase)
  390. {
  391. ulStyleT |= (pcbox->fCase & UPPERCASE) ? ES_UPPERCASE : ES_LOWERCASE;
  392. }
  393. //
  394. // Edit control need to know whether original CreateWindow*() call
  395. // was ANSI or Unicode.
  396. //
  397. if (ulExStyle & WS_EX_RIGHT)
  398. {
  399. ulStyleT |= ES_RIGHT;
  400. }
  401. hwndEdit = CreateWindowEx(
  402. ulExStyle,
  403. WC_EDIT,
  404. NULL,
  405. ulStyleT,
  406. pcbox->editrc.left,
  407. pcbox->editrc.top,
  408. pcbox->editrc.right - pcbox->editrc.left,
  409. pcbox->editrc.bottom - pcbox->editrc.top,
  410. hwnd,
  411. (HMENU)CBEDITID,
  412. GetWindowInstance(hwnd),
  413. NULL);
  414. pcbox->hwndEdit = hwndEdit;
  415. //
  416. // Override the edit's theme with combobox
  417. //
  418. SetWindowTheme(pcbox->hwndEdit, L"Combobox", NULL);
  419. }
  420. if (!pcbox->hwndEdit)
  421. {
  422. return -1L;
  423. }
  424. pcbox->iMinVisible = DEFAULT_MINVISIBLE;
  425. if (pcbox->CBoxStyle & SDROPPABLE)
  426. {
  427. ShowWindow(hwndList, SW_HIDE);
  428. SetParent(hwndList, NULL);
  429. //
  430. // We need to do this so dropped size works right
  431. //
  432. if (!TESTFLAG(GET_STATE2(pcbox), WS_S2_WIN40COMPAT))
  433. {
  434. InflateRect(&rcList, GetSystemMetrics(SM_CXBORDER), GetSystemMetrics(SM_CYBORDER));
  435. }
  436. ComboBox_SetDroppedSize(pcbox, &rcList);
  437. }
  438. //
  439. // return anything as long as it's not -1L (-1L == error)
  440. //
  441. return (LRESULT)hwnd;
  442. }
  443. //---------------------------------------------------------------------------//
  444. //
  445. // ComboBox_NcDestroyHandler
  446. //
  447. // Destroys the combobox and frees up all memory used by it
  448. //
  449. VOID ComboBox_NcDestroyHandler(HWND hwnd, PCBOX pcbox)
  450. {
  451. //
  452. // If there is no pcbox, there is nothing to clean up.
  453. //
  454. if (pcbox != NULL)
  455. {
  456. //
  457. // Destroy the list box here so that it'll send WM_DELETEITEM messages
  458. // before the combo box turns into a zombie.
  459. //
  460. if (pcbox->hwndList != NULL)
  461. {
  462. DestroyWindow(pcbox->hwndList);
  463. pcbox->hwndList = NULL;
  464. }
  465. pcbox->hwnd = NULL;
  466. pcbox->hwndParent = NULL;
  467. //
  468. // If there is no editcontrol, spwndEdit is the combobox window which
  469. // isn't locked (that would have caused a 'catch-22').
  470. //
  471. if (hwnd != pcbox->hwndEdit)
  472. {
  473. pcbox->hwndEdit = NULL;
  474. }
  475. if (pcbox->hTheme != NULL)
  476. {
  477. CloseThemeData(pcbox->hTheme);
  478. }
  479. //
  480. // free the combobox instance structure
  481. //
  482. UserLocalFree(pcbox);
  483. }
  484. TraceMsg(TF_STANDARD, "COMBOBOX: Clearing combobox instance pointer.");
  485. ComboBox_SetPtr(hwnd, NULL);
  486. }
  487. //---------------------------------------------------------------------------//
  488. VOID ComboBox_SetFontHandler(PCBOX pcbox, HANDLE hFont, BOOL fRedraw)
  489. {
  490. pcbox->hFont = hFont;
  491. if (!pcbox->fNoEdit && pcbox->hwndEdit)
  492. {
  493. SendMessage(pcbox->hwndEdit, WM_SETFONT, (WPARAM)hFont, FALSE);
  494. }
  495. SendMessage(pcbox->hwndList, WM_SETFONT, (WPARAM)hFont, FALSE);
  496. //
  497. // Recalculate the layout of controls. This will hide the listbox also.
  498. //
  499. ComboBox_Position(pcbox);
  500. if (fRedraw)
  501. {
  502. InvalidateRect(pcbox->hwnd, NULL, TRUE);
  503. }
  504. }
  505. //---------------------------------------------------------------------------//
  506. //
  507. // ComboBox_SetEditItemHeight
  508. //
  509. // Sets the height of the edit/static item of a combo box.
  510. //
  511. LONG ComboBox_SetEditItemHeight(PCBOX pcbox, int dyEdit)
  512. {
  513. if (dyEdit > 255)
  514. {
  515. TraceMsg(TF_STANDARD, "CCCombobox: CBSetEditItmeHeight: Invalid Parameter dwEdit = %d", dyEdit);
  516. return CB_ERR;
  517. }
  518. pcbox->editrc.bottom = pcbox->editrc.top + dyEdit;
  519. pcbox->cyCombo = pcbox->editrc.bottom + GetSystemMetrics(SM_CYFIXEDFRAME);
  520. if (pcbox->CBoxStyle & SDROPPABLE)
  521. {
  522. int cyBorder = g_cyEdge;
  523. if ( pcbox->hTheme )
  524. {
  525. GetThemeInt(pcbox->hTheme, 0, CBXS_NORMAL, TMT_BORDERSIZE, &cyBorder);
  526. }
  527. pcbox->buttonrc.bottom = pcbox->cyCombo - cyBorder;
  528. }
  529. //
  530. // Reposition the editfield.
  531. // Don't let spwndEdit or List of NULL go through; if someone adjusts
  532. // the height on a NCCREATE; same as not having
  533. // HW instead of HWq but we don't go to the kernel.
  534. //
  535. if (!pcbox->fNoEdit && pcbox->hwndEdit)
  536. {
  537. MoveWindow(pcbox->hwndEdit, pcbox->editrc.left, pcbox->editrc.top,
  538. pcbox->editrc.right-pcbox->editrc.left, dyEdit, TRUE);
  539. }
  540. //
  541. // Reposition the list and combobox windows.
  542. //
  543. if (pcbox->CBoxStyle == SSIMPLE)
  544. {
  545. if (pcbox->hwndList != 0)
  546. {
  547. RECT rcList;
  548. MoveWindow(pcbox->hwndList, 0, pcbox->cyCombo, pcbox->cxCombo,
  549. pcbox->cyDrop, FALSE);
  550. GetWindowRect(pcbox->hwndList, &rcList);
  551. SetWindowPos(pcbox->hwnd, HWND_TOP, 0, 0,
  552. pcbox->cxCombo, pcbox->cyCombo +
  553. rcList.bottom - rcList.top,
  554. SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
  555. }
  556. }
  557. else
  558. {
  559. RECT rcWindow;
  560. GetWindowRect(pcbox->hwnd, &rcWindow);
  561. if (pcbox->hwndList != NULL)
  562. {
  563. MoveWindow(pcbox->hwndList, rcWindow.left,
  564. rcWindow.top + pcbox->cyCombo,
  565. max(pcbox->cxDrop, pcbox->cxCombo), pcbox->cyDrop, FALSE);
  566. }
  567. SetWindowPos(pcbox->hwnd, HWND_TOP, 0, 0,
  568. pcbox->cxCombo, pcbox->cyCombo,
  569. SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
  570. }
  571. return CB_OKAY;
  572. }
  573. //---------------------------------------------------------------------------//
  574. //
  575. // ComboBox_SizeHandler
  576. //
  577. // Recalculates the sizes of the internal controls in response to a
  578. // resizing of the combo box window. The app must size the combo box to its
  579. // maximum open/dropped down size.
  580. //
  581. VOID ComboBox_SizeHandler(PCBOX pcbox)
  582. {
  583. RECT rcWindow;
  584. //
  585. // Assume listbox is visible since the app should size it to its maximum
  586. // visible size.
  587. //
  588. GetWindowRect(pcbox->hwnd, &rcWindow);
  589. pcbox->cxCombo = RECTWIDTH(rcWindow);
  590. if (RECTHEIGHT(rcWindow) > pcbox->cyCombo)
  591. {
  592. pcbox->cyDrop = RECALC_CYDROP;
  593. }
  594. //
  595. // Reposition everything.
  596. //
  597. ComboBox_Position(pcbox);
  598. }
  599. //---------------------------------------------------------------------------//
  600. //
  601. // ComboBox_Position()
  602. //
  603. // Repositions components of edit control.
  604. //
  605. VOID ComboBox_Position(PCBOX pcbox)
  606. {
  607. RECT rcList;
  608. //
  609. // Calculate placement of components--button, item, list
  610. //
  611. ComboBox_CalcControlRects(pcbox, &rcList);
  612. if (!pcbox->fNoEdit && pcbox->hwndEdit)
  613. {
  614. MoveWindow(pcbox->hwndEdit, pcbox->editrc.left, pcbox->editrc.top,
  615. pcbox->editrc.right - pcbox->editrc.left,
  616. pcbox->editrc.bottom - pcbox->editrc.top, TRUE);
  617. }
  618. //
  619. // Recalculate drop height & width
  620. //
  621. ComboBox_SetDroppedSize(pcbox, &rcList);
  622. }