4 * Copyright 1997 Alex Korobka
6 * FIXME: roll up in Netscape 3.01.
13 #include "sysmetrics.h"
25 /* bits in the dwKeyData */
26 #define KEYDATA_ALT 0x2000
27 #define KEYDATA_PREVSTATE 0x4000
30 * Additional combo box definitions
33 #define CB_GETPTR( wnd ) (*(LPHEADCOMBO*)((wnd)->wExtra))
34 #define CB_NOTIFY( lphc, code ) \
35 (SendMessage32A( (lphc)->owner, WM_COMMAND, \
36 MAKEWPARAM((lphc)->self->wIDmenu, (code)), (lphc)->self->hwndSelf))
37 #define CB_GETEDITTEXTLENGTH( lphc ) \
38 (SendMessage32A( (lphc)->hWndEdit, WM_GETTEXTLENGTH, 0, 0 ))
40 static HBITMAP16 hComboBmp = 0;
41 static UINT16 CBitHeight, CBitWidth;
42 static UINT16 CBitOffset = 8;
44 /***********************************************************************
47 * Load combo button bitmap.
49 static BOOL32 COMBO_Init()
53 if( hComboBmp ) return TRUE;
54 if( (hDC = CreateCompatibleDC16(0)) )
57 if( (hComboBmp = LoadBitmap16(0, MAKEINTRESOURCE(OBM_COMBO))) )
63 GetObject16( hComboBmp, sizeof(bm), &bm );
64 CBitHeight = bm.bmHeight;
65 CBitWidth = bm.bmWidth;
67 dprintf_combo(stddeb, "combo bitmap [%i,%i]\n", CBitWidth, CBitHeight );
69 hPrevB = SelectObject16( hDC, hComboBmp);
70 SetRect16( &r, 0, 0, CBitWidth, CBitHeight );
71 InvertRect16( hDC, &r );
72 SelectObject16( hDC, hPrevB );
81 /***********************************************************************
84 static LRESULT COMBO_NCCreate(WND* wnd, LPARAM lParam)
88 if ( wnd && COMBO_Init() &&
89 (lphc = HeapAlloc(GetProcessHeap(), 0, sizeof(HEADCOMBO))) )
91 LPCREATESTRUCT32A lpcs = (CREATESTRUCT32A*)lParam;
93 memset( lphc, 0, sizeof(HEADCOMBO) );
94 *(LPHEADCOMBO*)wnd->wExtra = lphc;
96 /* some braindead apps do try to use scrollbar/border flags */
98 lphc->dwStyle = (lpcs->style & ~(WS_BORDER | WS_HSCROLL | WS_VSCROLL));
99 wnd->dwStyle &= ~(WS_BORDER | WS_HSCROLL | WS_VSCROLL);
101 if( !(lpcs->style & (CBS_OWNERDRAWFIXED | CBS_OWNERDRAWVARIABLE)) )
102 lphc->dwStyle |= CBS_HASSTRINGS;
103 if( !(wnd->dwExStyle & WS_EX_NOPARENTNOTIFY) )
104 lphc->wState |= CBF_NOTIFY;
106 dprintf_combo(stddeb, "COMBO_NCCreate: [0x%08x], style = %08x\n",
107 (UINT32)lphc, lphc->dwStyle );
109 return (LRESULT)(UINT32)wnd->hwndSelf;
111 return (LRESULT)FALSE;
114 /***********************************************************************
117 static LRESULT COMBO_NCDestroy( LPHEADCOMBO lphc )
122 WND* wnd = lphc->self;
124 dprintf_combo(stddeb,"Combo [%04x]: freeing storage\n", CB_HWND(lphc));
126 if( (CB_GETTYPE(lphc) != CBS_SIMPLE) && lphc->hWndLBox )
127 DestroyWindow32( lphc->hWndLBox );
129 HeapFree( GetProcessHeap(), 0, lphc );
135 /***********************************************************************
138 * Set up component coordinates given valid lphc->RectCombo.
140 static void CBCalcPlacement( LPHEADCOMBO lphc,
141 LPRECT16 lprEdit, LPRECT16 lprButton, LPRECT16 lprLB )
143 RECT16 rect = lphc->RectCombo;
146 /* get combo height and width */
148 if( lphc->editHeight )
149 size.cy = (INT16)lphc->editHeight;
152 HDC16 hDC = GetDC16( lphc->self->hwndSelf );
153 HFONT16 hPrevFont = (HFONT16)0;
155 if( lphc->hFont ) hPrevFont = SelectObject16( hDC, lphc->hFont );
157 GetTextExtentPoint16( hDC, "0", 1, &size);
159 size.cy += size.cy / 4 + 4 * SYSMETRICS_CYBORDER;
161 if( hPrevFont ) SelectObject16( hDC, hPrevFont );
162 ReleaseDC16( lphc->self->hwndSelf, hDC );
164 size.cx = rect.right - rect.left;
166 if( CB_OWNERDRAWN(lphc) )
168 UINT16 u = lphc->RectEdit.bottom - lphc->RectEdit.top;
170 if( lphc->wState & CBF_MEASUREITEM ) /* first initialization */
172 MEASUREITEMSTRUCT32 mi32;
174 lphc->wState &= ~CBF_MEASUREITEM;
175 mi32.CtlType = ODT_COMBOBOX;
176 mi32.CtlID = lphc->self->wIDmenu;
178 mi32.itemWidth = size.cx;
179 mi32.itemHeight = size.cy - 6; /* ownerdrawn cb is taller */
181 SendMessage32A(lphc->owner, WM_MEASUREITEM,
182 (WPARAM32)mi32.CtlID, (LPARAM)&mi32);
183 u = 6 + (UINT16)mi32.itemHeight;
188 /* calculate text and button placement */
190 lprEdit->left = lprEdit->top = lprButton->top = 0;
191 if( CB_GETTYPE(lphc) == CBS_SIMPLE ) /* no button */
192 lprButton->left = lprButton->right = lprButton->bottom = 0;
195 INT32 i = size.cx - CBitWidth - 10; /* seems ok */
197 lprButton->right = size.cx;
198 lprButton->left = (INT16)i;
199 lprButton->bottom = lprButton->top + size.cy;
201 if( i < 0 ) size.cx = 0;
202 else size.cx = (INT16)i;
205 if( CB_GETTYPE(lphc) == CBS_DROPDOWN )
207 size.cx -= CBitOffset;
208 if( size.cx < 0 ) size.cx = 0;
211 lprEdit->right = size.cx; lprEdit->bottom = size.cy;
213 /* listbox placement */
215 lprLB->left = ( CB_GETTYPE(lphc) == CBS_DROPDOWNLIST ) ? 0 : CBitOffset;
216 lprLB->top = lprEdit->bottom - SYSMETRICS_CYBORDER;
217 lprLB->right = rect.right - rect.left;
218 lprLB->bottom = rect.bottom - rect.top;
220 if( lphc->droppedWidth > (lprLB->right - lprLB->left) )
221 lprLB->right = lprLB->left + (INT16)lphc->droppedWidth;
223 dprintf_combo(stddeb,"Combo [%04x]: (%i,%i-%i,%i) placement\n\ttext\t= (%i,%i-%i,%i)\
224 \n\tbutton\t= (%i,%i-%i,%i)\n\tlbox\t= (%i,%i-%i,%i)\n", CB_HWND(lphc),
225 lphc->RectCombo.left, lphc->RectCombo.top, lphc->RectCombo.right, lphc->RectCombo.bottom,
226 lprEdit->left, lprEdit->top, lprEdit->right, lprEdit->bottom,
227 lprButton->left, lprButton->top, lprButton->right, lprButton->bottom,
228 lprLB->left, lprLB->top, lprLB->right, lprLB->bottom );
232 /***********************************************************************
233 * CBGetDroppedControlRect32
235 static void CBGetDroppedControlRect32( LPHEADCOMBO lphc, LPRECT32 lpRect)
237 lpRect->left = lphc->RectCombo.left +
238 (lphc->wState & CBF_EDIT) ? CBitOffset : 0;
239 lpRect->top = lphc->RectCombo.top + lphc->RectEdit.bottom -
241 lpRect->right = lphc->RectCombo.right;
242 lpRect->bottom = lphc->RectCombo.bottom - SYSMETRICS_CYBORDER;
245 /***********************************************************************
248 static LRESULT COMBO_Create( LPHEADCOMBO lphc, WND* wnd, LPARAM lParam)
250 static char clbName[] = "ComboLBox";
251 static char editName[] = "Edit";
253 LPCREATESTRUCT32A lpcs = (CREATESTRUCT32A*)lParam;
255 if( !CB_GETTYPE(lphc) ) lphc->dwStyle |= CBS_SIMPLE;
256 else if( CB_GETTYPE(lphc) != CBS_DROPDOWNLIST ) lphc->wState |= CBF_EDIT;
259 lphc->owner = lpcs->hwndParent;
261 /* M$ IE 3.01 actually creates (and rapidly destroys) an ownerless combobox */
263 if( lphc->owner || !(lpcs->style & WS_VISIBLE) )
266 RECT16 editRect, btnRect, lbRect;
268 GetWindowRect16( wnd->hwndSelf, &lphc->RectCombo );
270 lphc->wState |= CBF_MEASUREITEM;
271 CBCalcPlacement( lphc, &editRect, &btnRect, &lbRect );
272 lphc->RectButton = btnRect;
273 lphc->droppedWidth = lphc->editHeight = 0;
275 /* create listbox popup */
277 lbeStyle = (LBS_NOTIFY | WS_BORDER | WS_CLIPSIBLINGS) |
278 (lpcs->style & (WS_VSCROLL | CBS_OWNERDRAWFIXED | CBS_OWNERDRAWVARIABLE));
280 if( lphc->dwStyle & CBS_SORT )
281 lbeStyle |= LBS_SORT;
282 if( lphc->dwStyle & CBS_HASSTRINGS )
283 lbeStyle |= LBS_HASSTRINGS;
284 if( lphc->dwStyle & CBS_NOINTEGRALHEIGHT )
285 lbeStyle |= LBS_NOINTEGRALHEIGHT;
286 if( lphc->dwStyle & CBS_DISABLENOSCROLL )
287 lbeStyle |= LBS_DISABLENOSCROLL;
289 if( CB_GETTYPE(lphc) == CBS_SIMPLE ) /* child listbox */
290 lbeStyle |= WS_CHILD | WS_VISIBLE;
291 else /* popup listbox */
293 lbeStyle |= WS_POPUP;
294 OffsetRect16( &lbRect, lphc->RectCombo.left, lphc->RectCombo.top );
297 /* Dropdown ComboLBox is not a child window and we cannot pass
298 * ID_CB_LISTBOX directly because it will be treated as a menu handle.
301 lphc->hWndLBox = CreateWindowEx32A( 0, clbName, NULL, lbeStyle,
302 lbRect.left + SYSMETRICS_CXBORDER,
303 lbRect.top + SYSMETRICS_CYBORDER,
304 lbRect.right - lbRect.left - 2 * SYSMETRICS_CXBORDER,
305 lbRect.bottom - lbRect.top - 2 * SYSMETRICS_CYBORDER,
306 lphc->self->hwndSelf,
307 (lphc->dwStyle & CBS_DROPDOWN)? (HMENU32)0 : (HMENU32)ID_CB_LISTBOX,
308 lphc->self->hInstance, (LPVOID)lphc );
312 lbeStyle = WS_CHILD | WS_VISIBLE | WS_BORDER | ES_NOHIDESEL | ES_LEFT;
313 if( lphc->wState & CBF_EDIT )
315 if( lphc->dwStyle & CBS_OEMCONVERT )
316 lbeStyle |= ES_OEMCONVERT;
317 if( lphc->dwStyle & CBS_AUTOHSCROLL )
318 lbeStyle |= ES_AUTOHSCROLL;
319 if( lphc->dwStyle & CBS_LOWERCASE )
320 lbeStyle |= ES_LOWERCASE;
321 else if( lphc->dwStyle & CBS_UPPERCASE )
322 lbeStyle |= ES_UPPERCASE;
323 lphc->hWndEdit = CreateWindowEx32A( 0, editName, NULL, lbeStyle,
324 editRect.left, editRect.top, editRect.right - editRect.left,
325 editRect.bottom - editRect.top, lphc->self->hwndSelf,
326 (HMENU32)ID_CB_EDIT, lphc->self->hInstance, NULL );
327 if( !lphc->hWndEdit ) bEdit = FALSE;
332 lphc->RectEdit = editRect;
333 if( CB_GETTYPE(lphc) != CBS_SIMPLE )
335 lphc->wState |= CBF_NORESIZE;
336 SetWindowPos32( wnd->hwndSelf, 0, 0, 0,
337 lphc->RectCombo.right - lphc->RectCombo.left,
338 lphc->RectEdit.bottom - lphc->RectEdit.top,
339 SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE );
340 lphc->wState &= ~CBF_NORESIZE;
342 dprintf_combo(stddeb,"COMBO_Create: init done\n");
343 return wnd->hwndSelf;
345 dprintf_combo(stderr, "COMBO_Create: edit control failure.\n");
346 } else dprintf_combo(stderr, "COMBO_Create: listbox failure.\n");
347 } else dprintf_combo(stderr, "COMBO_Create: no owner for visible combo.\n");
349 /* CreateWindow() will send WM_NCDESTROY to cleanup */
354 /***********************************************************************
357 * Paint combo button (normal, pressed, and disabled states).
359 static void CBPaintButton(LPHEADCOMBO lphc, HDC16 hdc)
366 hPrevBrush = (HBRUSH32)SelectObject32(hdc, sysColorObjects.hbrushBtnFace);
367 CONV_RECT16TO32( &lphc->RectButton, &r );
369 Rectangle32(hdc, r.left, r.top, r.right, r.bottom );
370 InflateRect32( &r, -1, -1 );
371 if( (bBool = lphc->wState & CBF_BUTTONDOWN) )
373 GRAPH_DrawReliefRect(hdc, &r, 1, 0, TRUE);
374 OffsetRect32( &r, 1, 1 );
375 } else GRAPH_DrawReliefRect(hdc, &r, 1, 2, FALSE);
377 x = (r.left + r.right - CBitWidth) >> 1;
378 y = (r.top + r.bottom - CBitHeight) >> 1;
380 InflateRect32( &r, -3, -3 );
381 if( (bBool = CB_DISABLED(lphc)) )
383 GRAPH_SelectClipMask(hdc, hComboBmp, x + 1, y + 1 );
384 FillRect32(hdc, &r, (HBRUSH32)GetStockObject32(WHITE_BRUSH));
387 GRAPH_SelectClipMask(hdc, hComboBmp, x, y );
388 FillRect32(hdc, &r, (HBRUSH32)GetStockObject32((bBool) ? GRAY_BRUSH : BLACK_BRUSH));
390 GRAPH_SelectClipMask(hdc, (HBITMAP32)0, 0, 0);
391 SelectObject32( hdc, hPrevBrush );
394 /***********************************************************************
397 * Paint CBS_DROPDOWNLIST text field / update edit control contents.
399 static void CBPaintText(LPHEADCOMBO lphc, HDC16 hdc)
404 /* follow Windows combobox that sends a bunch of text
405 * inquiries to its listbox while processing WM_PAINT. */
407 if( (id = SendMessage32A(lphc->hWndLBox, LB_GETCURSEL32, 0, 0) ) != LB_ERR )
409 size = SendMessage32A( lphc->hWndLBox, LB_GETTEXTLEN32, id, 0);
410 if( (pText = HeapAlloc( GetProcessHeap(), 0, size + 1)) )
412 SendMessage32A( lphc->hWndLBox, LB_GETTEXT32, (WPARAM32)id, (LPARAM)pText );
413 pText[size] = '\0'; /* just in case */
417 if( lphc->wState & CBF_EDIT )
419 if( CB_HASSTRINGS(lphc) ) SetWindowText32A( lphc->hWndEdit, pText );
420 if( lphc->wState & CBF_FOCUSED )
421 SendMessage32A( lphc->hWndEdit, EM_SETSEL32, 0, (LPARAM)(-1));
423 else /* paint text field ourselves */
425 HBRUSH32 hPrevBrush = 0;
430 if ((hDC = GetDC32(lphc->self->hwndSelf)))
432 HBRUSH32 hBrush = SendMessage32A( lphc->owner,
434 hDC, lphc->self->hwndSelf );
435 hPrevBrush = SelectObject32( hDC,
436 (hBrush) ? hBrush : GetStockObject32(WHITE_BRUSH) );
443 HFONT32 hPrevFont = (lphc->hFont) ? SelectObject32(hDC, lphc->hFont) : 0;
445 PatBlt32( hDC, (rect.left = lphc->RectEdit.left + SYSMETRICS_CXBORDER),
446 (rect.top = lphc->RectEdit.top + SYSMETRICS_CYBORDER),
447 (rect.right = lphc->RectEdit.right - SYSMETRICS_CXBORDER),
448 (rect.bottom = lphc->RectEdit.bottom - SYSMETRICS_CYBORDER) - 1, PATCOPY );
449 InflateRect32( &rect, -1, -1 );
451 if( lphc->wState & CBF_FOCUSED &&
452 !(lphc->wState & CBF_DROPPED) )
456 FillRect32( hDC, &rect, sysColorObjects.hbrushHighlight );
457 SetBkColor32( hDC, GetSysColor32( COLOR_HIGHLIGHT ) );
458 SetTextColor32( hDC, GetSysColor32( COLOR_HIGHLIGHTTEXT ) );
459 itemState = ODS_SELECTED | ODS_FOCUS;
460 } else itemState = 0;
462 if( CB_OWNERDRAWN(lphc) )
464 DRAWITEMSTRUCT32 dis;
466 if( lphc->self->dwStyle & WS_DISABLED ) itemState |= ODS_DISABLED;
468 dis.CtlType = ODT_COMBOBOX;
469 dis.CtlID = lphc->self->wIDmenu;
470 dis.hwndItem = lphc->self->hwndSelf;
471 dis.itemAction = ODA_DRAWENTIRE;
473 dis.itemState = itemState;
476 dis.itemData = SendMessage32A( lphc->hWndLBox, LB_GETITEMDATA32,
478 SendMessage32A( lphc->owner, WM_DRAWITEM,
479 lphc->self->wIDmenu, (LPARAM)&dis );
483 ExtTextOut32A( hDC, rect.left + 1, rect.top + 1,
484 ETO_OPAQUE | ETO_CLIPPED, &rect,
485 (pText) ? pText : "" , size, NULL );
486 if(lphc->wState & CBF_FOCUSED && !(lphc->wState & CBF_DROPPED))
487 DrawFocusRect32( hDC, &rect );
490 if( hPrevFont ) SelectObject32(hDC, hPrevFont );
493 if( hPrevBrush ) SelectObject32( hDC, hPrevBrush );
494 ReleaseDC32( lphc->self->hwndSelf, hDC );
498 HeapFree( GetProcessHeap(), 0, pText );
501 /***********************************************************************
504 static LRESULT COMBO_Paint(LPHEADCOMBO lphc, HDC16 hParamDC)
509 hDC = (hParamDC) ? hParamDC
510 : BeginPaint16( lphc->self->hwndSelf, &ps);
511 if( hDC && !(lphc->self->flags & WIN_NO_REDRAW) )
513 HBRUSH32 hPrevBrush, hBkgBrush;
515 hBkgBrush = SendMessage32A( lphc->owner, WM_CTLCOLORLISTBOX,
516 hDC, lphc->self->hwndSelf );
517 if( !hBkgBrush ) hBkgBrush = GetStockObject32(WHITE_BRUSH);
519 hPrevBrush = SelectObject32( hDC, hBkgBrush );
520 if( !IsRectEmpty16(&lphc->RectButton) )
522 /* paint everything to the right of the text field */
524 PatBlt32( hDC, lphc->RectEdit.right, lphc->RectEdit.top,
525 lphc->RectButton.right - lphc->RectEdit.right,
526 lphc->RectEdit.bottom - lphc->RectEdit.top, PATCOPY );
527 CBPaintButton( lphc, hDC );
530 if( !(lphc->wState & CBF_EDIT) )
532 /* paint text field */
534 GRAPH_DrawRectangle( hDC, lphc->RectEdit.left, lphc->RectEdit.top,
535 lphc->RectEdit.right - lphc->RectEdit.left,
536 lphc->RectButton.bottom - lphc->RectButton.top,
537 sysColorObjects.hpenWindowFrame );
538 CBPaintText( lphc, hDC );
540 if( hPrevBrush ) SelectObject32( hDC, hPrevBrush );
542 if( !hParamDC ) EndPaint16(lphc->self->hwndSelf, &ps);
546 /***********************************************************************
549 * Select listbox entry according to the contents of the edit control.
551 static INT32 CBUpdateLBox( LPHEADCOMBO lphc )
553 INT32 length, idx, ret;
557 length = CB_GETEDITTEXTLENGTH( lphc );
560 pText = (LPSTR) HeapAlloc( GetProcessHeap(), 0, length + 1);
562 dprintf_combo(stddeb,"\tCBUpdateLBox: edit text length %i\n", length );
566 if( length ) GetWindowText32A( lphc->hWndEdit, pText, length + 1);
567 else pText[0] = '\0';
568 idx = SendMessage32A( lphc->hWndLBox, LB_FINDSTRING32,
569 (WPARAM32)(-1), (LPARAM)pText );
570 if( idx == LB_ERR ) idx = 0; /* select first item */
572 HeapFree( GetProcessHeap(), 0, pText );
577 SendMessage32A( lphc->hWndLBox, LB_SETCURSEL32, (WPARAM32)idx, 0 );
581 SendMessage32A( lphc->hWndLBox, LB_SETTOPINDEX32, (WPARAM32)idx, 0 );
582 /* probably superfluous but Windows sends this too */
583 SendMessage32A( lphc->hWndLBox, LB_SETCARETINDEX32, (WPARAM32)idx, 0 );
588 /***********************************************************************
591 * Copy a listbox entry to the edit control.
593 static void CBUpdateEdit( LPHEADCOMBO lphc , INT32 index )
598 dprintf_combo(stddeb,"\tCBUpdateEdit: %i\n", index );
602 length = CB_GETEDITTEXTLENGTH( lphc );
605 if( (pText = (LPSTR) HeapAlloc( GetProcessHeap(), 0, length + 1)) )
607 GetWindowText32A( lphc->hWndEdit, pText, length + 1 );
608 index = SendMessage32A( lphc->hWndLBox, LB_FINDSTRING32,
609 (WPARAM32)(-1), (LPARAM)pText );
610 HeapFree( GetProcessHeap(), 0, pText );
615 if( index >= 0 ) /* got an entry */
617 length = SendMessage32A( lphc->hWndLBox, LB_GETTEXTLEN32, (WPARAM32)index, 0);
620 if( (pText = (LPSTR) HeapAlloc( GetProcessHeap(), 0, length + 1)) )
622 SendMessage32A( lphc->hWndLBox, LB_GETTEXT32,
623 (WPARAM32)index, (LPARAM)pText );
624 SendMessage32A( lphc->hWndEdit, WM_SETTEXT, 0, (LPARAM)pText );
625 SendMessage32A( lphc->hWndEdit, EM_SETSEL32, 0, (LPARAM)(-1) );
626 HeapFree( GetProcessHeap(), 0, pText );
632 /***********************************************************************
635 * Show listbox popup.
637 static void CBDropDown( LPHEADCOMBO lphc )
641 LPRECT16 pRect = NULL;
643 dprintf_combo(stddeb,"Combo [%04x]: drop down\n", CB_HWND(lphc));
645 CB_NOTIFY( lphc, CBN_DROPDOWN );
649 lphc->wState |= CBF_DROPPED;
650 if( CB_GETTYPE(lphc) == CBS_DROPDOWN )
652 index = CBUpdateLBox( lphc );
653 if( !(lphc->wState & CBF_CAPTURE) ) CBUpdateEdit( lphc, index );
657 index = SendMessage32A( lphc->hWndLBox, LB_GETCURSEL32, 0, 0 );
658 if( index == LB_ERR ) index = 0;
659 SendMessage32A( lphc->hWndLBox, LB_SETTOPINDEX32, (WPARAM32)index, 0 );
660 SendMessage32A( lphc->hWndLBox, LB_CARETON32, 0, 0 );
661 pRect = &lphc->RectEdit;
664 /* now set popup position */
666 GetWindowRect16( lphc->self->hwndSelf, &rect );
668 rect.top += lphc->RectEdit.bottom - lphc->RectEdit.top - SYSMETRICS_CYBORDER;
669 rect.bottom = rect.top + lphc->RectCombo.bottom -
670 lphc->RectCombo.top - SYSMETRICS_CYBORDER;
671 rect.right = rect.left + lphc->RectCombo.right - lphc->RectCombo.left;
672 rect.left += ( CB_GETTYPE(lphc) == CBS_DROPDOWNLIST ) ? 0 : CBitOffset;
674 SetWindowPos32( lphc->hWndLBox, HWND_TOP, rect.left, rect.top,
675 rect.right - rect.left, rect.bottom - rect.top,
676 SWP_NOACTIVATE | SWP_NOSIZE );
678 RedrawWindow16( lphc->self->hwndSelf, pRect, 0, RDW_INVALIDATE |
679 RDW_ERASE | RDW_UPDATENOW | RDW_NOCHILDREN );
680 ShowWindow32( lphc->hWndLBox, SW_SHOWNA );
683 /***********************************************************************
686 * Hide listbox popup.
688 static void CBRollUp( LPHEADCOMBO lphc, BOOL32 ok, BOOL32 bButton )
690 HWND32 hWnd = lphc->self->hwndSelf;
692 CB_NOTIFY( lphc, (ok) ? CBN_SELENDOK : CBN_SELENDCANCEL );
694 if( IsWindow32( hWnd ) && CB_GETTYPE(lphc) != CBS_SIMPLE )
697 dprintf_combo(stddeb,"Combo [%04x]: roll up [%i]\n", CB_HWND(lphc), (INT32)ok );
699 /* always send WM_LBUTTONUP? */
700 SendMessage32A( lphc->hWndLBox, WM_LBUTTONUP, 0, (LPARAM)(-1) );
702 if( lphc->wState & CBF_DROPPED )
706 lphc->wState &= ~CBF_DROPPED;
707 ShowWindow32( lphc->hWndLBox, SW_HIDE );
709 if( CB_GETTYPE(lphc) == CBS_DROPDOWN )
711 INT32 index = SendMessage32A( lphc->hWndLBox, LB_GETCURSEL32, 0, 0 );
712 CBUpdateEdit( lphc, index );
713 rect = lphc->RectButton;
718 UnionRect16( &rect, &lphc->RectButton,
721 rect = lphc->RectEdit;
726 RedrawWindow16( hWnd, &rect, 0, RDW_INVALIDATE |
727 RDW_ERASE | RDW_UPDATENOW | RDW_NOCHILDREN );
728 CB_NOTIFY( lphc, CBN_CLOSEUP );
733 /***********************************************************************
736 * Used by the ComboLBox to show/hide itself in response to VK_F4, etc...
738 BOOL32 COMBO_FlipListbox( LPHEADCOMBO lphc, BOOL32 bRedrawButton )
740 if( lphc->wState & CBF_DROPPED )
742 CBRollUp( lphc, TRUE, bRedrawButton );
750 /***********************************************************************
753 * Edit control helper.
755 HWND32 COMBO_GetLBWindow( WND* pWnd )
757 LPHEADCOMBO lphc = CB_GETPTR(pWnd);
758 if( lphc ) return lphc->hWndLBox;
763 /***********************************************************************
766 static void CBRepaintButton( LPHEADCOMBO lphc )
768 HDC32 hDC = GetDC32( lphc->self->hwndSelf );
772 CBPaintButton( lphc, (HDC16)hDC );
773 ReleaseDC32( lphc->self->hwndSelf, hDC );
777 /***********************************************************************
780 static void COMBO_SetFocus( LPHEADCOMBO lphc )
782 if( !(lphc->wState & CBF_FOCUSED) )
784 if( CB_GETTYPE(lphc) == CBS_DROPDOWNLIST )
785 SendMessage32A( lphc->hWndLBox, LB_CARETON32, 0, 0 );
787 if( lphc->wState & CBF_EDIT )
788 SendMessage32A( lphc->hWndEdit, EM_SETSEL32, 0, (LPARAM)(-1) );
789 lphc->wState |= CBF_FOCUSED;
790 if( !(lphc->wState & CBF_EDIT) ) CBPaintText( lphc, 0 );
792 CB_NOTIFY( lphc, CBN_SETFOCUS );
796 /***********************************************************************
799 static void COMBO_KillFocus( LPHEADCOMBO lphc )
801 HWND32 hWnd = lphc->self->hwndSelf;
803 if( lphc->wState & CBF_FOCUSED )
805 SendMessage32A( hWnd, WM_LBUTTONUP, 0, (LPARAM)(-1) );
807 CBRollUp( lphc, FALSE, TRUE );
808 if( IsWindow32( hWnd ) )
810 if( CB_GETTYPE(lphc) == CBS_DROPDOWNLIST )
811 SendMessage32A( lphc->hWndLBox, LB_CARETOFF32, 0, 0 );
813 lphc->wState &= ~CBF_FOCUSED;
816 if( lphc->wState & CBF_EDIT )
817 SendMessage32A( lphc->hWndEdit, EM_SETSEL32, (WPARAM32)(-1), 0 );
818 else CBPaintText( lphc, 0 );
820 CB_NOTIFY( lphc, CBN_KILLFOCUS );
825 /***********************************************************************
828 static LRESULT COMBO_Command( LPHEADCOMBO lphc, WPARAM32 wParam, HWND32 hWnd )
830 if( lphc->wState & CBF_EDIT && lphc->hWndEdit == hWnd )
832 /* ">> 8" makes gcc generate jump-table instead of cmp ladder */
834 switch( HIWORD(wParam) >> 8 )
836 case (EN_SETFOCUS >> 8):
838 dprintf_combo(stddeb,"Combo [%04x]: edit [%04x] got focus\n",
839 CB_HWND(lphc), (HWND16)lphc->hWndEdit );
841 if( !(lphc->wState & CBF_FOCUSED) ) COMBO_SetFocus( lphc );
844 case (EN_KILLFOCUS >> 8):
846 dprintf_combo(stddeb,"Combo [%04x]: edit [%04x] lost focus\n",
847 CB_HWND(lphc), (HWND16)lphc->hWndEdit );
849 /* NOTE: it seems that Windows' edit control sends an
850 * undocumented message WM_USER + 0x1B instead of this
851 * notification (only when it happens to be a part of
852 * the combo). ?? - AK.
855 COMBO_KillFocus( lphc );
859 case (EN_CHANGE >> 8):
860 CB_NOTIFY( lphc, CBN_EDITCHANGE );
861 CBUpdateLBox( lphc );
864 case (EN_UPDATE >> 8):
865 CB_NOTIFY( lphc, CBN_EDITUPDATE );
868 case (EN_ERRSPACE >> 8):
869 CB_NOTIFY( lphc, CBN_ERRSPACE );
872 else if( lphc->hWndLBox == hWnd )
874 switch( HIWORD(wParam) )
877 CB_NOTIFY( lphc, CBN_ERRSPACE );
881 CB_NOTIFY( lphc, CBN_DBLCLK );
887 dprintf_combo(stddeb,"Combo [%04x]: lbox selection change [%04x]\n",
888 CB_HWND(lphc), lphc->wState );
890 /* do not roll up if selection is being tracked
891 * by arrowkeys in the dropdown listbox */
893 if( (lphc->wState & CBF_DROPPED) && !(lphc->wState & CBF_NOROLLUP) )
894 CBRollUp( lphc, (HIWORD(wParam) == LBN_SELCHANGE), TRUE );
895 else lphc->wState &= ~CBF_NOROLLUP;
897 CB_NOTIFY( lphc, CBN_SELCHANGE );
898 CBPaintText( lphc, 0 );
903 /* nothing to do here since ComboLBox always resets the focus to its
904 * combo/edit counterpart */
911 /***********************************************************************
914 * Fixup an ownerdrawn item operation and pass it up to the combobox owner.
916 static LRESULT COMBO_ItemOp32( LPHEADCOMBO lphc, UINT32 msg,
917 WPARAM32 wParam, LPARAM lParam )
919 HWND32 hWnd = lphc->self->hwndSelf;
921 dprintf_combo(stddeb,"Combo [%04x]: ownerdraw op %04x\n",
922 CB_HWND(lphc), (UINT16)msg );
924 #define lpIS ((LPDELETEITEMSTRUCT32)lParam)
926 /* two first items are the same in all 4 structs */
927 lpIS->CtlType = ODT_COMBOBOX;
928 lpIS->CtlID = lphc->self->wIDmenu;
930 switch( msg ) /* patch window handle */
933 lpIS->hwndItem = hWnd;
937 #define lpIS ((LPDRAWITEMSTRUCT32)lParam)
938 lpIS->hwndItem = hWnd;
942 #define lpIS ((LPCOMPAREITEMSTRUCT32)lParam)
943 lpIS->hwndItem = hWnd;
948 return SendMessage32A( lphc->owner, msg, lphc->self->wIDmenu, lParam );
951 /***********************************************************************
954 static LRESULT COMBO_GetText( LPHEADCOMBO lphc, UINT32 N, LPSTR lpText)
958 if( lphc->wState & CBF_EDIT )
959 return SendMessage32A( lphc->hWndEdit, WM_GETTEXT,
960 (WPARAM32)N, (LPARAM)lpText );
962 /* get it from the listbox */
964 idx = SendMessage32A( lphc->hWndLBox, LB_GETCURSEL32, 0, 0 );
968 INT32 length = SendMessage32A( lphc->hWndLBox, LB_GETTEXTLEN32,
971 /* 'length' is without the terminating character */
973 lpBuffer = (LPSTR) HeapAlloc( GetProcessHeap(), 0, length + 1 );
979 INT32 n = SendMessage32A( lphc->hWndLBox, LB_GETTEXT32,
980 (WPARAM32)idx, (LPARAM)lpText );
982 /* truncate if buffer is too short */
986 if( n != LB_ERR ) memcpy( lpText, lpBuffer, (N>n) ? n+1 : N-1 );
987 lpText[N - 1] = '\0';
988 HeapFree( GetProcessHeap(), 0, lpBuffer );
997 /***********************************************************************
1000 * This function sets window positions according to the updated
1001 * component placement struct.
1003 static void CBResetPos( LPHEADCOMBO lphc, LPRECT16 lbRect, BOOL32 bRedraw )
1005 BOOL32 bDrop = (CB_GETTYPE(lphc) != CBS_SIMPLE);
1007 /* NOTE: logs sometimes have WM_LBUTTONUP before a cascade of
1008 * sizing messages */
1010 if( lphc->wState & CBF_EDIT )
1011 SetWindowPos32( lphc->hWndEdit, 0, lphc->RectEdit.left, lphc->RectEdit.top,
1012 lphc->RectEdit.right - lphc->RectEdit.left,
1013 lphc->RectEdit.bottom - lphc->RectEdit.top,
1014 SWP_NOZORDER | SWP_NOACTIVATE | ((bDrop) ? SWP_NOREDRAW : 0) );
1017 OffsetRect16( lbRect, lphc->RectCombo.left, lphc->RectCombo.top );
1019 lbRect->right -= lbRect->left; /* convert to width */
1020 lbRect->bottom -= lbRect->top;
1021 SetWindowPos32( lphc->hWndLBox, 0, lbRect->left, lbRect->top,
1022 lbRect->right, lbRect->bottom,
1023 SWP_NOACTIVATE | SWP_NOZORDER | ((bDrop) ? SWP_NOREDRAW : 0) );
1027 if( lphc->wState & CBF_DROPPED )
1029 lphc->wState &= ~CBF_DROPPED;
1030 ShowWindow32( lphc->hWndLBox, SW_HIDE );
1033 lphc->wState |= CBF_NORESIZE;
1034 SetWindowPos32( lphc->self->hwndSelf, 0, 0, 0,
1035 lphc->RectCombo.right - lphc->RectCombo.left,
1036 lphc->RectEdit.bottom - lphc->RectEdit.top,
1037 SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOREDRAW );
1038 lphc->wState &= ~CBF_NORESIZE;
1040 RedrawWindow32( lphc->self->hwndSelf, NULL, 0,
1041 RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW );
1046 /***********************************************************************
1049 static void COMBO_Size( LPHEADCOMBO lphc )
1054 GetWindowRect16( lphc->self->hwndSelf, &rect );
1055 w = rect.right - rect.left; h = rect.bottom - rect.top;
1057 dprintf_combo(stddeb,"COMBO_Size: w = %i, h = %i\n", w, h );
1059 /* CreateWindow() may send a bogus WM_SIZE, ignore it */
1061 if( w == (lphc->RectCombo.right - lphc->RectCombo.left) )
1062 if( (CB_GETTYPE(lphc) == CBS_SIMPLE) &&
1063 (h == (lphc->RectCombo.bottom - lphc->RectCombo.top)) )
1065 else if( (lphc->dwStyle & CBS_DROPDOWN) &&
1066 (h == (lphc->RectEdit.bottom - lphc->RectEdit.top)) )
1069 lphc->RectCombo = rect;
1070 CBCalcPlacement( lphc, &lphc->RectEdit, &lphc->RectButton, &rect );
1071 CBResetPos( lphc, &rect, TRUE );
1075 /***********************************************************************
1078 static void COMBO_Font( LPHEADCOMBO lphc, HFONT16 hFont, BOOL32 bRedraw )
1082 lphc->hFont = hFont;
1084 if( lphc->wState & CBF_EDIT )
1085 SendMessage32A( lphc->hWndEdit, WM_SETFONT, (WPARAM32)hFont, bRedraw );
1086 SendMessage32A( lphc->hWndLBox, WM_SETFONT, (WPARAM32)hFont, bRedraw );
1088 GetWindowRect16( lphc->self->hwndSelf, &rect );
1089 OffsetRect16( &lphc->RectCombo, rect.left - lphc->RectCombo.left,
1090 rect.top - lphc->RectCombo.top );
1091 CBCalcPlacement( lphc, &lphc->RectEdit,
1092 &lphc->RectButton, &rect );
1093 CBResetPos( lphc, &rect, bRedraw );
1097 /***********************************************************************
1098 * COMBO_SetItemHeight
1100 static LRESULT COMBO_SetItemHeight( LPHEADCOMBO lphc, INT32 index, INT32 height )
1102 LRESULT lRet = CB_ERR;
1104 if( index == -1 ) /* set text field height */
1106 if( height < 32768 )
1110 lphc->editHeight = height;
1111 GetWindowRect16( lphc->self->hwndSelf, &rect );
1112 OffsetRect16( &lphc->RectCombo, rect.left - lphc->RectCombo.left,
1113 rect.top - lphc->RectCombo.top );
1114 CBCalcPlacement( lphc, &lphc->RectEdit,
1115 &lphc->RectButton, &rect );
1116 CBResetPos( lphc, &rect, TRUE );
1120 else if ( CB_OWNERDRAWN(lphc) ) /* set listbox item height */
1121 lRet = SendMessage32A( lphc->hWndLBox, LB_SETITEMHEIGHT32,
1122 (WPARAM32)index, (LPARAM)height );
1126 /***********************************************************************
1127 * COMBO_SelectString
1129 static LRESULT COMBO_SelectString( LPHEADCOMBO lphc, INT32 start, LPCSTR pText )
1131 INT32 index = SendMessage32A( lphc->hWndLBox, CB_SELECTSTRING32,
1132 (WPARAM32)start, (LPARAM)pText );
1134 if( lphc->wState & CBF_EDIT )
1135 CBUpdateEdit( lphc, index );
1137 CBPaintText( lphc, 0 );
1138 return (LRESULT)index;
1141 /***********************************************************************
1144 static void COMBO_LButtonDown( LPHEADCOMBO lphc, LPARAM lParam )
1146 BOOL32 bButton = PtInRect16(&lphc->RectButton, MAKEPOINT16(lParam));
1147 HWND32 hWnd = lphc->self->hwndSelf;
1149 if( (CB_GETTYPE(lphc) == CBS_DROPDOWNLIST) ||
1150 (bButton && (CB_GETTYPE(lphc) == CBS_DROPDOWN)) )
1152 lphc->wState |= CBF_BUTTONDOWN;
1153 if( lphc->wState & CBF_DROPPED )
1155 /* got a click to cancel selection */
1157 CBRollUp( lphc, TRUE, FALSE );
1158 if( !IsWindow32( hWnd ) ) return;
1160 if( lphc->wState & CBF_CAPTURE )
1162 lphc->wState &= ~CBF_CAPTURE;
1165 lphc->wState &= ~CBF_BUTTONDOWN;
1169 /* drop down the listbox and start tracking */
1171 lphc->wState |= CBF_CAPTURE;
1173 SetCapture32( hWnd );
1175 if( bButton ) CBRepaintButton( lphc );
1179 /***********************************************************************
1182 * Release capture and stop tracking if needed.
1184 static void COMBO_LButtonUp( LPHEADCOMBO lphc, LPARAM lParam )
1186 if( lphc->wState & CBF_CAPTURE )
1188 lphc->wState &= ~CBF_CAPTURE;
1189 if( CB_GETTYPE(lphc) == CBS_DROPDOWN )
1191 INT32 index = CBUpdateLBox( lphc );
1192 CBUpdateEdit( lphc, index );
1197 if( lphc->wState & CBF_BUTTONDOWN )
1199 lphc->wState &= ~CBF_BUTTONDOWN;
1200 CBRepaintButton( lphc );
1204 /***********************************************************************
1207 * Two things to do - track combo button and release capture when
1208 * pointer goes into the listbox.
1210 static void COMBO_MouseMove( LPHEADCOMBO lphc, WPARAM32 wParam, LPARAM lParam )
1214 if( lphc->wState & CBF_BUTTONDOWN )
1216 BOOL32 bButton = PtInRect16(&lphc->RectButton, MAKEPOINT16(lParam));
1220 lphc->wState &= ~CBF_BUTTONDOWN;
1221 CBRepaintButton( lphc );
1225 GetClientRect16( lphc->hWndLBox, &lbRect );
1226 MapWindowPoints16( lphc->self->hwndSelf,
1227 lphc->hWndLBox, (LPPOINT16)&lParam, 1 );
1228 if( PtInRect16(&lbRect, MAKEPOINT16(lParam)) )
1230 lphc->wState &= ~CBF_CAPTURE;
1232 if( CB_GETTYPE(lphc) == CBS_DROPDOWN ) CBUpdateLBox( lphc );
1234 /* hand over pointer tracking */
1235 SendMessage32A( lphc->hWndLBox, WM_LBUTTONDOWN, wParam, lParam );
1240 /***********************************************************************
1243 * http://www.microsoft.com/msdn/sdk/platforms/doc/sdk/win32/ctrl/src/combobox_15.htm
1245 LRESULT WINAPI ComboWndProc( HWND32 hwnd, UINT32 message,
1246 WPARAM32 wParam, LPARAM lParam )
1248 WND* pWnd = WIN_FindWndPtr(hwnd);
1252 LPHEADCOMBO lphc = CB_GETPTR(pWnd);
1254 dprintf_combo( stddeb, "Combo [%04x]: msg %s wp %08x lp %08lx\n",
1255 pWnd->hwndSelf, SPY_GetMsgName(message), wParam, lParam );
1257 if( lphc || message == WM_NCCREATE )
1261 /* System messages */
1264 return COMBO_NCCreate(pWnd, lParam);
1267 COMBO_NCDestroy(lphc);
1271 return COMBO_Create(lphc, pWnd, lParam);
1274 /* wParam may contain a valid HDC! */
1275 return COMBO_Paint(lphc, (HDC16)wParam);
1281 return (LRESULT)(DLGC_WANTARROWS | DLGC_WANTCHARS);
1284 if( lphc->hWndLBox &&
1285 !(lphc->wState & CBF_NORESIZE) ) COMBO_Size( lphc );
1289 COMBO_Font( lphc, (HFONT16)wParam, (BOOL32)lParam );
1293 return (LRESULT)lphc->hFont;
1296 if( lphc->wState & CBF_EDIT )
1297 SetFocus32( lphc->hWndEdit );
1299 COMBO_SetFocus( lphc );
1303 #define hwndFocus ((HWND16)wParam)
1305 (hwndFocus != lphc->hWndEdit && hwndFocus != lphc->hWndLBox ))
1306 COMBO_KillFocus( lphc );
1311 return COMBO_Command( lphc, wParam, (HWND32)lParam );
1314 return COMBO_GetText( lphc, (UINT32)wParam, (LPSTR)lParam );
1317 case WM_GETTEXTLENGTH:
1322 if( lphc->wState & CBF_EDIT )
1323 return SendMessage32A( lphc->hWndEdit, message, wParam, lParam );
1328 case WM_COMPAREITEM:
1329 case WM_MEASUREITEM:
1330 return COMBO_ItemOp32( lphc, message, wParam, lParam );
1333 if( lphc->wState & CBF_EDIT )
1334 EnableWindow32( lphc->hWndEdit, (BOOL32)wParam );
1335 EnableWindow32( lphc->hWndLBox, (BOOL32)wParam );
1339 if( lphc->wState & CBF_EDIT )
1340 SendMessage32A( lphc->hWndEdit, message, wParam, lParam );
1341 SendMessage32A( lphc->hWndLBox, message, wParam, lParam );
1345 if( KEYDATA_ALT & HIWORD(lParam) )
1346 if( wParam == VK_UP || wParam == VK_DOWN )
1347 COMBO_FlipListbox( lphc, TRUE );
1352 if( lphc->wState & CBF_EDIT )
1353 return SendMessage32A( lphc->hWndEdit, message, wParam, lParam );
1355 return SendMessage32A( lphc->hWndLBox, message, wParam, lParam );
1357 case WM_LBUTTONDOWN:
1358 if( !(lphc->wState & CBF_FOCUSED) ) SetFocus32( lphc->self->hwndSelf );
1359 if( lphc->wState & CBF_FOCUSED ) COMBO_LButtonDown( lphc, lParam );
1363 COMBO_LButtonUp( lphc, lParam );
1367 if( lphc->wState & CBF_CAPTURE )
1368 COMBO_MouseMove( lphc, wParam, lParam );
1371 /* Combo messages */
1373 case CB_ADDSTRING16:
1374 if( CB_HASSTRINGS(lphc) ) lParam = (LPARAM)PTR_SEG_TO_LIN(lParam);
1375 case CB_ADDSTRING32:
1376 return SendMessage32A( lphc->hWndLBox, LB_ADDSTRING32, 0, lParam);
1378 case CB_INSERTSTRING16:
1379 wParam = (INT32)(INT16)wParam;
1380 if( CB_HASSTRINGS(lphc) ) lParam = (LPARAM)PTR_SEG_TO_LIN(lParam);
1381 case CB_INSERTSTRING32:
1382 return SendMessage32A( lphc->hWndLBox, LB_INSERTSTRING32, wParam, lParam);
1384 case CB_DELETESTRING16:
1385 case CB_DELETESTRING32:
1386 return SendMessage32A( lphc->hWndLBox, LB_DELETESTRING32, wParam, 0);
1388 case CB_SELECTSTRING16:
1389 wParam = (INT32)(INT16)wParam;
1390 if( CB_HASSTRINGS(lphc) ) lParam = (LPARAM)PTR_SEG_TO_LIN(lParam);
1391 case CB_SELECTSTRING32:
1392 return COMBO_SelectString( lphc, (INT32)wParam, (LPSTR)lParam );
1394 case CB_FINDSTRING16:
1395 wParam = (INT32)(INT16)wParam;
1396 if( CB_HASSTRINGS(lphc) ) lParam = (LPARAM)PTR_SEG_TO_LIN(lParam);
1397 case CB_FINDSTRING32:
1398 return SendMessage32A( lphc->hWndLBox, LB_FINDSTRING32, wParam, lParam);
1400 case CB_FINDSTRINGEXACT16:
1401 wParam = (INT32)(INT16)wParam;
1402 if( CB_HASSTRINGS(lphc) ) lParam = (LPARAM)PTR_SEG_TO_LIN(lParam);
1403 case CB_FINDSTRINGEXACT32:
1404 return SendMessage32A( lphc->hWndLBox, LB_FINDSTRINGEXACT32,
1406 case CB_SETITEMHEIGHT16:
1407 wParam = (INT32)(INT16)wParam;
1408 case CB_SETITEMHEIGHT32:
1409 return COMBO_SetItemHeight( lphc, (INT32)wParam, (INT32)lParam);
1411 case CB_RESETCONTENT16:
1412 case CB_RESETCONTENT32:
1413 SendMessage32A( lphc->hWndLBox, LB_RESETCONTENT32, 0, 0 );
1414 CBPaintText( lphc, 0 );
1417 case CB_INITSTORAGE32:
1418 return SendMessage32A( lphc->hWndLBox, LB_INITSTORAGE32, wParam, lParam);
1420 case CB_GETHORIZONTALEXTENT32:
1421 return SendMessage32A( lphc->hWndLBox, LB_GETHORIZONTALEXTENT32, 0, 0);
1423 case CB_SETHORIZONTALEXTENT32:
1424 return SendMessage32A( lphc->hWndLBox, LB_SETHORIZONTALEXTENT32, wParam, 0);
1426 case CB_GETTOPINDEX32:
1427 return SendMessage32A( lphc->hWndLBox, LB_GETTOPINDEX32, 0, 0);
1429 case CB_GETLOCALE32:
1430 return SendMessage32A( lphc->hWndLBox, LB_GETLOCALE32, 0, 0);
1432 case CB_SETLOCALE32:
1433 return SendMessage32A( lphc->hWndLBox, LB_SETLOCALE32, wParam, 0);
1435 case CB_GETDROPPEDWIDTH32:
1436 if( lphc->droppedWidth )
1437 return lphc->droppedWidth;
1438 return lphc->RectCombo.right - lphc->RectCombo.left -
1439 (lphc->wState & CBF_EDIT) ? CBitOffset : 0;
1441 case CB_SETDROPPEDWIDTH32:
1442 if( (CB_GETTYPE(lphc) != CBS_SIMPLE) &&
1443 (INT32)wParam < 32768 ) lphc->droppedWidth = (INT32)wParam;
1446 case CB_GETDROPPEDCONTROLRECT16:
1447 lParam = (LPARAM)PTR_SEG_TO_LIN(lParam);
1451 CBGetDroppedControlRect32( lphc, &r );
1452 CONV_RECT32TO16( &r, (LPRECT16)lParam );
1456 case CB_GETDROPPEDCONTROLRECT32:
1457 if( lParam ) CBGetDroppedControlRect32(lphc, (LPRECT32)lParam );
1460 case CB_GETDROPPEDSTATE16:
1461 case CB_GETDROPPEDSTATE32:
1462 return (lphc->wState & CBF_DROPPED) ? TRUE : FALSE;
1465 lParam = (LPARAM)PTR_SEG_TO_LIN(lParam);
1468 return COMBO_Directory( lphc, (UINT32)wParam,
1469 (LPSTR)lParam, (message == CB_DIR32));
1470 case CB_SHOWDROPDOWN16:
1471 case CB_SHOWDROPDOWN32:
1472 if( CB_GETTYPE(lphc) != CBS_SIMPLE )
1475 if( !(lphc->wState & CBF_DROPPED) )
1479 if( lphc->wState & CBF_DROPPED )
1480 CBRollUp( lphc, FALSE, TRUE );
1485 return SendMessage32A( lphc->hWndLBox, LB_GETCOUNT32, 0, 0);
1487 case CB_GETCURSEL16:
1488 case CB_GETCURSEL32:
1489 return SendMessage32A( lphc->hWndLBox, LB_GETCURSEL32, 0, 0);
1491 case CB_SETCURSEL16:
1492 wParam = (INT32)(INT16)wParam;
1493 case CB_SETCURSEL32:
1494 return SendMessage32A( lphc->hWndLBox, LB_SETCURSEL32, wParam, 0);
1496 case CB_GETLBTEXT16:
1497 wParam = (INT32)(INT16)wParam;
1498 lParam = (LPARAM)PTR_SEG_TO_LIN(lParam);
1499 case CB_GETLBTEXT32:
1500 return SendMessage32A( lphc->hWndLBox, LB_GETTEXT32, wParam, lParam);
1502 case CB_GETLBTEXTLEN16:
1503 wParam = (INT32)(INT16)wParam;
1504 case CB_GETLBTEXTLEN32:
1505 return SendMessage32A( lphc->hWndLBox, LB_GETTEXTLEN32, wParam, 0);
1507 case CB_GETITEMDATA16:
1508 wParam = (INT32)(INT16)wParam;
1509 case CB_GETITEMDATA32:
1510 return SendMessage32A( lphc->hWndLBox, LB_GETITEMDATA32, wParam, 0);
1512 case CB_SETITEMDATA16:
1513 wParam = (INT32)(INT16)wParam;
1514 case CB_SETITEMDATA32:
1515 return SendMessage32A( lphc->hWndLBox, LB_SETITEMDATA32, wParam, lParam);
1517 case CB_GETEDITSEL16:
1518 wParam = lParam = 0; /* just in case */
1519 case CB_GETEDITSEL32:
1520 if( lphc->wState & CBF_EDIT )
1524 return SendMessage32A( lphc->hWndEdit, EM_GETSEL32,
1525 (wParam) ? wParam : (WPARAM32)&a,
1526 (lParam) ? lParam : (LPARAM)&b );
1530 case CB_SETEDITSEL16:
1531 case CB_SETEDITSEL32:
1532 if( lphc->wState & CBF_EDIT )
1533 return SendMessage32A( lphc->hWndEdit, EM_SETSEL32,
1534 (INT32)(INT16)LOWORD(lParam), (INT32)(INT16)HIWORD(lParam) );
1537 case CB_SETEXTENDEDUI16:
1538 case CB_SETEXTENDEDUI32:
1539 if( CB_GETTYPE(lphc) == CBS_SIMPLE ) return CB_ERR;
1542 lphc->wState |= CBF_EUI;
1543 else lphc->wState &= ~CBF_EUI;
1546 case CB_GETEXTENDEDUI16:
1547 case CB_GETEXTENDEDUI32:
1548 return (lphc->wState & CBF_EUI) ? TRUE : FALSE;
1550 case (WM_USER + 0x1B):
1551 dprintf_combo(stddeb,"Combo [%04x]: undocumented msg!\n", (HWND16)hwnd );
1553 return DefWindowProc32A(hwnd, message, wParam, lParam);