Leaked source code of windows server 2003
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.

641 lines
21 KiB

  1. /**************************** Module Header ********************************\
  2. * Module Name: comboini.c
  3. *
  4. * Copyright (c) 1985 - 1999, Microsoft Corporation
  5. *
  6. * All the (one time) initialization/destruction code used for combo boxes
  7. *
  8. * History:
  9. * 12-05-90 IanJa Ported
  10. * 01-Feb-1991 mikeke Added Revalidation code
  11. * 20-Jan-1992 IanJa ANSI/UNIOCDE netralization
  12. \***************************************************************************/
  13. #include "precomp.h"
  14. #pragma hdrstop
  15. extern LOOKASIDE ComboboxLookaside;
  16. #define RECALC_CYDROP -1
  17. void xxxCBSetDroppedSize(PCBOX pcbox, LPRECT lprc);
  18. /***************************************************************************\
  19. * CBNcCreateHandler
  20. *
  21. * Allocates space for the CBOX structure and sets the window to point to it.
  22. *
  23. * History:
  24. \***************************************************************************/
  25. LONG CBNcCreateHandler(
  26. PCBOX pcbox,
  27. PWND pwnd)
  28. {
  29. /*
  30. * Save the style bits so that we have them when we create the client area
  31. * of the combo box window.
  32. */
  33. pcbox->styleSave = pwnd->style & (WS_VSCROLL | WS_HSCROLL);
  34. if (!TestWF(pwnd, CBFOWNERDRAW))
  35. // Add in CBS_HASSTRINGS if the style is implied...
  36. SetWindowState(pwnd, CBFHASSTRINGS);
  37. UserAssert(HIBYTE(WFVSCROLL) == HIBYTE(WFHSCROLL));
  38. UserAssert(HIBYTE(WFHSCROLL) == HIBYTE(WFBORDER));
  39. ClearWindowState(pwnd, WFVSCROLL | WFHSCROLL | WFBORDER);
  40. //
  41. // If the window is 4.0 compatible or has a CLIENTEDGE, draw the combo
  42. // in 3D. Otherwise, use a flat border.
  43. //
  44. if (TestWF(pwnd, WFWIN40COMPAT) || TestWF(pwnd, WEFCLIENTEDGE))
  45. pcbox->f3DCombo = TRUE;
  46. ClearWindowState(pwnd, WEFEDGEMASK);
  47. return (LONG)TRUE;
  48. }
  49. /***************************************************************************\
  50. * xxxCBCreateHandler
  51. *
  52. * Creates all the child controls within the combo box
  53. * Returns -1 if error
  54. *
  55. * History:
  56. \***************************************************************************/
  57. LRESULT xxxCBCreateHandler(
  58. PCBOX pcbox,
  59. PWND pwnd)
  60. {
  61. LONG lStyleT;
  62. RECT rcList;
  63. HWND hwndList;
  64. HWND hwndEdit;
  65. DWORD lExStyle;
  66. CheckLock(pwnd);
  67. /*
  68. * Don't lock the combobox window: this would prevent WM_FINALDESTROY
  69. * being sent to it, so pwnd and pcbox wouldn't get freed (zombies)
  70. * until thread cleanup. (IanJa) LATER: change name from spwnd to pwnd.
  71. * Lock(&pcbox->spwnd, pwnd); - caused a 'catch-22'
  72. */
  73. Lock(&(pcbox->spwndParent), REBASEPWND(pwnd, spwndParent));
  74. /*
  75. * Break out the style bits so that we will be able to create the listbox
  76. * and editcontrol windows.
  77. */
  78. if (TestWF(pwnd, CBFDROPDOWNLIST) == LOBYTE(CBFDROPDOWNLIST)) {
  79. pcbox->CBoxStyle = SDROPDOWNLIST;
  80. pcbox->fNoEdit = TRUE;
  81. } else if (TestWF(pwnd, CBFDROPDOWN))
  82. pcbox->CBoxStyle = SDROPDOWN;
  83. else
  84. pcbox->CBoxStyle = SSIMPLE;
  85. pcbox->fRtoLReading = (TestWF(pwnd, WEFRTLREADING) != 0);
  86. pcbox->fRightAlign = (TestWF(pwnd, WEFRIGHT) != 0);
  87. if (TestWF(pwnd, CBFUPPERCASE))
  88. pcbox->fCase = UPPERCASE;
  89. else if (TestWF(pwnd, CBFLOWERCASE))
  90. pcbox->fCase = LOWERCASE;
  91. else
  92. pcbox->fCase = 0;
  93. // Listbox item flags.
  94. if (TestWF(pwnd, CBFOWNERDRAWVAR))
  95. pcbox->OwnerDraw = OWNERDRAWVAR;
  96. if (TestWF(pwnd, CBFOWNERDRAWFIXED)) {
  97. pcbox->OwnerDraw = OWNERDRAWFIXED;
  98. }
  99. /*
  100. * Get the size of the combo box rectangle.
  101. */
  102. // Get control sizes.
  103. pcbox->cxCombo = pwnd->rcWindow.right - pwnd->rcWindow.left;
  104. pcbox->cyDrop = RECALC_CYDROP;
  105. pcbox->cxDrop = 0;
  106. xxxCBCalcControlRects(pcbox, &rcList);
  107. //
  108. // We need to do this because listboxes, as of VER40, have stopped
  109. // reinflating themselves by CXBORDER and CYBORDER.
  110. //
  111. if (!TestWF(pwnd, WFWIN40COMPAT))
  112. InflateRect(&rcList, -SYSMET(CXBORDER), -SYSMET(CYBORDER));
  113. /*
  114. * Note that we have to create the listbox before the editcontrol since the
  115. * editcontrol code looks for and saves away the listbox pwnd and the
  116. * listbox pwnd will be NULL if we don't create it first. Also, hack in
  117. * some special +/- values for the listbox size due to the way we create
  118. * listboxes with borders.
  119. */
  120. lStyleT = pcbox->styleSave;
  121. lStyleT |= WS_CHILD | WS_VISIBLE | LBS_NOTIFY | LBS_COMBOBOX | WS_CLIPSIBLINGS;
  122. if (TestWF(pwnd, WFDISABLED))
  123. lStyleT |= WS_DISABLED;
  124. if (TestWF(pwnd, CBFNOINTEGRALHEIGHT))
  125. lStyleT |= LBS_NOINTEGRALHEIGHT;
  126. if (TestWF(pwnd, CBFSORT))
  127. lStyleT |= LBS_SORT;
  128. if (TestWF(pwnd, CBFHASSTRINGS))
  129. lStyleT |= LBS_HASSTRINGS;
  130. if (TestWF(pwnd, CBFDISABLENOSCROLL))
  131. lStyleT |= LBS_DISABLENOSCROLL;
  132. if (pcbox->OwnerDraw == OWNERDRAWVAR)
  133. lStyleT |= LBS_OWNERDRAWVARIABLE;
  134. else if (pcbox->OwnerDraw == OWNERDRAWFIXED)
  135. lStyleT |= LBS_OWNERDRAWFIXED;
  136. if (pcbox->CBoxStyle & SDROPPABLE)
  137. lStyleT |= WS_BORDER;
  138. lExStyle = pwnd->ExStyle & (WS_EX_RIGHT | WS_EX_RTLREADING | WS_EX_LEFTSCROLLBAR);
  139. hwndList = _CreateWindowEx(lExStyle |
  140. ((pcbox->CBoxStyle & SDROPPABLE) ? WS_EX_TOOLWINDOW : WS_EX_CLIENTEDGE),
  141. MAKEINTRESOURCE(gpsi->atomSysClass[ICLS_COMBOLISTBOX]), NULL, lStyleT,
  142. rcList.left, rcList.top, rcList.right - rcList.left,
  143. rcList.bottom - rcList.top,
  144. HW(pwnd), (HMENU)CBLISTBOXID, KHANDLE_TO_HANDLE(pcbox->spwnd->hModule), NULL,
  145. 0);
  146. Lock(&(pcbox->spwndList), ValidateHwnd(hwndList));
  147. if (!pcbox->spwndList) {
  148. return -1;
  149. }
  150. /*
  151. * Create either the edit control or the static text rectangle.
  152. */
  153. if (pcbox->fNoEdit) {
  154. /*
  155. * No editcontrol so we will draw text directly into the combo box
  156. * window.
  157. */
  158. /*
  159. * Don't lock the combobox window: this would prevent WM_FINALDESTROY
  160. * being sent to it, so pwnd and pcbox wouldn't get freed (zombies)
  161. * until thread cleanup. (IanJa) LATER: change name from spwnd to pwnd.
  162. * Lock(&(pcbox->spwndEdit), pcbox->spwnd); - caused a 'catch-22'
  163. */
  164. pcbox->spwndEdit = pcbox->spwnd;
  165. } else {
  166. DWORD dwCsFlags;
  167. lStyleT = WS_CHILD | WS_VISIBLE | ES_COMBOBOX | ES_NOHIDESEL;
  168. if (TestWF(pwnd, WFDISABLED))
  169. lStyleT |= WS_DISABLED;
  170. if (TestWF(pwnd, CBFAUTOHSCROLL))
  171. lStyleT |= ES_AUTOHSCROLL;
  172. if (TestWF(pwnd, CBFOEMCONVERT))
  173. lStyleT |= ES_OEMCONVERT;
  174. if (pcbox->fCase)
  175. lStyleT |= (pcbox->fCase & UPPERCASE) ? ES_UPPERCASE : ES_LOWERCASE;
  176. /*
  177. * Edit control need to know whether original CreateWindow*() call
  178. * was ANSI or Unicode.
  179. */
  180. dwCsFlags = TestWF(pcbox->spwnd, WFANSICREATOR) ? CW_FLAGS_ANSI : 0L;
  181. if (lExStyle & WS_EX_RIGHT)
  182. lStyleT |= ES_RIGHT;
  183. hwndEdit = _CreateWindowEx(lExStyle,
  184. MAKEINTRESOURCE(gpsi->atomSysClass[ICLS_EDIT]), NULL, lStyleT,
  185. pcbox->editrc.left, pcbox->editrc.top,
  186. pcbox->editrc.right - pcbox->editrc.left, pcbox->editrc.bottom -
  187. pcbox->editrc.top, HW(pwnd), (HMENU)CBEDITID,
  188. KHANDLE_TO_HANDLE(pcbox->spwnd->hModule), NULL,
  189. dwCsFlags);
  190. Lock(&(pcbox->spwndEdit), ValidateHwnd(hwndEdit));
  191. }
  192. if (!pcbox->spwndEdit)
  193. return -1L;
  194. if (pcbox->CBoxStyle & SDROPPABLE) {
  195. NtUserShowWindow(hwndList, SW_HIDE);
  196. NtUserSetParent(hwndList, NULL);
  197. // We need to do this so dropped size works right
  198. if (!TestWF(pwnd, WFWIN40COMPAT))
  199. InflateRect(&rcList, SYSMET(CXBORDER), SYSMET(CYBORDER));
  200. xxxCBSetDroppedSize(pcbox, &rcList);
  201. }
  202. /*
  203. * return anything as long as it's not -1L (-1L == error)
  204. */
  205. return (LRESULT)pwnd;
  206. }
  207. /***************************************************************************\
  208. * xxxCBCalcControlRects
  209. *
  210. * History:
  211. \***************************************************************************/
  212. void xxxCBCalcControlRects(PCBOX pcbox, LPRECT lprcList)
  213. {
  214. HDC hdc;
  215. HANDLE hOldFont = NULL;
  216. int dyEdit, dxEdit;
  217. MEASUREITEMSTRUCT mis;
  218. SIZE size;
  219. HWND hwnd = HWq(pcbox->spwnd);
  220. TL tlpwndParent;
  221. CheckLock(pcbox->spwnd);
  222. /*
  223. * Determine height of the edit control. We can use this info to center
  224. * the button with recpect to the edit/static text window. For example
  225. * this will be useful if owner draw and this window is tall.
  226. */
  227. hdc = NtUserGetDC(hwnd);
  228. if (pcbox->hFont) {
  229. hOldFont = SelectObject(hdc, pcbox->hFont);
  230. }
  231. // Add on CYEDGE just for some extra space in the edit field/static item.
  232. // It's really only for static text items, but we want static & editable
  233. // controls to be the same height.
  234. GetTextExtentPoint(hdc, szOneChar, 1, &size);
  235. dyEdit = size.cy + SYSMET(CYEDGE);
  236. if (hOldFont) {
  237. SelectObject(hdc, hOldFont);
  238. }
  239. /*
  240. * IanJa: was ReleaseDC(pcbox->hwnd, hdc);
  241. */
  242. NtUserReleaseDC(hwnd, hdc);
  243. if (pcbox->OwnerDraw) {
  244. // This is an ownerdraw combo. Have the owner tell us how tall this
  245. // item is.
  246. int iOwnerDrawHeight;
  247. if (iOwnerDrawHeight = pcbox->editrc.bottom - pcbox->editrc.top) {
  248. dyEdit = iOwnerDrawHeight;
  249. } else {
  250. /*
  251. * No height has been defined yet for the static text window. Send
  252. * a measure item message to the parent
  253. */
  254. mis.CtlType = ODT_COMBOBOX;
  255. mis.CtlID = PtrToUlong(pcbox->spwnd->spmenu);
  256. mis.itemID = (UINT)-1;
  257. mis.itemHeight = dyEdit;
  258. mis.itemData = 0;
  259. ThreadLock(pcbox->spwndParent, &tlpwndParent);
  260. SendMessage(HW(pcbox->spwndParent), WM_MEASUREITEM, mis.CtlID, (LPARAM)&mis);
  261. ThreadUnlock(&tlpwndParent);
  262. dyEdit = mis.itemHeight;
  263. }
  264. }
  265. /*
  266. * Set the initial width to be the combo box rect. Later we will shorten it
  267. * if there is a dropdown button.
  268. */
  269. pcbox->cyCombo = 2*SYSMET(CYFIXEDFRAME) + dyEdit;
  270. dxEdit = pcbox->cxCombo - (2 * SYSMET(CXFIXEDFRAME));
  271. if (pcbox->cyDrop == RECALC_CYDROP)
  272. {
  273. // recompute the max height of the dropdown listbox -- full window
  274. // size MINUS edit/static height
  275. pcbox->cyDrop = max((pcbox->spwnd->rcWindow.bottom - pcbox->spwnd->rcWindow.top) - pcbox->cyCombo, 0);
  276. if (!TestWF(pcbox->spwnd, WFWIN40COMPAT) && (pcbox->cyDrop == 23))
  277. // This is VC++ 2.1's debug/release dropdown that they made super
  278. // small -- let's make 'em a wee bit bigger so the world can
  279. // continue to spin -- jeffbog -- 4/19/95 -- B#10029
  280. pcbox->cyDrop = 28;
  281. }
  282. /*
  283. * Determine the rectangles for each of the windows... 1. Pop down button 2.
  284. * Edit control or generic window for static text or ownerdraw... 3. List
  285. * box
  286. */
  287. // Is there a button?
  288. if (pcbox->CBoxStyle & SDROPPABLE) {
  289. // Determine button's rectangle.
  290. pcbox->buttonrc.top = SYSMET(CYEDGE);
  291. pcbox->buttonrc.bottom = pcbox->cyCombo - SYSMET(CYEDGE);
  292. if (pcbox->fRightAlign) {
  293. pcbox->buttonrc.left = SYSMET(CXFIXEDFRAME);
  294. pcbox->buttonrc.right = pcbox->buttonrc.left + SYSMET(CXVSCROLL);
  295. } else {
  296. pcbox->buttonrc.right = pcbox->cxCombo - SYSMET(CXEDGE);
  297. pcbox->buttonrc.left = pcbox->buttonrc.right - SYSMET(CXVSCROLL);
  298. }
  299. // Reduce the width of the edittext window to make room for the button.
  300. dxEdit = max(dxEdit - SYSMET(CXVSCROLL), 0);
  301. } else {
  302. /*
  303. * No button so make the rectangle 0 so that a point in rect will always
  304. * return false.
  305. */
  306. SetRectEmpty(KPRECT_TO_PRECT(&pcbox->buttonrc));
  307. }
  308. /*
  309. * So now, the edit rect is really the item area.
  310. */
  311. pcbox->editrc.left = SYSMET(CXFIXEDFRAME);
  312. pcbox->editrc.right = pcbox->editrc.left + dxEdit;
  313. pcbox->editrc.top = SYSMET(CYFIXEDFRAME);
  314. pcbox->editrc.bottom = pcbox->editrc.top + dyEdit;
  315. // Is there a right-aligned button?
  316. if ((pcbox->CBoxStyle & SDROPPABLE) && (pcbox->fRightAlign)) {
  317. pcbox->editrc.right = pcbox->cxCombo - SYSMET(CXEDGE);
  318. pcbox->editrc.left = pcbox->editrc.right - dxEdit;
  319. }
  320. lprcList->left = 0;
  321. lprcList->top = pcbox->cyCombo;
  322. lprcList->right = max(pcbox->cxDrop, pcbox->cxCombo);
  323. lprcList->bottom = pcbox->cyCombo + pcbox->cyDrop;
  324. }
  325. /***************************************************************************\
  326. * xxxCBNcDestroyHandler
  327. *
  328. * Destroys the combobox and frees up all memory used by it
  329. *
  330. * History:
  331. \***************************************************************************/
  332. void xxxCBNcDestroyHandler(
  333. PWND pwnd,
  334. PCBOX pcbox)
  335. {
  336. CheckLock(pwnd);
  337. /*
  338. * If there is no pcbox, there is nothing to clean up.
  339. */
  340. if (pcbox != NULL) {
  341. /*
  342. * [msadek, 02/04/2001] fInDestroy is used to prevent oing through destruction code twice.
  343. * This code happen when apps like Delphi 5 tries to destroy the combobox again during processing of
  344. * WM_PARENTNOTIFY in the NtUserDestroyWindow call (below). Thus, we end up freeing the same lookaside entry twice.
  345. * Windows Bugs bug# 266084
  346. */
  347. if (!pcbox->fInDestroy) {
  348. pcbox->fInDestroy = TRUE;
  349. /*
  350. * Destroy the list box here so that it'll send WM_DELETEITEM messages
  351. * before the combo box turns into a zombie.
  352. */
  353. if (pcbox->spwndList != NULL) {
  354. NtUserDestroyWindow(HWq(pcbox->spwndList));
  355. Unlock(&pcbox->spwndList);
  356. }
  357. pcbox->spwnd = NULL;
  358. Unlock(&pcbox->spwndParent);
  359. /*
  360. * If there is no editcontrol, spwndEdit is the combobox window which
  361. * isn't locked (that would have caused a 'catch-22').
  362. */
  363. if (pwnd != pcbox->spwndEdit) {
  364. Unlock(&pcbox->spwndEdit);
  365. }
  366. /*
  367. * Since a pointer and a handle to a fixed local object are the same.
  368. */
  369. FreeLookasideEntry(&ComboboxLookaside, KPVOID_TO_PVOID(pcbox));
  370. }
  371. else {
  372. RIPMSG1(RIP_WARNING, "Trying to destroy the same combobox %x twice. Ignoring", pcbox);
  373. }
  374. }
  375. /*
  376. * Set the window's fnid status so that we can ignore rogue messages
  377. */
  378. NtUserSetWindowFNID(HWq(pwnd), FNID_CLEANEDUP_BIT);
  379. }
  380. /***************************************************************************\
  381. * xxxCBSetFontHandler
  382. *
  383. * History:
  384. \***************************************************************************/
  385. void xxxCBSetFontHandler(
  386. PCBOX pcbox,
  387. HANDLE hFont,
  388. BOOL fRedraw)
  389. {
  390. TL tlpwndEdit;
  391. TL tlpwndList;
  392. CheckLock(pcbox->spwnd);
  393. ThreadLock(pcbox->spwndEdit, &tlpwndEdit);
  394. ThreadLock(pcbox->spwndList, &tlpwndList);
  395. pcbox->hFont = hFont;
  396. if (!pcbox->fNoEdit && pcbox->spwndEdit) {
  397. SendMessageWorker(pcbox->spwndEdit, WM_SETFONT, (WPARAM)hFont, FALSE, FALSE);
  398. }
  399. SendMessageWorker(pcbox->spwndList, WM_SETFONT, (WPARAM)hFont, FALSE, FALSE);
  400. // Recalculate the layout of controls. This will hide the listbox also.
  401. xxxCBPosition(pcbox);
  402. if (fRedraw) {
  403. NtUserInvalidateRect(HWq(pcbox->spwnd), NULL, TRUE);
  404. // LATER UpdateWindow(HW(pcbox->spwnd));
  405. }
  406. ThreadUnlock(&tlpwndList);
  407. ThreadUnlock(&tlpwndEdit);
  408. }
  409. /***************************************************************************\
  410. * xxxCBSetEditItemHeight
  411. *
  412. * Sets the height of the edit/static item of a combo box.
  413. *
  414. * History:
  415. * 06-27-91 DarrinM Ported from Win 3.1.
  416. \***************************************************************************/
  417. LONG xxxCBSetEditItemHeight(
  418. PCBOX pcbox,
  419. int dyEdit)
  420. {
  421. TL tlpwndEdit;
  422. TL tlpwndList;
  423. CheckLock(pcbox->spwnd);
  424. if (dyEdit > 255) {
  425. RIPERR0(ERROR_INVALID_EDIT_HEIGHT, RIP_VERBOSE, "");
  426. return CB_ERR;
  427. }
  428. pcbox->editrc.bottom = pcbox->editrc.top + dyEdit;
  429. pcbox->cyCombo = pcbox->editrc.bottom + SYSMET(CYFIXEDFRAME);
  430. if (pcbox->CBoxStyle & SDROPPABLE) {
  431. pcbox->buttonrc.bottom = pcbox->cyCombo - SYSMET(CYEDGE);
  432. }
  433. ThreadLock(pcbox->spwndEdit, &tlpwndEdit);
  434. ThreadLock(pcbox->spwndList, &tlpwndList);
  435. /*
  436. * Reposition the editfield.
  437. * Don't let spwndEdit or List of NULL go through; if someone adjusts
  438. * the height on a NCCREATE; same as not having
  439. * HW instead of HWq but we don't go to the kernel.
  440. */
  441. if (!pcbox->fNoEdit && pcbox->spwndEdit) {
  442. NtUserMoveWindow(HWq(pcbox->spwndEdit), pcbox->editrc.left, pcbox->editrc.top,
  443. pcbox->editrc.right-pcbox->editrc.left, dyEdit, TRUE);
  444. }
  445. /*
  446. * Reposition the list and combobox windows.
  447. */
  448. if (pcbox->CBoxStyle == SSIMPLE) {
  449. if (pcbox->spwndList != 0) {
  450. NtUserMoveWindow(HWq(pcbox->spwndList), 0, pcbox->cyCombo, pcbox->cxCombo,
  451. pcbox->cyDrop, FALSE);
  452. NtUserSetWindowPos(HWq(pcbox->spwnd), HWND_TOP, 0, 0,
  453. pcbox->cxCombo, pcbox->cyCombo +
  454. pcbox->spwndList->rcWindow.bottom - pcbox->spwndList->rcWindow.top,
  455. SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
  456. }
  457. } else {
  458. if (pcbox->spwndList != NULL) {
  459. NtUserMoveWindow(HWq(pcbox->spwndList), pcbox->spwnd->rcWindow.left,
  460. pcbox->spwnd->rcWindow.top + pcbox->cyCombo,
  461. max(pcbox->cxDrop, pcbox->cxCombo), pcbox->cyDrop, FALSE);
  462. }
  463. NtUserSetWindowPos(HWq(pcbox->spwnd), HWND_TOP, 0, 0,
  464. pcbox->cxCombo, pcbox->cyCombo,
  465. SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
  466. }
  467. ThreadUnlock(&tlpwndList);
  468. ThreadUnlock(&tlpwndEdit);
  469. return CB_OKAY;
  470. }
  471. /***************************************************************************\
  472. * xxxCBSizeHandler
  473. *
  474. * Recalculates the sizes of the internal controls in response to a
  475. * resizing of the combo box window. The app must size the combo box to its
  476. * maximum open/dropped down size.
  477. *
  478. * History:
  479. \***************************************************************************/
  480. void xxxCBSizeHandler(
  481. PCBOX pcbox)
  482. {
  483. CheckLock(pcbox->spwnd);
  484. /*
  485. * Assume listbox is visible since the app should size it to its maximum
  486. * visible size.
  487. */
  488. pcbox->cxCombo = pcbox->spwnd->rcWindow.right - pcbox->spwnd->rcWindow.left;
  489. // only recalc cyDrop if the drop down is not TOTALLY nuked by the sizing
  490. // -- Visio 1.0 -- B#13112
  491. if (((pcbox->spwnd->rcWindow.bottom - pcbox->spwnd->rcWindow.top) - pcbox->cyCombo) > 0)
  492. pcbox->cyDrop = RECALC_CYDROP;
  493. // Reposition everything.
  494. xxxCBPosition(pcbox);
  495. }
  496. /***************************************************************************\
  497. *
  498. * CBPosition()
  499. *
  500. * Repositions components of edit control.
  501. *
  502. \***************************************************************************/
  503. void xxxCBPosition(PCBOX pcbox)
  504. {
  505. RECT rcList;
  506. // Calculate placement of components--button, item, list
  507. xxxCBCalcControlRects(pcbox, &rcList);
  508. if (!pcbox->fNoEdit && pcbox->spwndEdit) {
  509. TL tlpwndEdit;
  510. ThreadLock(pcbox->spwndEdit, &tlpwndEdit);
  511. NtUserMoveWindow(HWq(pcbox->spwndEdit), pcbox->editrc.left, pcbox->editrc.top,
  512. pcbox->editrc.right - pcbox->editrc.left,
  513. pcbox->editrc.bottom - pcbox->editrc.top, TRUE);
  514. ThreadUnlock(&tlpwndEdit);
  515. }
  516. // Recalculate drop height & width
  517. xxxCBSetDroppedSize(pcbox, &rcList);
  518. }
  519. /***************************************************************************\
  520. *
  521. * CBSetDroppedSize()
  522. *
  523. * Compute the drop down window's width and max height
  524. *
  525. \***************************************************************************/
  526. void xxxCBSetDroppedSize(PCBOX pcbox, LPRECT lprc)
  527. {
  528. TL tlpwndList;
  529. pcbox->fLBoxVisible = TRUE;
  530. xxxCBHideListBoxWindow(pcbox, FALSE, FALSE);
  531. ThreadLock(pcbox->spwndList, &tlpwndList);
  532. NtUserMoveWindow(HWq(pcbox->spwndList), lprc->left, lprc->top,
  533. lprc->right - lprc->left, lprc->bottom - lprc->top, FALSE);
  534. ThreadUnlock(&tlpwndList);
  535. }