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.

873 lines
25 KiB

  1. /****************************** Module Header ********************************\
  2. * Module Name: lb1.c
  3. *
  4. * Copyright (c) 1985 - 1999, Microsoft Corporation
  5. *
  6. * ListBox routines
  7. *
  8. * History:
  9. * ??-???-???? ianja Ported from Win 3.0 sources
  10. * 14-Feb-1991 mikeke Added Revalidation code
  11. \*****************************************************************************/
  12. #include "precomp.h"
  13. #pragma hdrstop
  14. LOOKASIDE ListboxLookaside;
  15. /***************************************************************************\
  16. * xxxLBoxCtlWndProc
  17. *
  18. * Window Procedure for ListBox AND ComboLBox control.
  19. * NOTE: All window procedures are APIENTRY
  20. * WARNING: This listbox code contains some internal messages and styles which
  21. * are defined in combcom.h and in combcom.inc. They may be redefined
  22. * (or renumbered) as needed to extend the windows API.
  23. *
  24. * History:
  25. * 16-Apr-1992 beng Added LB_SETCOUNT
  26. \***************************************************************************/
  27. LRESULT APIENTRY ListBoxWndProcWorker(
  28. PWND pwnd,
  29. UINT message,
  30. WPARAM wParam,
  31. LPARAM lParam,
  32. DWORD fAnsi)
  33. {
  34. HWND hwnd = HWq(pwnd);
  35. PAINTSTRUCT ps;
  36. HDC hdc;
  37. LPRECT lprc;
  38. PLBIV plb; /* List Box Instance Variable */
  39. INT iSel; /* Index of selected item */
  40. DWORD dw;
  41. TL tlpwndParent;
  42. UINT wFlags;
  43. LPWSTR lpwsz = NULL;
  44. LRESULT lReturn = 0;
  45. static BOOL fInit = TRUE;
  46. CheckLock(pwnd);
  47. VALIDATECLASSANDSIZE(pwnd, FNID_LISTBOX);
  48. INITCONTROLLOOKASIDE(&ListboxLookaside, LBIV, spwnd, 4);
  49. /*
  50. * Get the plb for the given window now since we will use it a lot in
  51. * various handlers. This was stored using SetWindowLong(hwnd,0,plb)
  52. * when the listbox was first created (by INITCONTROLLOOKASIDE above)
  53. */
  54. plb = ((PLBWND)pwnd)->pLBIV;
  55. /*
  56. * Handle ANSI translations of input parameters
  57. */
  58. if (fAnsi) {
  59. switch (message) {
  60. case LB_ADDSTRING:
  61. case LB_ADDSTRINGUPPER:
  62. case LB_ADDSTRINGLOWER:
  63. case LB_FINDSTRING:
  64. case LB_FINDSTRINGEXACT:
  65. case LB_INSERTSTRING:
  66. case LB_INSERTSTRINGUPPER:
  67. case LB_INSERTSTRINGLOWER:
  68. case LB_SELECTSTRING:
  69. if (!plb->fHasStrings) {
  70. break;
  71. }
  72. // Fall through...
  73. case LB_ADDFILE:
  74. case LB_DIR:
  75. if (lParam) {
  76. if (!MBToWCS((LPSTR)lParam, -1, &lpwsz, -1, TRUE))
  77. return LB_ERR;
  78. }
  79. break;
  80. default:
  81. break;
  82. }
  83. if (lpwsz) {
  84. lParam = (LPARAM)lpwsz;
  85. }
  86. }
  87. switch (message) {
  88. case LB_GETTOPINDEX: // Return index of top item displayed.
  89. return plb->iTop;
  90. case LB_SETTOPINDEX:
  91. if (wParam && ((INT)wParam < 0 || (INT)wParam >= plb->cMac)) {
  92. RIPERR0(ERROR_INVALID_INDEX, RIP_VERBOSE, "");
  93. return LB_ERR;
  94. }
  95. if (plb->cMac) {
  96. xxxNewITop(plb, (INT)wParam);
  97. }
  98. break;
  99. case WM_STYLECHANGED:
  100. plb->fRtoLReading = (TestWF(pwnd, WEFRTLREADING) != 0);
  101. plb->fRightAlign = (TestWF(pwnd, WEFRIGHT) != 0);
  102. xxxCheckRedraw(plb, FALSE, 0);
  103. break;
  104. case WM_WINDOWPOSCHANGED:
  105. /*
  106. * If we are in the middle of creation, ignore this
  107. * message because it will generate a WM_SIZE message.
  108. * See xxxLBCreate().
  109. */
  110. if (!plb->fIgnoreSizeMsg)
  111. goto CallDWP;
  112. break;
  113. case WM_SIZE:
  114. /*
  115. * If we are in the middle of creation, ignore size
  116. * messages. See xxxLBCreate().
  117. */
  118. if (!plb->fIgnoreSizeMsg)
  119. xxxLBSize(plb, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
  120. break;
  121. case WM_ERASEBKGND:
  122. ThreadLock(plb->spwndParent, &tlpwndParent);
  123. FillWindow(HW(plb->spwndParent), hwnd, (HDC)wParam,
  124. (HBRUSH)CTLCOLOR_LISTBOX);
  125. ThreadUnlock(&tlpwndParent);
  126. return TRUE;
  127. case LB_RESETCONTENT:
  128. xxxLBResetContent(plb);
  129. break;
  130. case WM_TIMER:
  131. if (wParam == IDSYS_LBSEARCH) {
  132. plb->iTypeSearch = 0;
  133. NtUserKillTimer(hwnd, IDSYS_LBSEARCH);
  134. xxxInvertLBItem(plb, plb->iSel, TRUE);
  135. break;
  136. }
  137. message = WM_MOUSEMOVE;
  138. xxxTrackMouse(plb, message, plb->ptPrev);
  139. break;
  140. /*
  141. * Fall through
  142. */
  143. case WM_MOUSEMOVE:
  144. case WM_LBUTTONDOWN:
  145. case WM_LBUTTONUP:
  146. case WM_LBUTTONDBLCLK:
  147. {
  148. POINT pt;
  149. POINTSTOPOINT(pt, lParam);
  150. xxxTrackMouse(plb, message, pt);
  151. }
  152. break;
  153. case WM_MBUTTONDOWN:
  154. EnterReaderModeHelper(hwnd);
  155. break;
  156. case WM_CAPTURECHANGED:
  157. //
  158. // Note that this message should be handled only on unexpected
  159. // capture changes currently.
  160. //
  161. UserAssert(TestWF(pwnd, WFWIN40COMPAT));
  162. if (plb->fCaptured)
  163. xxxLBButtonUp(plb, LBUP_NOTIFY);
  164. break;
  165. case LBCB_STARTTRACK:
  166. //
  167. // Start tracking mouse moves in the listbox, setting capture
  168. //
  169. if (!plb->pcbox)
  170. break;
  171. plb->fCaptured = FALSE;
  172. if (wParam) {
  173. POINT pt;
  174. POINTSTOPOINT(pt, lParam);
  175. _ScreenToClient(pwnd, &pt);
  176. xxxTrackMouse(plb, WM_LBUTTONDOWN, pt);
  177. } else {
  178. NtUserSetCapture(hwnd);
  179. plb->fCaptured = TRUE;
  180. plb->iLastSelection = plb->iSel;
  181. }
  182. break;
  183. case LBCB_ENDTRACK:
  184. // Kill capture, tracking, etc.
  185. if (plb->fCaptured)
  186. xxxLBButtonUp(plb, LBUP_RELEASECAPTURE | (wParam ? LBUP_SELCHANGE :
  187. LBUP_RESETSELECTION));
  188. break;
  189. case WM_PRINTCLIENT:
  190. xxxLBPaint(plb, (HDC) wParam, NULL);
  191. break;
  192. case WM_PAINT:
  193. if (wParam) {
  194. hdc = (HDC) wParam;
  195. lprc = NULL;
  196. } else {
  197. hdc = NtUserBeginPaint(hwnd, &ps);
  198. lprc = &(ps.rcPaint);
  199. }
  200. if (IsLBoxVisible(plb))
  201. xxxLBPaint(plb, hdc, lprc);
  202. if (!wParam)
  203. NtUserEndPaint(hwnd, &ps);
  204. break;
  205. case WM_NCDESTROY:
  206. case WM_FINALDESTROY:
  207. xxxDestroyLBox(plb, pwnd);
  208. break;
  209. case WM_SETFOCUS:
  210. // DISABLED in Win 3.1 xxxUpdateWindow(pwnd);
  211. CaretCreate(plb);
  212. xxxLBSetCaret(plb, TRUE);
  213. xxxNotifyOwner(plb, LBN_SETFOCUS);
  214. /*
  215. * We need to send this event even if the listbox isn't visible. See
  216. * bug #88548.
  217. */
  218. LBEvent(plb, EVENT_OBJECT_FOCUS, plb->iSelBase);
  219. break;
  220. case WM_KILLFOCUS:
  221. /*
  222. * Reset the wheel delta count.
  223. */
  224. gcWheelDelta = 0;
  225. xxxLBSetCaret(plb, FALSE);
  226. xxxCaretDestroy(plb);
  227. xxxNotifyOwner(plb, LBN_KILLFOCUS);
  228. if (plb->iTypeSearch) {
  229. plb->iTypeSearch = 0;
  230. NtUserKillTimer(hwnd, IDSYS_LBSEARCH);
  231. }
  232. if (plb->pszTypeSearch) {
  233. UserLocalFree(plb->pszTypeSearch);
  234. plb->pszTypeSearch = NULL;
  235. }
  236. break;
  237. case WM_MOUSEWHEEL:
  238. {
  239. int cDetants;
  240. int cPage;
  241. int cLines;
  242. RECT rc;
  243. int windowWidth;
  244. int cPos;
  245. /*
  246. * Don't handle zoom and datazoom.
  247. */
  248. if (wParam & (MK_SHIFT | MK_CONTROL)) {
  249. goto CallDWP;
  250. }
  251. lReturn = 1;
  252. gcWheelDelta -= (short) HIWORD(wParam);
  253. cDetants = gcWheelDelta / WHEEL_DELTA;
  254. if ( cDetants != 0 &&
  255. gpsi->ucWheelScrollLines > 0 &&
  256. (pwnd->style & (WS_VSCROLL | WS_HSCROLL))) {
  257. gcWheelDelta = gcWheelDelta % WHEEL_DELTA;
  258. if (pwnd->style & WS_VSCROLL) {
  259. cPage = max(1, (plb->cItemFullMax - 1));
  260. cLines = cDetants *
  261. (int) min((UINT) cPage, gpsi->ucWheelScrollLines);
  262. cPos = max(0, min(plb->iTop + cLines, plb->cMac - 1));
  263. if (cPos != plb->iTop) {
  264. xxxLBoxCtlScroll(plb, SB_THUMBPOSITION, cPos);
  265. xxxLBoxCtlScroll(plb, SB_ENDSCROLL, 0);
  266. }
  267. } else if (plb->fMultiColumn) {
  268. cPage = max(1, plb->numberOfColumns);
  269. cLines = cDetants * (int) min((UINT) cPage, gpsi->ucWheelScrollLines);
  270. cPos = max(
  271. 0,
  272. min((plb->iTop / plb->itemsPerColumn) + cLines,
  273. plb->cMac - 1 - ((plb->cMac - 1) % plb->itemsPerColumn)));
  274. if (cPos != plb->iTop) {
  275. xxxLBoxCtlHScrollMultiColumn(plb, SB_THUMBPOSITION, cPos);
  276. xxxLBoxCtlHScrollMultiColumn(plb, SB_ENDSCROLL, 0);
  277. }
  278. } else {
  279. _GetClientRect(plb->spwnd, &rc);
  280. windowWidth = rc.right;
  281. cPage = max(plb->cxChar, (windowWidth / 3) * 2) /
  282. plb->cxChar;
  283. cLines = cDetants *
  284. (int) min((UINT) cPage, gpsi->ucWheelScrollLines);
  285. cPos = max(
  286. 0,
  287. min(plb->xOrigin + (cLines * plb->cxChar),
  288. plb->maxWidth));
  289. if (cPos != plb->xOrigin) {
  290. xxxLBoxCtlHScroll(plb, SB_THUMBPOSITION, cPos);
  291. xxxLBoxCtlHScroll(plb, SB_ENDSCROLL, 0);
  292. }
  293. }
  294. }
  295. }
  296. break;
  297. case WM_VSCROLL:
  298. xxxLBoxCtlScroll(plb, LOWORD(wParam), HIWORD(wParam));
  299. break;
  300. case WM_HSCROLL:
  301. xxxLBoxCtlHScroll(plb, LOWORD(wParam), HIWORD(wParam));
  302. break;
  303. case WM_GETDLGCODE:
  304. return DLGC_WANTARROWS | DLGC_WANTCHARS;
  305. case WM_CREATE:
  306. return xxxLBCreate(plb, pwnd, (LPCREATESTRUCT) lParam);
  307. case WM_SETREDRAW:
  308. /*
  309. * If wParam is nonzero, the redraw flag is set
  310. * If wParam is zero, the flag is cleared
  311. */
  312. xxxLBSetRedraw(plb, (wParam != 0));
  313. break;
  314. case WM_ENABLE:
  315. xxxLBInvalidateRect(plb, NULL, !plb->OwnerDraw);
  316. break;
  317. case WM_SETFONT:
  318. xxxLBSetFont(plb, (HANDLE)wParam, LOWORD(lParam));
  319. break;
  320. case WM_GETFONT:
  321. return (LRESULT)plb->hFont;
  322. case WM_DRAGSELECT:
  323. case WM_DRAGLOOP:
  324. case WM_DRAGMOVE:
  325. case WM_DROPFILES:
  326. ThreadLock(plb->spwndParent, &tlpwndParent);
  327. lReturn = SendMessage(HW(plb->spwndParent), message, wParam, lParam);
  328. ThreadUnlock(&tlpwndParent);
  329. return lReturn;
  330. case WM_QUERYDROPOBJECT:
  331. case WM_DROPOBJECT:
  332. /*
  333. * fix up control data, then pass message to parent
  334. */
  335. LBDropObjectHandler(plb, (PDROPSTRUCT)lParam);
  336. ThreadLock(plb->spwndParent, &tlpwndParent);
  337. lReturn = SendMessage(HW(plb->spwndParent), message, wParam, lParam);
  338. ThreadUnlock(&tlpwndParent);
  339. return lReturn;
  340. case LB_GETITEMRECT:
  341. return LBGetItemRect(plb, (INT)wParam, (LPRECT)lParam);
  342. case LB_GETITEMDATA:
  343. return LBGetItemData(plb, (INT)wParam); // wParam = item index
  344. case LB_SETITEMDATA:
  345. /*
  346. * wParam is item index
  347. */
  348. return LBSetItemData(plb, (INT)wParam, lParam);
  349. case LB_ADDSTRINGUPPER:
  350. wFlags = UPPERCASE | LBI_ADD;
  351. goto CallInsertItem;
  352. case LB_ADDSTRINGLOWER:
  353. wFlags = LOWERCASE | LBI_ADD;
  354. goto CallInsertItem;
  355. case LB_ADDSTRING:
  356. wFlags = LBI_ADD;
  357. goto CallInsertItem;
  358. case LB_INSERTSTRINGUPPER:
  359. wFlags = UPPERCASE;
  360. goto CallInsertItem;
  361. case LB_INSERTSTRINGLOWER:
  362. wFlags = LOWERCASE;
  363. goto CallInsertItem;
  364. case LB_INSERTSTRING:
  365. wFlags = 0;
  366. CallInsertItem:
  367. lReturn = ((LRESULT) xxxLBInsertItem(plb, (LPWSTR) lParam, (int) wParam, wFlags));
  368. break;
  369. case LB_INITSTORAGE:
  370. return xxxLBInitStorage(plb, fAnsi, (INT)wParam, (INT)lParam);
  371. case LB_DELETESTRING:
  372. return xxxLBoxCtlDelete(plb, (INT)wParam);
  373. case LB_DIR:
  374. /*
  375. * wParam - Dos attribute value.
  376. * lParam - Points to a file specification string
  377. */
  378. lReturn = xxxLbDir(plb, (INT)wParam, (LPWSTR)lParam);
  379. break;
  380. case LB_ADDFILE:
  381. lReturn = xxxLbInsertFile(plb, (LPWSTR)lParam);
  382. break;
  383. case LB_SETSEL:
  384. return xxxLBSetSel(plb, (wParam != 0), (INT)lParam);
  385. case LB_SETCURSEL:
  386. /*
  387. * If window obscured, update so invert will work correctly
  388. */
  389. // DISABLED in Win 3.1 xxxUpdateWindow(pwnd);
  390. return xxxLBSetCurSel(plb, (INT)wParam);
  391. case LB_GETSEL:
  392. if (wParam >= (UINT) plb->cMac)
  393. return((LRESULT) LB_ERR);
  394. return IsSelected(plb, (INT)wParam, SELONLY);
  395. case LB_GETCURSEL:
  396. if (plb->wMultiple == SINGLESEL) {
  397. return plb->iSel;
  398. }
  399. return plb->iSelBase;
  400. case LB_SELITEMRANGE:
  401. if (plb->wMultiple == SINGLESEL) {
  402. /*
  403. * Can't select a range if only single selections are enabled
  404. */
  405. RIPERR0(ERROR_INVALID_INDEX, RIP_VERBOSE,"Invalid index passed to LB_SELITEMRANGE");
  406. return LB_ERR;
  407. }
  408. xxxLBSelRange(plb, LOWORD(lParam), HIWORD(lParam), (wParam != 0));
  409. break;
  410. case LB_SELITEMRANGEEX:
  411. if (plb->wMultiple == SINGLESEL) {
  412. /*
  413. * Can't select a range if only single selections are enabled
  414. */
  415. RIPERR0(ERROR_INVALID_LB_MESSAGE, RIP_VERBOSE,"LB_SELITEMRANGEEX:Can't select a range if only single selections are enabled");
  416. return LB_ERR;
  417. } else {
  418. BOOL fHighlight = ((DWORD)lParam > (DWORD)wParam);
  419. if (fHighlight == FALSE) {
  420. ULONG_PTR temp = lParam;
  421. lParam = wParam;
  422. wParam = temp;
  423. }
  424. xxxLBSelRange(plb, (INT)wParam, (INT)lParam, fHighlight);
  425. }
  426. break;
  427. case LB_GETTEXTLEN:
  428. if (lParam != 0) {
  429. RIPMSG1(RIP_WARNING, "LB_GETTEXTLEN with lParam = %lx\n", lParam);
  430. }
  431. lReturn = LBGetText(plb, TRUE, fAnsi, (INT)wParam, NULL);
  432. break;
  433. case LB_GETTEXT:
  434. lReturn = LBGetText(plb, FALSE, fAnsi, (INT)wParam, (LPWSTR)lParam);
  435. break;
  436. case LB_GETCOUNT:
  437. // Lotus Approach calls CallWndProc(ListWndProc, LB_GETCOUNT,...)
  438. // on a window that doesn't have a plb yet. So, we need to make
  439. // this check. Bug #6675 - 11/7/94 --
  440. if(plb)
  441. return((LRESULT) plb->cMac);
  442. else
  443. return(0);
  444. case LB_SETCOUNT:
  445. return xxxLBSetCount(plb, (INT)wParam);
  446. case LB_SELECTSTRING:
  447. case LB_FINDSTRING:
  448. iSel = xxxFindString(plb, (LPWSTR)lParam, (INT)wParam, PREFIX, TRUE);
  449. if (message == LB_FINDSTRING || iSel == LB_ERR) {
  450. lReturn = iSel;
  451. } else {
  452. lReturn = xxxLBSetCurSel(plb, iSel);
  453. }
  454. break;
  455. case LB_GETLOCALE:
  456. return plb->dwLocaleId;
  457. case LB_SETLOCALE:
  458. /*
  459. * Validate locale
  460. */
  461. wParam = ConvertDefaultLocale((LCID)wParam);
  462. if (!IsValidLocale((LCID)wParam, LCID_INSTALLED))
  463. return LB_ERR;
  464. dw = plb->dwLocaleId;
  465. plb->dwLocaleId = (DWORD)wParam;
  466. return dw;
  467. case WM_KEYDOWN:
  468. /*
  469. * IanJa: Use LOWORD() to get low 16-bits of wParam - this should
  470. * work for Win16 & Win32. The value obtained is the virtual key
  471. */
  472. xxxLBoxCtlKeyInput(plb, message, LOWORD(wParam));
  473. break;
  474. case WM_CHAR:
  475. xxxLBoxCtlCharInput(plb, LOWORD(wParam), fAnsi);
  476. break;
  477. case LB_GETSELITEMS:
  478. case LB_GETSELCOUNT:
  479. /*
  480. * IanJa/Win32 should this be LPWORD now?
  481. */
  482. return LBoxGetSelItems(plb, (message == LB_GETSELCOUNT), (INT)wParam,
  483. (LPINT)lParam);
  484. case LB_SETTABSTOPS:
  485. /*
  486. * IanJa/Win32: Tabs given by array of INT for backwards compatability
  487. */
  488. return LBSetTabStops(plb, (INT)wParam, (LPINT)lParam);
  489. case LB_GETHORIZONTALEXTENT:
  490. /*
  491. * Return the max width of the listbox used for horizontal scrolling
  492. */
  493. return plb->maxWidth;
  494. case LB_SETHORIZONTALEXTENT:
  495. /*
  496. * Set the max width of the listbox used for horizontal scrolling
  497. */
  498. if (plb->maxWidth != (INT)wParam) {
  499. plb->maxWidth = (INT)wParam;
  500. /*
  501. * When horizontal extent is set, Show/hide the scroll bars.
  502. * NOTE: LBShowHideScrollBars() takes care if Redraw is OFF.
  503. * Fix for Bug #2477 -- 01/14/91 -- SANKAR --
  504. */
  505. xxxLBShowHideScrollBars(plb); //Try to show or hide scroll bars
  506. if (plb->fHorzBar && plb->fRightAlign && !(plb->fMultiColumn || plb->OwnerDraw)) {
  507. /*
  508. * origin to right
  509. */
  510. xxxLBoxCtlHScroll(plb, SB_BOTTOM, 0);
  511. }
  512. }
  513. break; /* originally returned register ax (message) ! */
  514. case LB_SETCOLUMNWIDTH:
  515. /*
  516. * Set the width of a column in a multicolumn listbox
  517. */
  518. plb->cxColumn = (INT)wParam;
  519. LBCalcItemRowsAndColumns(plb);
  520. if (IsLBoxVisible(plb))
  521. NtUserInvalidateRect(hwnd, NULL, TRUE);
  522. xxxLBShowHideScrollBars(plb);
  523. break;
  524. case LB_SETANCHORINDEX:
  525. if ((INT)wParam >= plb->cMac) {
  526. RIPERR0(ERROR_INVALID_INDEX, RIP_VERBOSE,"Invalid index passed to LB_SETANCHORINDEX");
  527. return LB_ERR;
  528. }
  529. plb->iMouseDown = (INT)wParam;
  530. plb->iLastMouseMove = (INT)wParam;
  531. xxxInsureVisible(plb, (int) wParam, (BOOL)(lParam != 0));
  532. break;
  533. case LB_GETANCHORINDEX:
  534. return plb->iMouseDown;
  535. case LB_SETCARETINDEX:
  536. if ( (plb->iSel == -1) || ((plb->wMultiple != SINGLESEL) &&
  537. (plb->cMac > (INT)wParam))) {
  538. /*
  539. * Set's the iSelBase to the wParam
  540. * if lParam, then don't scroll if partially visible
  541. * else scroll into view if not fully visible
  542. */
  543. xxxInsureVisible(plb, (INT)wParam, (BOOL)LOWORD(lParam));
  544. xxxSetISelBase(plb, (INT)wParam);
  545. break;
  546. } else {
  547. if ((INT)wParam >= plb->cMac) {
  548. RIPERR0(ERROR_INVALID_INDEX, RIP_VERBOSE,"Invalid index passed to LB_SETCARETINDEX");
  549. }
  550. return LB_ERR;
  551. }
  552. break;
  553. case LB_GETCARETINDEX:
  554. return plb->iSelBase;
  555. case LB_SETITEMHEIGHT:
  556. case LB_GETITEMHEIGHT:
  557. return LBGetSetItemHeightHandler(plb, message, (INT)wParam, LOWORD(lParam));
  558. break;
  559. case LB_FINDSTRINGEXACT:
  560. lReturn = xxxFindString(plb, (LPWSTR)lParam, (INT)wParam, EQ, TRUE);
  561. break;
  562. case LB_ITEMFROMPOINT: {
  563. POINT pt;
  564. BOOL bOutside;
  565. DWORD dwItem;
  566. POINTSTOPOINT(pt, lParam);
  567. bOutside = ISelFromPt(plb, pt, &dwItem);
  568. UserAssert(bOutside == 1 || bOutside == 0);
  569. return (LRESULT)MAKELONG(dwItem, bOutside);
  570. }
  571. case LBCB_CARETON:
  572. /*
  573. * Internal message for combo box support
  574. */
  575. CaretCreate(plb);
  576. // Set up the caret in the proper location for drop downs.
  577. plb->iSelBase = plb->iSel;
  578. xxxLBSetCaret(plb, TRUE);
  579. /*
  580. * We need to send this event even if the listbox isn't visible. See
  581. * bug #88548. Also see 355612.
  582. */
  583. if (_IsWindowVisible(pwnd) || (GetFocus() == hwnd)) {
  584. LBEvent(plb, EVENT_OBJECT_FOCUS, plb->iSelBase);
  585. }
  586. return(plb->iSel);
  587. case LBCB_CARETOFF:
  588. /*
  589. * Internal message for combo box support
  590. */
  591. xxxLBSetCaret(plb, FALSE);
  592. xxxCaretDestroy(plb);
  593. break;
  594. case LB_GETLISTBOXINFO:
  595. return NtUserGetListBoxInfo(hwnd);
  596. case WM_NCCREATE:
  597. if ((pwnd->style & LBS_MULTICOLUMN) && (pwnd->style & WS_VSCROLL))
  598. {
  599. DWORD mask = WS_VSCROLL;
  600. DWORD flags = 0;
  601. if (!TestWF(pwnd, WFWIN40COMPAT)) {
  602. mask |= WS_HSCROLL;
  603. flags = WS_HSCROLL;
  604. }
  605. NtUserAlterWindowStyle(hwnd, mask, flags);
  606. }
  607. goto CallDWP;
  608. default:
  609. CallDWP:
  610. return DefWindowProcWorker(pwnd, message, wParam, lParam, fAnsi);
  611. }
  612. /*
  613. * Handle translation of ANSI output data and free buffer
  614. */
  615. if (lpwsz) {
  616. UserLocalFree(lpwsz);
  617. }
  618. return lReturn;
  619. }
  620. /***************************************************************************\
  621. \***************************************************************************/
  622. LRESULT WINAPI ListBoxWndProcA(
  623. HWND hwnd,
  624. UINT message,
  625. WPARAM wParam,
  626. LPARAM lParam)
  627. {
  628. PWND pwnd;
  629. if ((pwnd = ValidateHwnd(hwnd)) == NULL) {
  630. return (0L);
  631. }
  632. /*
  633. * If the control is not interested in this message,
  634. * pass it to DefWindowProc.
  635. */
  636. if (!FWINDOWMSG(message, FNID_LISTBOX))
  637. return DefWindowProcWorker(pwnd, message, wParam, lParam, TRUE);
  638. return ListBoxWndProcWorker(pwnd, message, wParam, lParam, TRUE);
  639. }
  640. LRESULT WINAPI ListBoxWndProcW(
  641. HWND hwnd,
  642. UINT message,
  643. WPARAM wParam,
  644. LPARAM lParam)
  645. {
  646. PWND pwnd;
  647. if ((pwnd = ValidateHwnd(hwnd)) == NULL) {
  648. return (0L);
  649. }
  650. /*
  651. * If the control is not interested in this message,
  652. * pass it to DefWindowProc.
  653. */
  654. if (!FWINDOWMSG(message, FNID_LISTBOX))
  655. return DefWindowProcWorker(pwnd, message, wParam, lParam, FALSE);
  656. return ListBoxWndProcWorker(pwnd, message, wParam, lParam, FALSE);
  657. }
  658. LRESULT WINAPI ComboListBoxWndProcA(
  659. HWND hwnd,
  660. UINT message,
  661. WPARAM wParam,
  662. LPARAM lParam)
  663. {
  664. PWND pwnd;
  665. if ((pwnd = ValidateHwnd(hwnd)) == NULL) {
  666. return (0L);
  667. }
  668. /*
  669. * If the control is not interested in this message,
  670. * pass it to DefWindowProc.
  671. */
  672. if (!FWINDOWMSG(message, FNID_LISTBOX))
  673. return DefWindowProcWorker(pwnd, message, wParam, lParam, TRUE);
  674. return ListBoxWndProcWorker(pwnd, message, wParam, lParam, TRUE);
  675. }
  676. LRESULT WINAPI ComboListBoxWndProcW(
  677. HWND hwnd,
  678. UINT message,
  679. WPARAM wParam,
  680. LPARAM lParam)
  681. {
  682. PWND pwnd;
  683. if ((pwnd = ValidateHwnd(hwnd)) == NULL) {
  684. return (0L);
  685. }
  686. /*
  687. * If the control is not interested in this message,
  688. * pass it to DefWindowProc.
  689. */
  690. if (!FWINDOWMSG(message, FNID_LISTBOX))
  691. return DefWindowProcWorker(pwnd, message, wParam, lParam, FALSE);
  692. return ListBoxWndProcWorker(pwnd, message, wParam, lParam, FALSE);
  693. }
  694. /***************************************************************************\
  695. * GetLpszItem
  696. *
  697. * Returns a far pointer to the string belonging to item sItem
  698. * ONLY for Listboxes maintaining their own strings (pLBIV->fHasStrings == TRUE)
  699. *
  700. * History:
  701. \***************************************************************************/
  702. LPWSTR GetLpszItem(
  703. PLBIV pLBIV,
  704. INT sItem)
  705. {
  706. LONG offsz;
  707. lpLBItem plbi;
  708. if (sItem < 0 || sItem >= pLBIV->cMac) {
  709. RIPERR1(ERROR_INVALID_PARAMETER,
  710. RIP_WARNING,
  711. "Invalid parameter \"sItem\" (%ld) to GetLpszItem",
  712. sItem);
  713. return NULL;
  714. }
  715. /*
  716. * get pointer to item index array
  717. * NOTE: NOT OWNERDRAW
  718. */
  719. plbi = (lpLBItem)(pLBIV->rgpch);
  720. offsz = plbi[sItem].offsz;
  721. return (LPWSTR)((PBYTE)(pLBIV->hStrings) + offsz);
  722. }