00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
#include "precomp.h"
00015
#pragma hdrstop
00016
00017 extern LOOKASIDE ComboboxLookaside;
00018
00019 #define RECALC_CYDROP -1
00020
00021
void xxxCBSetDroppedSize(
PCBOX pcbox, LPRECT lprc);
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 LONG
CBNcCreateHandler(
00032
PCBOX pcbox,
00033
PWND pwnd)
00034 {
00035
00036
00037
00038
00039 pcbox->
styleSave = pwnd->style & (WS_VSCROLL | WS_HSCROLL);
00040
00041
if (!
TestWF(pwnd,
CBFOWNERDRAW))
00042
00043
SetWindowState(pwnd,
CBFHASSTRINGS);
00044
00045 UserAssert(
HIBYTE(
WFVSCROLL) ==
HIBYTE(
WFHSCROLL));
00046 UserAssert(
HIBYTE(
WFHSCROLL) ==
HIBYTE(
WFBORDER));
00047
ClearWindowState(pwnd,
WFVSCROLL |
WFHSCROLL |
WFBORDER);
00048
00049
00050
00051
00052
00053
if (
TestWF(pwnd,
WFWIN40COMPAT) ||
TestWF(pwnd,
WEFCLIENTEDGE))
00054 pcbox->
f3DCombo =
TRUE;
00055
00056
ClearWindowState(pwnd,
WEFEDGEMASK);
00057
00058
return (LONG)
TRUE;
00059 }
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070 LRESULT
xxxCBCreateHandler(
00071
PCBOX pcbox,
00072
PWND pwnd)
00073 {
00074 LONG lStyleT;
00075 RECT rcList;
00076 HWND hwndList;
00077 HWND hwndEdit;
00078
DWORD lExStyle;
00079
00080
CheckLock(pwnd);
00081
00082
00083
00084
00085
00086
00087
00088
Lock(&(pcbox->
spwndParent),
REBASEPWND(pwnd, spwndParent));
00089
00090
00091
00092
00093
00094
00095
if (
TestWF(pwnd,
CBFDROPDOWNLIST) ==
LOBYTE(
CBFDROPDOWNLIST)) {
00096 pcbox->
CBoxStyle =
SDROPDOWNLIST;
00097 pcbox->
fNoEdit =
TRUE;
00098 }
else if (
TestWF(pwnd,
CBFDROPDOWN))
00099 pcbox->
CBoxStyle =
SDROPDOWN;
00100
else
00101 pcbox->
CBoxStyle =
SSIMPLE;
00102
00103 pcbox->
fRtoLReading = (
TestWF(pwnd,
WEFRTLREADING) != 0);
00104 pcbox->
fRightAlign = (
TestWF(pwnd,
WEFRIGHT) != 0);
00105
00106
if (
TestWF(pwnd,
CBFUPPERCASE))
00107 pcbox->
fCase =
UPPERCASE;
00108
else if (
TestWF(pwnd,
CBFLOWERCASE))
00109 pcbox->
fCase =
LOWERCASE;
00110
else
00111 pcbox->
fCase = 0;
00112
00113
00114
if (
TestWF(pwnd,
CBFOWNERDRAWVAR))
00115 pcbox->
OwnerDraw =
OWNERDRAWVAR;
00116
if (
TestWF(pwnd,
CBFOWNERDRAWFIXED)) {
00117 pcbox->
OwnerDraw =
OWNERDRAWFIXED;
00118 }
00119
00120
00121
00122
00123
00124 pcbox->
cxCombo = pwnd->
rcWindow.right - pwnd->
rcWindow.left;
00125 pcbox->
cyDrop =
RECALC_CYDROP;
00126 pcbox->
cxDrop = 0;
00127
xxxCBCalcControlRects(pcbox, &rcList);
00128
00129
00130
00131
00132
00133
if (!
TestWF(pwnd,
WFWIN40COMPAT))
00134
InflateRect(&rcList, -
SYSMET(CXBORDER), -
SYSMET(CYBORDER));
00135
00136
00137
00138
00139
00140
00141
00142
00143 lStyleT = pcbox->
styleSave;
00144
00145 lStyleT |= WS_CHILD | WS_VISIBLE | LBS_NOTIFY |
LBS_COMBOBOX | WS_CLIPSIBLINGS;
00146
00147
if (
TestWF(pwnd,
WFDISABLED))
00148 lStyleT |= WS_DISABLED;
00149
if (
TestWF(pwnd,
CBFNOINTEGRALHEIGHT))
00150 lStyleT |= LBS_NOINTEGRALHEIGHT;
00151
if (
TestWF(pwnd,
CBFSORT))
00152 lStyleT |= LBS_SORT;
00153
if (
TestWF(pwnd,
CBFHASSTRINGS))
00154 lStyleT |= LBS_HASSTRINGS;
00155
if (
TestWF(pwnd,
CBFDISABLENOSCROLL))
00156 lStyleT |= LBS_DISABLENOSCROLL;
00157
00158
if (pcbox->
OwnerDraw ==
OWNERDRAWVAR)
00159 lStyleT |= LBS_OWNERDRAWVARIABLE;
00160
else if (pcbox->
OwnerDraw ==
OWNERDRAWFIXED)
00161 lStyleT |= LBS_OWNERDRAWFIXED;
00162
00163
if (pcbox->
CBoxStyle &
SDROPPABLE)
00164 lStyleT |= WS_BORDER;
00165
00166 lExStyle = pwnd->ExStyle & (WS_EX_RIGHT | WS_EX_RTLREADING | WS_EX_LEFTSCROLLBAR);
00167 hwndList =
_CreateWindowEx(lExStyle |
00168 ((pcbox->
CBoxStyle &
SDROPPABLE) ? WS_EX_TOOLWINDOW : WS_EX_CLIENTEDGE),
00169 MAKEINTRESOURCE(
gpsi->
atomSysClass[
ICLS_COMBOLISTBOX]),
NULL, lStyleT,
00170 rcList.left, rcList.top, rcList.right - rcList.left,
00171 rcList.bottom - rcList.top,
00172
HW(pwnd), (HMENU)
CBLISTBOXID, pcbox->
spwnd->hModule,
NULL,
00173 0);
00174
Lock(&(pcbox->
spwndList),
ValidateHwnd(hwndList));
00175
00176
if (!pcbox->
spwndList) {
00177
return -1;
00178 }
00179
00180
00181
00182
00183
if (pcbox->
fNoEdit) {
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195 pcbox->
spwndEdit = pcbox->
spwnd;
00196 }
else {
00197
DWORD dwCsFlags;
00198
00199 lStyleT = WS_CHILD | WS_VISIBLE | ES_COMBOBOX | ES_NOHIDESEL;
00200
if (
TestWF(pwnd,
WFDISABLED))
00201 lStyleT |= WS_DISABLED;
00202
if (
TestWF(pwnd,
CBFAUTOHSCROLL))
00203 lStyleT |= ES_AUTOHSCROLL;
00204
if (
TestWF(pwnd,
CBFOEMCONVERT))
00205 lStyleT |= ES_OEMCONVERT;
00206
if (pcbox->
fCase)
00207 lStyleT |= (pcbox->
fCase &
UPPERCASE) ? ES_UPPERCASE : ES_LOWERCASE;
00208
00209
00210
00211
00212
00213 dwCsFlags =
TestWF(pcbox->
spwnd,
WFANSICREATOR) ? CW_FLAGS_ANSI : 0
L;
00214
if (lExStyle & WS_EX_RIGHT)
00215 lStyleT |= ES_RIGHT;
00216
00217 hwndEdit =
_CreateWindowEx(lExStyle,
00218 MAKEINTRESOURCE(
gpsi->
atomSysClass[
ICLS_EDIT]),
NULL, lStyleT,
00219 pcbox->
editrc.left, pcbox->
editrc.top,
00220 pcbox->
editrc.right - pcbox->
editrc.left, pcbox->
editrc.bottom -
00221 pcbox->
editrc.top,
HW(pwnd), (HMENU)
CBEDITID,
00222 pcbox->
spwnd->hModule,
NULL,
00223 dwCsFlags);
00224
Lock(&(pcbox->
spwndEdit),
ValidateHwnd(hwndEdit));
00225 }
00226
if (!pcbox->
spwndEdit)
00227
return -1
L;
00228
00229
if (pcbox->
CBoxStyle &
SDROPPABLE) {
00230
00231
NtUserShowWindow(hwndList, SW_HIDE);
00232
NtUserSetParent(hwndList,
NULL);
00233
00234
00235
if (!
TestWF(pwnd,
WFWIN40COMPAT))
00236
InflateRect(&rcList,
SYSMET(CXBORDER),
SYSMET(CYBORDER));
00237
00238
xxxCBSetDroppedSize(pcbox, &rcList);
00239 }
00240
00241
00242
00243
00244
return (LRESULT)pwnd;
00245 }
00246
00247
00248
00249
00250
00251
00252
00253 void xxxCBCalcControlRects(
PCBOX pcbox, LPRECT lprcList)
00254 {
00255 HDC hdc;
00256 HANDLE hOldFont =
NULL;
00257
int dyEdit, dxEdit;
00258 MEASUREITEMSTRUCT mis;
00259 SIZE size;
00260 HWND hwnd =
HWq(pcbox->
spwnd);
00261
TL tlpwndParent;
00262
00263
CheckLock(pcbox->
spwnd);
00264
00265
00266
00267
00268
00269
00270 hdc =
NtUserGetDC(hwnd);
00271
if (pcbox->
hFont) {
00272 hOldFont = SelectObject(hdc, pcbox->
hFont);
00273 }
00274
00275
00276
00277
00278 GetTextExtentPoint(hdc,
szOneChar, 1, &size);
00279 dyEdit = size.cy +
SYSMET(CYEDGE);
00280
00281
if (hOldFont) {
00282 SelectObject(hdc, hOldFont);
00283 }
00284
00285
00286
00287
00288
NtUserReleaseDC(hwnd, hdc);
00289
00290
if (pcbox->
OwnerDraw) {
00291
00292
00293
int iOwnerDrawHeight;
00294
00295
if (iOwnerDrawHeight = pcbox->
editrc.bottom - pcbox->
editrc.top) {
00296 dyEdit = iOwnerDrawHeight;
00297 }
else {
00298
00299
00300
00301
00302 mis.CtlType = ODT_COMBOBOX;
00303 mis.CtlID = PtrToUlong(pcbox->
spwnd->
spmenu);
00304 mis.itemID = (
UINT)-1;
00305 mis.itemHeight = dyEdit;
00306 mis.itemData = 0;
00307
00308
ThreadLock(pcbox->
spwndParent, &tlpwndParent);
00309
SendMessage(
HW(pcbox->
spwndParent), WM_MEASUREITEM, mis.CtlID, (LPARAM)&mis);
00310
ThreadUnlock(&tlpwndParent);
00311
00312 dyEdit = mis.itemHeight;
00313 }
00314 }
00315
00316
00317
00318
00319 pcbox->
cyCombo = 2*
SYSMET(CYFIXEDFRAME) + dyEdit;
00320 dxEdit = pcbox->
cxCombo - (2 *
SYSMET(CXFIXEDFRAME));
00321
00322
if (pcbox->
cyDrop ==
RECALC_CYDROP)
00323 {
00324
00325
00326 pcbox->
cyDrop =
max((pcbox->
spwnd->
rcWindow.bottom - pcbox->
spwnd->
rcWindow.top) - pcbox->
cyCombo, 0);
00327
00328
if (!
TestWF(pcbox->
spwnd,
WFWIN40COMPAT) && (pcbox->
cyDrop == 23))
00329
00330
00331
00332 pcbox->
cyDrop = 28;
00333 }
00334
00335
00336
00337
00338
00339
00340
00341
00342
if (pcbox->
CBoxStyle &
SDROPPABLE) {
00343
00344 pcbox->
buttonrc.top =
SYSMET(CYEDGE);
00345 pcbox->
buttonrc.bottom = pcbox->
cyCombo -
SYSMET(CYEDGE);
00346
if (pcbox->
fRightAlign) {
00347 pcbox->
buttonrc.left =
SYSMET(CXFIXEDFRAME);
00348 pcbox->
buttonrc.right = pcbox->
buttonrc.left +
SYSMET(CXVSCROLL);
00349 }
else {
00350 pcbox->
buttonrc.right = pcbox->
cxCombo -
SYSMET(CXEDGE);
00351 pcbox->
buttonrc.left = pcbox->
buttonrc.right -
SYSMET(CXVSCROLL);
00352 }
00353
00354
00355 dxEdit =
max(dxEdit -
SYSMET(CXVSCROLL), 0);
00356
00357 }
else {
00358
00359
00360
00361
00362
00363
SetRectEmpty(&pcbox->
buttonrc);
00364 }
00365
00366
00367
00368
00369 pcbox->
editrc.left =
SYSMET(CXFIXEDFRAME);
00370 pcbox->
editrc.right = pcbox->
editrc.left + dxEdit;
00371 pcbox->
editrc.top =
SYSMET(CYFIXEDFRAME);
00372 pcbox->
editrc.bottom = pcbox->
editrc.top + dyEdit;
00373
00374
00375
if ((pcbox->
CBoxStyle &
SDROPPABLE) && (pcbox->
fRightAlign)) {
00376 pcbox->
editrc.right = pcbox->
cxCombo -
SYSMET(CXEDGE);
00377 pcbox->
editrc.left = pcbox->
editrc.right - dxEdit;
00378 }
00379
00380 lprcList->left = 0;
00381 lprcList->top = pcbox->
cyCombo;
00382 lprcList->right =
max(pcbox->
cxDrop, pcbox->
cxCombo);
00383 lprcList->bottom = pcbox->
cyCombo + pcbox->
cyDrop;
00384 }
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394 void xxxCBNcDestroyHandler(
00395
PWND pwnd,
00396
PCBOX pcbox)
00397 {
00398
CheckLock(pwnd);
00399
00400
00401
00402
00403
if (pcbox !=
NULL) {
00404
00405
00406
00407
00408
00409
if (pcbox->
spwndList !=
NULL) {
00410
NtUserDestroyWindow(
HWq(pcbox->
spwndList));
00411
Unlock(&pcbox->
spwndList);
00412 }
00413
00414 pcbox->
spwnd =
NULL;
00415
Unlock(&pcbox->
spwndParent);
00416
00417
00418
00419
00420
00421
if (pwnd != pcbox->
spwndEdit) {
00422
Unlock(&pcbox->
spwndEdit);
00423 }
00424
00425
00426
00427
00428
FreeLookasideEntry(&
ComboboxLookaside, pcbox);
00429 }
00430
00431
00432
00433
00434
NtUserSetWindowFNID(
HWq(pwnd),
FNID_CLEANEDUP_BIT);
00435 }
00436
00437
00438
00439
00440
00441
00442
00443 void xxxCBSetFontHandler(
00444
PCBOX pcbox,
00445 HANDLE hFont,
00446 BOOL fRedraw)
00447 {
00448
TL tlpwndEdit;
00449
TL tlpwndList;
00450
00451
CheckLock(pcbox->
spwnd);
00452
00453
ThreadLock(pcbox->
spwndEdit, &tlpwndEdit);
00454
ThreadLock(pcbox->
spwndList, &tlpwndList);
00455
00456 pcbox->
hFont = hFont;
00457
00458
if (!pcbox->
fNoEdit && pcbox->
spwndEdit) {
00459
SendMessageWorker(pcbox->
spwndEdit, WM_SETFONT, (WPARAM)hFont,
FALSE,
FALSE);
00460 }
00461
00462
SendMessageWorker(pcbox->
spwndList, WM_SETFONT, (WPARAM)hFont,
FALSE,
FALSE);
00463
00464
00465
xxxCBPosition(pcbox);
00466
00467
if (fRedraw) {
00468
NtUserInvalidateRect(
HWq(pcbox->
spwnd),
NULL,
TRUE);
00469
00470 }
00471
00472
ThreadUnlock(&tlpwndList);
00473
ThreadUnlock(&tlpwndEdit);
00474 }
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485 LONG
xxxCBSetEditItemHeight(
00486
PCBOX pcbox,
00487
int dyEdit)
00488 {
00489
TL tlpwndEdit;
00490
TL tlpwndList;
00491
00492
CheckLock(pcbox->
spwnd);
00493
00494
if (dyEdit > 255) {
00495 RIPERR0(ERROR_INVALID_EDIT_HEIGHT, RIP_VERBOSE,
"");
00496
return CB_ERR;
00497 }
00498
00499 pcbox->
editrc.bottom = pcbox->
editrc.top + dyEdit;
00500 pcbox->
cyCombo = pcbox->
editrc.bottom +
SYSMET(CYFIXEDFRAME);
00501
00502
if (pcbox->
CBoxStyle &
SDROPPABLE) {
00503 pcbox->
buttonrc.bottom = pcbox->
cyCombo -
SYSMET(CYEDGE);
00504 }
00505
00506
ThreadLock(pcbox->
spwndEdit, &tlpwndEdit);
00507
ThreadLock(pcbox->
spwndList, &tlpwndList);
00508
00509
00510
00511
00512
00513
00514
00515
00516
if (!pcbox->
fNoEdit && pcbox->
spwndEdit) {
00517
NtUserMoveWindow(
HWq(pcbox->
spwndEdit), pcbox->
editrc.left, pcbox->
editrc.top,
00518 pcbox->
editrc.right-pcbox->
editrc.left, dyEdit,
TRUE);
00519 }
00520
00521
00522
00523
00524
if (pcbox->
CBoxStyle ==
SSIMPLE) {
00525
if (pcbox->
spwndList != 0) {
00526
NtUserMoveWindow(
HWq(pcbox->
spwndList), 0, pcbox->
cyCombo, pcbox->
cxCombo,
00527 pcbox->
cyDrop,
FALSE);
00528
00529
NtUserSetWindowPos(
HWq(pcbox->
spwnd), HWND_TOP, 0, 0,
00530 pcbox->
cxCombo, pcbox->
cyCombo +
00531 pcbox->
spwndList->
rcWindow.bottom - pcbox->
spwndList->
rcWindow.top,
00532 SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
00533 }
00534 }
else {
00535
if (pcbox->
spwndList !=
NULL) {
00536
NtUserMoveWindow(
HWq(pcbox->
spwndList), pcbox->
spwnd->
rcWindow.left,
00537 pcbox->
spwnd->
rcWindow.top + pcbox->
cyCombo,
00538
max(pcbox->
cxDrop, pcbox->
cxCombo), pcbox->
cyDrop,
FALSE);
00539 }
00540
00541
NtUserSetWindowPos(
HWq(pcbox->
spwnd), HWND_TOP, 0, 0,
00542 pcbox->
cxCombo, pcbox->
cyCombo,
00543 SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
00544 }
00545
00546
ThreadUnlock(&tlpwndList);
00547
ThreadUnlock(&tlpwndEdit);
00548
00549
return CB_OKAY;
00550 }
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563 void xxxCBSizeHandler(
00564
PCBOX pcbox)
00565 {
00566
CheckLock(pcbox->
spwnd);
00567
00568
00569
00570
00571
00572 pcbox->
cxCombo = pcbox->
spwnd->
rcWindow.right - pcbox->
spwnd->
rcWindow.left;
00573
00574
00575
if (((pcbox->
spwnd->
rcWindow.bottom - pcbox->
spwnd->
rcWindow.top) - pcbox->
cyCombo) > 0)
00576 pcbox->
cyDrop =
RECALC_CYDROP;
00577
00578
00579
xxxCBPosition(pcbox);
00580 }
00581
00582
00583
00584
00585
00586
00587
00588
00589 void xxxCBPosition(
PCBOX pcbox)
00590 {
00591 RECT rcList;
00592
00593
00594
xxxCBCalcControlRects(pcbox, &rcList);
00595
00596
if (!pcbox->
fNoEdit && pcbox->
spwndEdit) {
00597
TL tlpwndEdit;
00598
00599
ThreadLock(pcbox->
spwndEdit, &tlpwndEdit);
00600
NtUserMoveWindow(
HWq(pcbox->
spwndEdit), pcbox->
editrc.left, pcbox->
editrc.top,
00601 pcbox->
editrc.right - pcbox->
editrc.left,
00602 pcbox->
editrc.bottom - pcbox->
editrc.top,
TRUE);
00603
ThreadUnlock(&tlpwndEdit);
00604 }
00605
00606
00607
xxxCBSetDroppedSize(pcbox, &rcList);
00608 }
00609
00610
00611
00612
00613
00614
00615
00616
00617 void xxxCBSetDroppedSize(
PCBOX pcbox, LPRECT lprc)
00618 {
00619
TL tlpwndList;
00620
00621 pcbox->
fLBoxVisible =
TRUE;
00622
xxxCBHideListBoxWindow(pcbox,
FALSE,
FALSE);
00623
00624
ThreadLock(pcbox->
spwndList, &tlpwndList);
00625
NtUserMoveWindow(
HWq(pcbox->
spwndList), lprc->left, lprc->top,
00626 lprc->right - lprc->left, lprc->bottom - lprc->top,
FALSE);
00627
ThreadUnlock(&tlpwndList);
00628
00629 }