Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

lboxrare.c

Go to the documentation of this file.
00001 /**************************** Module Header ********************************\ 00002 * Module Name: lboxrare.c 00003 * 00004 * Copyright (c) 1985 - 1999, Microsoft Corporation 00005 * 00006 * Infrequently Used List Box Routines 00007 * 00008 * History: 00009 * ??-???-???? ianja Ported from Win 3.0 sources 00010 * 14-Feb-1991 mikeke Added Revalidation code 00011 \***************************************************************************/ 00012 00013 #include "precomp.h" 00014 #pragma hdrstop 00015 00016 extern LOOKASIDE ListboxLookaside; 00017 00018 /***************************************************************************\ 00019 * LBSetCItemFullMax 00020 * 00021 * History: 00022 * 03-04-92 JimA Ported from Win 3.1 sources. 00023 \***************************************************************************/ 00024 00025 void LBSetCItemFullMax( 00026 PLBIV plb) 00027 { 00028 if (plb->OwnerDraw != OWNERDRAWVAR) { 00029 plb->cItemFullMax = CItemInWindow(plb, FALSE); 00030 } else if (plb->cMac < 2) { 00031 plb->cItemFullMax = 1; 00032 } else { 00033 int height; 00034 RECT rect; 00035 int i; 00036 int j = 0; 00037 00038 _GetClientRect(plb->spwnd, &rect); 00039 height = rect.bottom; 00040 00041 plb->cItemFullMax = 0; 00042 for (i = plb->cMac - 1; i >= 0; i--, j++) { 00043 height -= LBGetVariableHeightItemHeight(plb, i); 00044 00045 if (height < 0) { 00046 plb->cItemFullMax = j; 00047 break; 00048 } 00049 } 00050 if (!plb->cItemFullMax) 00051 plb->cItemFullMax = j; 00052 } 00053 } 00054 00055 /***************************************************************************\ 00056 * xxxCreateLBox 00057 * 00058 * History: 00059 * 16-Apr-1992 beng Added LBS_NODATA 00060 \***************************************************************************/ 00061 00062 LONG xxxLBCreate( 00063 PLBIV plb, PWND pwnd, LPCREATESTRUCT lpcs) 00064 { 00065 UINT style; 00066 MEASUREITEMSTRUCT measureItemStruct; 00067 TL tlpwndParent; 00068 HDC hdc; 00069 00070 /* 00071 * Once we make it here, nobody can change the ownerdraw style bits 00072 * by calling SetWindowLong. The window style must match the flags in plb 00073 * 00074 */ 00075 plb->fInitialized = TRUE; 00076 00077 style = pwnd->style; 00078 00079 /* 00080 * Compatibility hack. 00081 */ 00082 if (pwnd->spwndParent == NULL) 00083 Lock(&(plb->spwndParent), _GetDesktopWindow()); 00084 else 00085 Lock(&(plb->spwndParent), REBASEPWND(pwnd, spwndParent)); 00086 00087 /* 00088 * Break out the style bits 00089 */ 00090 plb->fRedraw = ((style & LBS_NOREDRAW) == 0); 00091 plb->fDeferUpdate = FALSE; 00092 plb->fNotify = (UINT)((style & LBS_NOTIFY) != 0); 00093 plb->fVertBar = ((style & WS_VSCROLL) != 0); 00094 plb->fHorzBar = ((style & WS_HSCROLL) != 0); 00095 00096 if (!TestWF(pwnd, WFWIN40COMPAT)) { 00097 // for 3.x apps, if either scroll bar was specified, the app got BOTH 00098 if (plb->fVertBar || plb->fHorzBar) 00099 plb->fVertBar = plb->fHorzBar = TRUE; 00100 } 00101 00102 plb->fRtoLReading = (TestWF(pwnd, WEFRTLREADING) != 0); 00103 plb->fRightAlign = (TestWF(pwnd, WEFRIGHT) != 0); 00104 plb->fDisableNoScroll = ((style & LBS_DISABLENOSCROLL) != 0); 00105 00106 plb->fSmoothScroll = TRUE; 00107 00108 /* 00109 * LBS_NOSEL gets priority over any other selection style. Next highest 00110 * priority goes to LBS_EXTENDEDSEL. Then LBS_MULTIPLESEL. 00111 */ 00112 if (TestWF(pwnd, WFWIN40COMPAT) && (style & LBS_NOSEL)) { 00113 plb->wMultiple = SINGLESEL; 00114 plb->fNoSel = TRUE; 00115 } else if (style & LBS_EXTENDEDSEL) { 00116 plb->wMultiple = EXTENDEDSEL; 00117 } else { 00118 plb->wMultiple = (UINT)((style & LBS_MULTIPLESEL) ? MULTIPLESEL : SINGLESEL); 00119 } 00120 00121 plb->fNoIntegralHeight = ((style & LBS_NOINTEGRALHEIGHT) != 0); 00122 plb->fWantKeyboardInput = ((style & LBS_WANTKEYBOARDINPUT) != 0); 00123 plb->fUseTabStops = ((style & LBS_USETABSTOPS) != 0); 00124 if (plb->fUseTabStops) { 00125 00126 /* 00127 * Set tab stops every <default> dialog units. 00128 */ 00129 LBSetTabStops(plb, 0, NULL); 00130 } 00131 plb->fMultiColumn = ((style & LBS_MULTICOLUMN) != 0); 00132 plb->fHasStrings = TRUE; 00133 plb->iLastSelection = -1; 00134 plb->iMouseDown = -1; /* Anchor point for multi selection */ 00135 plb->iLastMouseMove = -1; 00136 00137 /* 00138 * Get ownerdraw style bits 00139 */ 00140 if ((style & LBS_OWNERDRAWFIXED)) { 00141 plb->OwnerDraw = OWNERDRAWFIXED; 00142 } else if ((style & LBS_OWNERDRAWVARIABLE) && !plb->fMultiColumn) { 00143 plb->OwnerDraw = OWNERDRAWVAR; 00144 00145 /* 00146 * Integral height makes no sense with var height owner draw 00147 */ 00148 plb->fNoIntegralHeight = TRUE; 00149 } 00150 00151 if (plb->OwnerDraw && !(style & LBS_HASSTRINGS)) { 00152 00153 /* 00154 * If owner draw, do they want the listbox to maintain strings? 00155 */ 00156 plb->fHasStrings = FALSE; 00157 } 00158 00159 /* 00160 * If user specifies sort and not hasstrings, then we will send 00161 * WM_COMPAREITEM messages to the parent. 00162 */ 00163 plb->fSort = ((style & LBS_SORT) != 0); 00164 00165 /* 00166 * "No data" lazy-eval listbox mandates certain other style settings 00167 */ 00168 plb->fHasData = TRUE; 00169 00170 if (style & LBS_NODATA) { 00171 if (plb->OwnerDraw != OWNERDRAWFIXED || plb->fSort || plb->fHasStrings) { 00172 RIPERR0(ERROR_INVALID_FLAGS, RIP_WARNING, 00173 "NODATA listbox must be OWNERDRAWFIXED, w/o SORT or HASSTRINGS"); 00174 } else { 00175 plb->fHasData = FALSE; 00176 } 00177 } 00178 00179 plb->dwLocaleId = GetThreadLocale(); 00180 00181 /* 00182 * Check if this is part of a combo box 00183 */ 00184 if ((style & LBS_COMBOBOX) != 0) { 00185 00186 /* 00187 * Get the pcbox structure contained in the parent window's extra data 00188 * pointer. Check cbwndExtra to ensure compatibility with SQL windows. 00189 */ 00190 if (plb->spwndParent->cbwndExtra != 0) 00191 plb->pcbox = ((PCOMBOWND)(plb->spwndParent))->pcbox; 00192 } 00193 00194 /* 00195 * No need to set these to 0 since that was done for us when we Alloced 00196 * the PLBIV. 00197 */ 00198 00199 /* 00200 * plb->rgpch = (PBYTE)0; 00201 */ 00202 00203 /* 00204 * plb->iSelBase = plb->iTop = 0; 00205 */ 00206 00207 /* 00208 * plb->fMouseDown = FALSE; 00209 */ 00210 00211 /* 00212 * plb->fCaret = FALSE; 00213 */ 00214 00215 /* 00216 * plb->fCaretOn = FALSE; 00217 */ 00218 00219 /* 00220 * plb->maxWidth = 0; 00221 */ 00222 00223 plb->iSel = -1; 00224 00225 plb->hdc = NULL; 00226 00227 /* 00228 * Set the keyboard state so that when the user keyboard clicks he selects 00229 * an item. 00230 */ 00231 plb->fNewItemState = TRUE; 00232 00233 InitHStrings(plb); 00234 00235 if (plb->fHasStrings && plb->hStrings == NULL) { 00236 return -1L; 00237 } 00238 00239 hdc = NtUserGetDC(HWq(pwnd)); 00240 plb->cxChar = GdiGetCharDimensions(hdc, NULL, &plb->cyChar); 00241 NtUserReleaseDC(HWq(pwnd), hdc); 00242 00243 if (plb->cxChar == 0) { 00244 RIPMSG0(RIP_WARNING, "xxxLBCreate: GdiGetCharDimensions failed"); 00245 plb->cxChar = gpsi->cxSysFontChar; 00246 plb->cyChar = gpsi->cySysFontChar; 00247 } 00248 00249 if (plb->OwnerDraw == OWNERDRAWFIXED) { 00250 00251 /* 00252 * Query for item height only if we are fixed height owner draw. Note 00253 * that we don't care about an item's width for listboxes. 00254 */ 00255 measureItemStruct.CtlType = ODT_LISTBOX; 00256 measureItemStruct.CtlID = PtrToUlong(pwnd->spmenu); 00257 00258 /* 00259 * System font height is default height 00260 */ 00261 measureItemStruct.itemHeight = plb->cyChar; 00262 measureItemStruct.itemWidth = 0; 00263 measureItemStruct.itemData = 0; 00264 00265 /* 00266 * IanJa: #ifndef WIN16 (32-bit Windows), plb->id gets extended 00267 * to LONG wParam automatically by the compiler 00268 */ 00269 ThreadLock(plb->spwndParent, &tlpwndParent); 00270 SendMessage(HW(plb->spwndParent), WM_MEASUREITEM, 00271 measureItemStruct.CtlID, 00272 (LPARAM)&measureItemStruct); 00273 ThreadUnlock(&tlpwndParent); 00274 00275 /* 00276 * Use default height if given 0. This prevents any possible future 00277 * div-by-zero errors. 00278 */ 00279 if (measureItemStruct.itemHeight) 00280 plb->cyChar = measureItemStruct.itemHeight; 00281 00282 00283 if (plb->fMultiColumn) { 00284 00285 /* 00286 * Get default column width from measure items struct if we are a 00287 * multicolumn listbox. 00288 */ 00289 plb->cxColumn = measureItemStruct.itemWidth; 00290 } 00291 } else if (plb->OwnerDraw == OWNERDRAWVAR) 00292 plb->cyChar = 0; 00293 00294 00295 if (plb->fMultiColumn) { 00296 00297 /* 00298 * Set these default values till we get the WM_SIZE message and we 00299 * calculate them properly. This is because some people create a 00300 * 0 width/height listbox and size it later. We don't want to have 00301 * problems with invalid values in these fields 00302 */ 00303 if (plb->cxColumn <= 0) 00304 plb->cxColumn = 15 * plb->cxChar; 00305 plb->numberOfColumns = plb->itemsPerColumn = 1; 00306 } 00307 00308 LBSetCItemFullMax(plb); 00309 00310 // Don't do this for 4.0 apps. It'll make everyone's lives easier and 00311 // fix the anomaly that a combo & list created the same width end up 00312 // different when all is done. 00313 // B#1520 00314 00315 if (!TestWF(pwnd, WFWIN40COMPAT)) { 00316 plb->fIgnoreSizeMsg = TRUE; 00317 NtUserMoveWindow(HWq(pwnd), 00318 lpcs->x - SYSMET(CXBORDER), 00319 lpcs->y - SYSMET(CYBORDER), 00320 lpcs->cx + SYSMET(CXEDGE), 00321 lpcs->cy + SYSMET(CYEDGE), 00322 FALSE); 00323 plb->fIgnoreSizeMsg = FALSE; 00324 } 00325 00326 if (!plb->fNoIntegralHeight) { 00327 00328 /* 00329 * Send a message to ourselves to resize the listbox to an integral 00330 * height. We need to do it this way because at create time we are all 00331 * mucked up with window rects etc... 00332 * IanJa: #ifndef WIN16 (32-bit Windows), wParam 0 gets extended 00333 * to wParam 0L automatically by the compiler. 00334 */ 00335 PostMessage(HWq(pwnd), WM_SIZE, 0, 0L); 00336 } 00337 00338 return 1L; 00339 } 00340 00341 /***************************************************************************\ 00342 * xxxLBoxDoDeleteItems 00343 * 00344 * Send DELETEITEM message for all the items in the ownerdraw listbox. 00345 * 00346 * History: 00347 * 16-Apr-1992 beng Nodata case 00348 \***************************************************************************/ 00349 00350 void xxxLBoxDoDeleteItems( 00351 PLBIV plb) 00352 { 00353 INT sItem; 00354 00355 CheckLock(plb->spwnd); 00356 00357 /* 00358 * Send WM_DELETEITEM message for ownerdraw listboxes which are 00359 * being deleted. (NODATA listboxes don't send such, though.) 00360 */ 00361 if (plb->OwnerDraw && plb->cMac && plb->fHasData) { 00362 for (sItem = plb->cMac - 1; sItem >= 0; sItem--) { 00363 xxxLBoxDeleteItem(plb, sItem); 00364 } 00365 } 00366 } 00367 00368 00369 /***************************************************************************\ 00370 * xxxDestroyLBox 00371 * 00372 * History: 00373 \***************************************************************************/ 00374 00375 void xxxDestroyLBox( 00376 PLBIV pLBIV, 00377 PWND pwnd) 00378 { 00379 PWND pwndParent; 00380 00381 CheckLock(pwnd); 00382 00383 if (pLBIV != NULL) { 00384 CheckLock(pLBIV->spwnd); 00385 00386 /* 00387 * If ownerdraw, send deleteitem messages to parent 00388 */ 00389 xxxLBoxDoDeleteItems(pLBIV); 00390 00391 if (pLBIV->rgpch != NULL) { 00392 UserLocalFree(pLBIV->rgpch); 00393 pLBIV->rgpch = NULL; 00394 } 00395 00396 if (pLBIV->hStrings != NULL) { 00397 UserLocalFree(pLBIV->hStrings); 00398 pLBIV->hStrings = NULL; 00399 } 00400 00401 if (pLBIV->iTabPixelPositions != NULL) { 00402 UserLocalFree((HANDLE)pLBIV->iTabPixelPositions); 00403 pLBIV->iTabPixelPositions = NULL; 00404 } 00405 00406 Unlock(&pLBIV->spwnd); 00407 Unlock(&pLBIV->spwndParent); 00408 00409 if (pLBIV->pszTypeSearch) { 00410 UserLocalFree(pLBIV->pszTypeSearch); 00411 } 00412 00413 FreeLookasideEntry(&ListboxLookaside, pLBIV); 00414 } 00415 00416 /* 00417 * Set the window's fnid status so that we can ignore rogue messages 00418 */ 00419 NtUserSetWindowFNID(HWq(pwnd), FNID_CLEANEDUP_BIT); 00420 00421 /* 00422 * If we're part of a combo box, let it know we're gone 00423 */ 00424 pwndParent = REBASEPWND(pwnd, spwndParent); 00425 if (pwndParent && GETFNID(pwndParent) == FNID_COMBOBOX) { 00426 ComboBoxWndProcWorker(pwndParent, WM_PARENTNOTIFY, 00427 MAKELONG(WM_DESTROY, PTR_TO_ID(pwnd->spmenu)), (LPARAM)HWq(pwnd), FALSE); 00428 } 00429 } 00430 00431 00432 /***************************************************************************\ 00433 * xxxLBSetFont 00434 * 00435 * History: 00436 \***************************************************************************/ 00437 00438 void xxxLBSetFont( 00439 PLBIV plb, 00440 HANDLE hFont, 00441 BOOL fRedraw) 00442 { 00443 HDC hdc; 00444 HANDLE hOldFont = NULL; 00445 int iHeight; 00446 00447 CheckLock(plb->spwnd); 00448 00449 plb->hFont = hFont; 00450 00451 hdc = NtUserGetDC(HWq(plb->spwnd)); 00452 00453 if (hFont) { 00454 hOldFont = SelectObject(hdc, hFont); 00455 if (!hOldFont) { 00456 plb->hFont = NULL; 00457 } 00458 } 00459 00460 plb->cxChar = GdiGetCharDimensions(hdc, NULL, &iHeight); 00461 if (plb->cxChar == 0) { 00462 RIPMSG0(RIP_WARNING, "xxxLBSetFont: GdiGetCharDimensions failed"); 00463 plb->cxChar = gpsi->cxSysFontChar; 00464 iHeight = gpsi->cySysFontChar; 00465 } 00466 00467 00468 if (!plb->OwnerDraw && (plb->cyChar != iHeight)) { 00469 00470 /* 00471 * We don't want to mess up the cyChar height for owner draw listboxes 00472 * so don't do this. 00473 */ 00474 plb->cyChar = iHeight; 00475 00476 /* 00477 * Only resize the listbox for 4.0 dudes, or combo dropdowns. 00478 * Macromedia Director 4.0 GP-faults otherwise. 00479 */ 00480 if (!plb->fNoIntegralHeight && 00481 (plb->pcbox || TestWF(plb->spwnd, WFWIN40COMPAT))) { 00482 xxxLBSize(plb, 00483 plb->spwnd->rcClient.right - plb->spwnd->rcClient.left, 00484 plb->spwnd->rcClient.bottom - plb->spwnd->rcClient.top); 00485 } 00486 } 00487 00488 if (hOldFont) { 00489 SelectObject(hdc, hOldFont); 00490 } 00491 00492 /* 00493 * IanJa: was ReleaseDC(hwnd, hdc); 00494 */ 00495 NtUserReleaseDC(HWq(plb->spwnd), hdc); 00496 00497 if (plb->fMultiColumn) { 00498 LBCalcItemRowsAndColumns(plb); 00499 } 00500 00501 LBSetCItemFullMax(plb); 00502 00503 if (fRedraw) 00504 xxxCheckRedraw(plb, FALSE, 0); 00505 } 00506 00507 00508 /***************************************************************************\ 00509 * xxxLBSize 00510 * 00511 * History: 00512 \***************************************************************************/ 00513 00514 void xxxLBSize( 00515 PLBIV plb, 00516 INT cx, 00517 INT cy) 00518 { 00519 RECT rc; 00520 int iTopOld; 00521 BOOL fSizedSave; 00522 00523 CheckLock(plb->spwnd); 00524 00525 if (!plb->fNoIntegralHeight) { 00526 int cBdrs = GetWindowBorders(plb->spwnd->style, plb->spwnd->ExStyle, TRUE, TRUE); 00527 00528 CopyInflateRect(&rc, &plb->spwnd->rcWindow, 0, -cBdrs * SYSMET(CYBORDER)); 00529 00530 // Size the listbox to fit an integral # of items in its client 00531 if ((rc.bottom - rc.top) % plb->cyChar) { 00532 int iItems = (rc.bottom - rc.top); 00533 00534 // B#2285 - If its a 3.1 app its SetWindowPos needs 00535 // to be window based dimensions not Client ! 00536 // this crunches Money into using a scroll bar 00537 00538 if ( ! TestWF( plb->spwnd, WFWIN40COMPAT ) ) 00539 iItems += (cBdrs * SYSMET(CYEDGE)); // so add it back in 00540 00541 iItems /= plb->cyChar; 00542 00543 NtUserSetWindowPos(HWq(plb->spwnd), HWND_TOP, 0, 0, rc.right - rc.left, 00544 iItems * plb->cyChar + (SYSMET(CYEDGE) * cBdrs), 00545 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER); 00546 00547 /* 00548 * Changing the size causes us to recurse. Upon return 00549 * the state is where it should be and nothing further 00550 * needs to be done. 00551 */ 00552 return; 00553 } 00554 } 00555 00556 if (plb->fMultiColumn) { 00557 00558 /* 00559 * Compute the number of DISPLAYABLE rows and columns in the listbox 00560 */ 00561 LBCalcItemRowsAndColumns(plb); 00562 } else { 00563 00564 /* 00565 * Adjust the current horizontal position to eliminate as much 00566 * empty space as possible from the right side of the items. 00567 */ 00568 _GetClientRect(plb->spwnd, &rc); 00569 if ((plb->maxWidth - plb->xOrigin) < (rc.right - rc.left)) 00570 plb->xOrigin = max(0, plb->maxWidth - (rc.right - rc.left)); 00571 } 00572 00573 LBSetCItemFullMax(plb); 00574 00575 /* 00576 * Adjust the top item in the listbox to eliminate as much empty space 00577 * after the last item as possible 00578 * (fix for bugs #8490 & #3836) 00579 */ 00580 iTopOld = plb->iTop; 00581 fSizedSave = plb->fSized; 00582 plb->fSized = FALSE; 00583 xxxNewITop(plb, plb->iTop); 00584 00585 /* 00586 * If changing the top item index caused a resize, there is no 00587 * more work to be done here. 00588 */ 00589 if (plb->fSized) 00590 return; 00591 plb->fSized = fSizedSave; 00592 00593 if (IsLBoxVisible(plb)) { 00594 /* 00595 * This code no longer blows because it's fixed right!!! We could 00596 * optimize the fMultiColumn case with some more code to figure out 00597 * if we really need to invalidate the whole thing but note that some 00598 * 3.0 apps depend on this extra invalidation (AMIPRO 2.0, bug 14620) 00599 * 00600 * For 3.1 apps, we blow off the invalidaterect in the case where 00601 * cx and cy are 0 because this happens during the processing of 00602 * the posted WM_SIZE message when we are created which would otherwise 00603 * cause us to flash. 00604 */ 00605 if ((plb->fMultiColumn && !(cx == 0 && cy == 0)) || 00606 plb->iTop != iTopOld) 00607 NtUserInvalidateRect(HWq(plb->spwnd), NULL, TRUE); 00608 else if (plb->iSelBase >= 0) { 00609 00610 /* 00611 * Invalidate the item with the caret so that if the listbox 00612 * grows horizontally, we redraw it properly. 00613 */ 00614 LBGetItemRect(plb, plb->iSelBase, &rc); 00615 NtUserInvalidateRect(HWq(plb->spwnd), &rc, FALSE); 00616 } 00617 } else if (!plb->fRedraw) 00618 plb->fDeferUpdate = TRUE; 00619 00620 /* 00621 * Send "fake" scroll bar messages to update the scroll positions since we 00622 * changed size. 00623 */ 00624 if (TestWF(plb->spwnd, WFVSCROLL)) { 00625 xxxLBoxCtlScroll(plb, SB_ENDSCROLL, 0); 00626 } 00627 00628 /* 00629 * We count on this to call LBShowHideScrollBars except when plb->cMac == 0! 00630 */ 00631 xxxLBoxCtlHScroll(plb, SB_ENDSCROLL, 0); 00632 00633 /* 00634 * Show/hide scroll bars depending on how much stuff is visible... 00635 * 00636 * Note: Now we only call this guy when cMac == 0, because it is 00637 * called inside the LBoxCtlHScroll with SB_ENDSCROLL otherwise. 00638 */ 00639 if (plb->cMac == 0) 00640 xxxLBShowHideScrollBars(plb); 00641 } 00642 00643 00644 /***************************************************************************\ 00645 * LBSetTabStops 00646 * 00647 * Sets the tab stops for this listbox. Returns TRUE if successful else FALSE. 00648 * 00649 * History: 00650 \***************************************************************************/ 00651 00652 BOOL LBSetTabStops( 00653 PLBIV plb, 00654 INT count, 00655 LPINT lptabstops) 00656 { 00657 PINT ptabs; 00658 00659 if (!plb->fUseTabStops) { 00660 RIPERR0(ERROR_LB_WITHOUT_TABSTOPS, RIP_VERBOSE, ""); 00661 return FALSE; 00662 } 00663 00664 if (count) { 00665 /* 00666 * Allocate memory for the tab stops. The first byte in the 00667 * plb->iTabPixelPositions array will contain a count of the number 00668 * of tab stop positions we have. 00669 */ 00670 ptabs = (LPINT)UserLocalAlloc(HEAP_ZERO_MEMORY, (count + 1) * sizeof(int)); 00671 if (ptabs == NULL) 00672 return FALSE; 00673 00674 if (plb->iTabPixelPositions != NULL) 00675 UserLocalFree(plb->iTabPixelPositions); 00676 plb->iTabPixelPositions = ptabs; 00677 00678 /* 00679 * Set the count of tab stops 00680 */ 00681 *ptabs++ = count; 00682 00683 for (; count > 0; count--) { 00684 00685 /* 00686 * Convert the dialog unit tabstops into pixel position tab stops. 00687 */ 00688 *ptabs++ = MultDiv(*lptabstops, plb->cxChar, 4); 00689 lptabstops++; 00690 } 00691 } else { 00692 00693 /* 00694 * Set default 8 system font ave char width tabs. So free the memory 00695 * associated with the tab stop list. 00696 */ 00697 if (plb->iTabPixelPositions != NULL) { 00698 UserLocalFree((HANDLE)plb->iTabPixelPositions); 00699 plb->iTabPixelPositions = NULL; 00700 } 00701 } 00702 00703 return TRUE; 00704 } 00705 00706 00707 /***************************************************************************\ 00708 * InitHStrings 00709 * 00710 * History: 00711 \***************************************************************************/ 00712 00713 void InitHStrings( 00714 PLBIV plb) 00715 { 00716 if (plb->fHasStrings) { 00717 plb->ichAlloc = 0; 00718 plb->cchStrings = 0; 00719 plb->hStrings = UserLocalAlloc(0, 0L); 00720 } 00721 } 00722 00723 00724 /***************************************************************************\ 00725 * LBDropObjectHandler 00726 * 00727 * Handles a WM_DROPITEM message on this listbox 00728 * 00729 * History: 00730 \***************************************************************************/ 00731 00732 void LBDropObjectHandler( 00733 PLBIV plb, 00734 PDROPSTRUCT pds) 00735 { 00736 LONG mouseSel; 00737 00738 if (ISelFromPt(plb, pds->ptDrop, &mouseSel)) { 00739 00740 /* 00741 * User dropped in empty space at bottom of listbox 00742 */ 00743 pds->dwControlData = (DWORD)-1L; 00744 } else { 00745 pds->dwControlData = mouseSel; 00746 } 00747 } 00748 00749 00750 /***************************************************************************\ 00751 * LBGetSetItemHeightHandler() 00752 * 00753 * Sets/Gets the height associated with each item. For non ownerdraw 00754 * and fixed height ownerdraw, the item number is ignored. 00755 * 00756 * History: 00757 \***************************************************************************/ 00758 00759 int LBGetSetItemHeightHandler( 00760 PLBIV plb, 00761 UINT message, 00762 int item, 00763 UINT height) 00764 { 00765 if (message == LB_GETITEMHEIGHT) { 00766 /* 00767 * All items are same height for non ownerdraw and for fixed height 00768 * ownerdraw. 00769 */ 00770 if (plb->OwnerDraw != OWNERDRAWVAR) 00771 return plb->cyChar; 00772 00773 if (plb->cMac && item >= plb->cMac) { 00774 RIPERR0(ERROR_INVALID_INDEX, RIP_VERBOSE, ""); 00775 return LB_ERR; 00776 } 00777 00778 return (int)LBGetVariableHeightItemHeight(plb, (INT)item); 00779 } 00780 00781 if (!height || height > 255) { 00782 RIPERR1(ERROR_INVALID_PARAMETER, 00783 RIP_WARNING, 00784 "Invalid parameter \"height\" (%ld) to LBGetSetItemHeightHandler", 00785 height); 00786 00787 return LB_ERR; 00788 } 00789 00790 if (plb->OwnerDraw != OWNERDRAWVAR) 00791 plb->cyChar = height; 00792 else { 00793 if (item < 0 || item >= plb->cMac) { 00794 RIPERR1(ERROR_INVALID_PARAMETER, 00795 RIP_WARNING, 00796 "Invalid parameter \"item\" (%ld) to LBGetSetItemHeightHandler", 00797 item); 00798 00799 return LB_ERR; 00800 } 00801 00802 LBSetVariableHeightItemHeight(plb, (INT)item, (INT)height); 00803 } 00804 00805 if (plb->fMultiColumn) 00806 LBCalcItemRowsAndColumns(plb); 00807 00808 LBSetCItemFullMax(plb); 00809 00810 return(0); 00811 } 00812 00813 /*****************************************************************************\ 00814 * 00815 * LBEvent() 00816 * 00817 * This is for item focus & selection events in listboxes. 00818 * 00819 \*****************************************************************************/ 00820 void LBEvent(PLBIV plb, UINT uEvent, int iItem) 00821 { 00822 UserAssert(FWINABLE()); 00823 00824 switch (uEvent) { 00825 case EVENT_OBJECT_SELECTIONREMOVE: 00826 if (plb->wMultiple != SINGLESEL) { 00827 break; 00828 } 00829 iItem = -1; 00830 // 00831 // FALL THRU 00832 // 00833 00834 case EVENT_OBJECT_SELECTIONADD: 00835 if (plb->wMultiple == MULTIPLESEL) { 00836 uEvent = EVENT_OBJECT_SELECTION; 00837 } 00838 break; 00839 00840 case EVENT_OBJECT_SELECTIONWITHIN: 00841 iItem = -1; 00842 break; 00843 } 00844 00845 NotifyWinEvent(uEvent, HW(plb->spwnd), OBJID_CLIENT, iItem+1); 00846 }

Generated on Sat May 15 19:40:37 2004 for test by doxygen 1.3.7