00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
#include "precomp.h"
00014
#pragma hdrstop
00015
00016 extern LOOKASIDE ListboxLookaside;
00017
00018
00019
00020
00021
00022
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
00057
00058
00059
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
00072
00073
00074
00075 plb->
fInitialized =
TRUE;
00076
00077 style = pwnd->style;
00078
00079
00080
00081
00082
if (pwnd->
spwndParent ==
NULL)
00083
Lock(&(plb->
spwndParent),
_GetDesktopWindow());
00084
else
00085
Lock(&(plb->
spwndParent),
REBASEPWND(pwnd, spwndParent));
00086
00087
00088
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
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
00110
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
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;
00135 plb->
iLastMouseMove = -1;
00136
00137
00138
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
00147
00148 plb->
fNoIntegralHeight =
TRUE;
00149 }
00150
00151
if (plb->
OwnerDraw && !(style & LBS_HASSTRINGS)) {
00152
00153
00154
00155
00156 plb->
fHasStrings =
FALSE;
00157 }
00158
00159
00160
00161
00162
00163 plb->
fSort = ((style & LBS_SORT) != 0);
00164
00165
00166
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
00183
00184
if ((style &
LBS_COMBOBOX) != 0) {
00185
00186
00187
00188
00189
00190
if (plb->
spwndParent->
cbwndExtra != 0)
00191 plb->
pcbox = ((
PCOMBOWND)(plb->
spwndParent))->pcbox;
00192 }
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223 plb->
iSel = -1;
00224
00225 plb->
hdc =
NULL;
00226
00227
00228
00229
00230
00231 plb->
fNewItemState =
TRUE;
00232
00233
InitHStrings(plb);
00234
00235
if (plb->
fHasStrings && plb->
hStrings ==
NULL) {
00236
return -1
L;
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
00253
00254
00255 measureItemStruct.CtlType = ODT_LISTBOX;
00256 measureItemStruct.CtlID = PtrToUlong(pwnd->
spmenu);
00257
00258
00259
00260
00261 measureItemStruct.itemHeight = plb->
cyChar;
00262 measureItemStruct.itemWidth = 0;
00263 measureItemStruct.itemData = 0;
00264
00265
00266
00267
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
00277
00278
00279
if (measureItemStruct.itemHeight)
00280 plb->
cyChar = measureItemStruct.itemHeight;
00281
00282
00283
if (plb->
fMultiColumn) {
00284
00285
00286
00287
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
00299
00300
00301
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
00311
00312
00313
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
00330
00331
00332
00333
00334
00335
PostMessage(
HWq(pwnd), WM_SIZE, 0, 0
L);
00336 }
00337
00338
return 1
L;
00339 }
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350 void xxxLBoxDoDeleteItems(
00351
PLBIV plb)
00352 {
00353
INT sItem;
00354
00355
CheckLock(plb->
spwnd);
00356
00357
00358
00359
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
00371
00372
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
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
00418
00419
NtUserSetWindowFNID(
HWq(pwnd),
FNID_CLEANEDUP_BIT);
00420
00421
00422
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
00434
00435
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
00472
00473
00474 plb->
cyChar = iHeight;
00475
00476
00477
00478
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
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
00510
00511
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
00531
if ((rc.bottom - rc.top) % plb->
cyChar) {
00532
int iItems = (rc.bottom - rc.top);
00533
00534
00535
00536
00537
00538
if ( !
TestWF( plb->
spwnd,
WFWIN40COMPAT ) )
00539 iItems += (cBdrs *
SYSMET(CYEDGE));
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
00549
00550
00551
00552
return;
00553 }
00554 }
00555
00556
if (plb->
fMultiColumn) {
00557
00558
00559
00560
00561
LBCalcItemRowsAndColumns(plb);
00562 }
else {
00563
00564
00565
00566
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
00577
00578
00579
00580 iTopOld = plb->
iTop;
00581 fSizedSave = plb->
fSized;
00582 plb->
fSized =
FALSE;
00583
xxxNewITop(plb, plb->
iTop);
00584
00585
00586
00587
00588
00589
if (plb->
fSized)
00590
return;
00591 plb->
fSized = fSizedSave;
00592
00593
if (
IsLBoxVisible(plb)) {
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
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
00612
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
00622
00623
00624
if (
TestWF(plb->
spwnd,
WFVSCROLL)) {
00625
xxxLBoxCtlScroll(plb, SB_ENDSCROLL, 0);
00626 }
00627
00628
00629
00630
00631
xxxLBoxCtlHScroll(plb, SB_ENDSCROLL, 0);
00632
00633
00634
00635
00636
00637
00638
00639
if (plb->
cMac == 0)
00640
xxxLBShowHideScrollBars(plb);
00641 }
00642
00643
00644
00645
00646
00647
00648
00649
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
00667
00668
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
00680
00681 *ptabs++ = count;
00682
00683
for (; count > 0; count--) {
00684
00685
00686
00687
00688 *ptabs++ =
MultDiv(*lptabstops, plb->
cxChar, 4);
00689 lptabstops++;
00690 }
00691 }
else {
00692
00693
00694
00695
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
00709
00710
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, 0
L);
00720 }
00721 }
00722
00723
00724
00725
00726
00727
00728
00729
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
00742
00743 pds->dwControlData = (
DWORD)-1
L;
00744 }
else {
00745 pds->dwControlData = mouseSel;
00746 }
00747 }
00748
00749
00750
00751
00752
00753
00754
00755
00756
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
00768
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
00816
00817
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
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 }