4 * Copyright 1997 Alex Korobka
6 * FIXME: roll up in Netscape 3.01.
12 #include "sysmetrics.h"
21 /* bits in the dwKeyData */
22 #define KEYDATA_ALT 0x2000
23 #define KEYDATA_PREVSTATE 0x4000
26 * Additional combo box definitions
29 #define CB_GETPTR( wnd ) (*(LPHEADCOMBO*)((wnd)->wExtra))
30 #define CB_NOTIFY( lphc, code ) \
31 (SendMessage32A( (lphc)->owner, WM_COMMAND, \
32 MAKEWPARAM((lphc)->self->wIDmenu, (code)), (lphc)->self->hwndSelf))
33 #define CB_GETEDITTEXTLENGTH( lphc ) \
34 (SendMessage32A( (lphc)->hWndEdit, WM_GETTEXTLENGTH, 0, 0 ))
36 static HBITMAP32 hComboBmp
= 0;
37 static UINT32 CBitHeight
, CBitWidth
;
38 static UINT32 CBitOffset
= 8;
40 /***********************************************************************
43 * Load combo button bitmap.
45 static BOOL32
COMBO_Init()
49 if( hComboBmp
) return TRUE
;
50 if( (hDC
= CreateCompatibleDC32(0)) )
53 if( (hComboBmp
= LoadBitmap32A(0, MAKEINTRESOURCE32A(OBM_COMBO
))) )
59 GetObject32A( hComboBmp
, sizeof(bm
), &bm
);
60 CBitHeight
= bm
.bmHeight
;
61 CBitWidth
= bm
.bmWidth
;
63 TRACE(combo
, "combo bitmap [%i,%i]\n", CBitWidth
, CBitHeight
);
65 hPrevB
= SelectObject16( hDC
, hComboBmp
);
66 SetRect32( &r
, 0, 0, CBitWidth
, CBitHeight
);
67 InvertRect32( hDC
, &r
);
68 SelectObject32( hDC
, hPrevB
);
77 /***********************************************************************
80 static LRESULT
COMBO_NCCreate(WND
* wnd
, LPARAM lParam
)
84 if ( wnd
&& COMBO_Init() &&
85 (lphc
= HeapAlloc(GetProcessHeap(), 0, sizeof(HEADCOMBO
))) )
87 LPCREATESTRUCT32A lpcs
= (CREATESTRUCT32A
*)lParam
;
89 memset( lphc
, 0, sizeof(HEADCOMBO
) );
90 *(LPHEADCOMBO
*)wnd
->wExtra
= lphc
;
92 /* some braindead apps do try to use scrollbar/border flags */
94 lphc
->dwStyle
= (lpcs
->style
& ~(WS_BORDER
| WS_HSCROLL
| WS_VSCROLL
));
95 wnd
->dwStyle
&= ~(WS_BORDER
| WS_HSCROLL
| WS_VSCROLL
);
97 if( !(lpcs
->style
& (CBS_OWNERDRAWFIXED
| CBS_OWNERDRAWVARIABLE
)) )
98 lphc
->dwStyle
|= CBS_HASSTRINGS
;
99 if( !(wnd
->dwExStyle
& WS_EX_NOPARENTNOTIFY
) )
100 lphc
->wState
|= CBF_NOTIFY
;
102 TRACE(combo
, "[0x%08x], style = %08x\n",
103 (UINT32
)lphc
, lphc
->dwStyle
);
105 return (LRESULT
)(UINT32
)wnd
->hwndSelf
;
107 return (LRESULT
)FALSE
;
110 /***********************************************************************
113 static LRESULT
COMBO_NCDestroy( LPHEADCOMBO lphc
)
118 WND
* wnd
= lphc
->self
;
120 TRACE(combo
,"[%04x]: freeing storage\n", CB_HWND(lphc
));
122 if( (CB_GETTYPE(lphc
) != CBS_SIMPLE
) && lphc
->hWndLBox
)
123 DestroyWindow32( lphc
->hWndLBox
);
125 HeapFree( GetProcessHeap(), 0, lphc
);
131 /***********************************************************************
132 * CBGetDefaultTextHeight
134 static void CBGetDefaultTextHeight( LPHEADCOMBO lphc
, LPSIZE32 lpSize
)
136 if( lphc
->editHeight
) /* explicitly set height */
137 lpSize
->cy
= lphc
->editHeight
;
140 HDC32 hDC
= GetDC32( lphc
->self
->hwndSelf
);
141 HFONT32 hPrevFont
= 0;
143 if( lphc
->hFont
) hPrevFont
= SelectObject32( hDC
, lphc
->hFont
);
145 GetTextExtentPoint32A( hDC
, "0", 1, lpSize
);
147 lpSize
->cy
+= lpSize
->cy
/ 4 + 4 * SYSMETRICS_CYBORDER
;
149 if( hPrevFont
) SelectObject32( hDC
, hPrevFont
);
150 ReleaseDC32( lphc
->self
->hwndSelf
, hDC
);
152 lpSize
->cx
= lphc
->RectCombo
.right
- lphc
->RectCombo
.left
;
156 /***********************************************************************
159 * Set up component coordinates given valid lphc->RectCombo.
161 static void CBCalcPlacement( LPHEADCOMBO lphc
, LPRECT32 lprEdit
,
162 LPRECT32 lprButton
, LPRECT32 lprLB
)
164 RECT32 rect
= lphc
->RectCombo
;
167 /* get combo height and width */
169 if( CB_OWNERDRAWN(lphc
) )
171 UINT32 u
= lphc
->RectEdit
.bottom
- lphc
->RectEdit
.top
;
173 if( lphc
->wState
& CBF_MEASUREITEM
) /* first initialization */
175 MEASUREITEMSTRUCT32 mi32
;
177 /* calculate defaults before sending WM_MEASUREITEM */
179 CBGetDefaultTextHeight( lphc
, &size
);
181 lphc
->wState
&= ~CBF_MEASUREITEM
;
183 mi32
.CtlType
= ODT_COMBOBOX
;
184 mi32
.CtlID
= lphc
->self
->wIDmenu
;
186 mi32
.itemWidth
= size
.cx
;
187 mi32
.itemHeight
= size
.cy
- 6; /* ownerdrawn cb is taller */
189 SendMessage32A(lphc
->owner
, WM_MEASUREITEM
,
190 (WPARAM32
)mi32
.CtlID
, (LPARAM
)&mi32
);
191 u
= 6 + (UINT16
)mi32
.itemHeight
;
194 size
.cx
= rect
.right
- rect
.left
;
198 CBGetDefaultTextHeight( lphc
, &size
);
200 /* calculate text and button placement */
202 lprEdit
->left
= lprEdit
->top
= lprButton
->top
= 0;
203 if( CB_GETTYPE(lphc
) == CBS_SIMPLE
) /* no button */
204 lprButton
->left
= lprButton
->right
= lprButton
->bottom
= 0;
207 INT32 i
= size
.cx
- CBitWidth
- 10; /* seems ok */
209 lprButton
->right
= size
.cx
;
210 lprButton
->left
= (INT16
)i
;
211 lprButton
->bottom
= lprButton
->top
+ size
.cy
;
213 if( i
< 0 ) size
.cx
= 0;
217 if( CB_GETTYPE(lphc
) == CBS_DROPDOWN
)
219 size
.cx
-= CBitOffset
;
220 if( size
.cx
< 0 ) size
.cx
= 0;
223 lprEdit
->right
= size
.cx
; lprEdit
->bottom
= size
.cy
;
225 /* listbox placement */
227 lprLB
->left
= ( CB_GETTYPE(lphc
) == CBS_DROPDOWNLIST
) ? 0 : CBitOffset
;
228 lprLB
->top
= lprEdit
->bottom
- SYSMETRICS_CYBORDER
;
229 lprLB
->right
= rect
.right
- rect
.left
;
230 lprLB
->bottom
= rect
.bottom
- rect
.top
;
232 if( lphc
->droppedWidth
> (lprLB
->right
- lprLB
->left
) )
233 lprLB
->right
= lprLB
->left
+ lphc
->droppedWidth
;
235 TRACE(combo
,"[%04x]: (%i,%i-%i,%i) placement\n",
236 CB_HWND(lphc
), lphc
->RectCombo
.left
, lphc
->RectCombo
.top
,
237 lphc
->RectCombo
.right
, lphc
->RectCombo
.bottom
);
239 TRACE(combo
,"\ttext\t= (%i,%i-%i,%i)\n",
240 lprEdit
->left
, lprEdit
->top
, lprEdit
->right
, lprEdit
->bottom
);
242 TRACE(combo
,"\tbutton\t= (%i,%i-%i,%i)\n",
243 lprButton
->left
, lprButton
->top
, lprButton
->right
, lprButton
->bottom
);
245 TRACE(combo
,"\tlbox\t= (%i,%i-%i,%i)\n",
246 lprLB
->left
, lprLB
->top
, lprLB
->right
, lprLB
->bottom
);
249 /***********************************************************************
250 * CBGetDroppedControlRect32
252 static void CBGetDroppedControlRect32( LPHEADCOMBO lphc
, LPRECT32 lpRect
)
254 lpRect
->left
= lphc
->RectCombo
.left
+
255 (lphc
->wState
& CBF_EDIT
) ? CBitOffset
: 0;
256 lpRect
->top
= lphc
->RectCombo
.top
+ lphc
->RectEdit
.bottom
-
258 lpRect
->right
= lphc
->RectCombo
.right
;
259 lpRect
->bottom
= lphc
->RectCombo
.bottom
- SYSMETRICS_CYBORDER
;
262 /***********************************************************************
265 static LRESULT
COMBO_Create( LPHEADCOMBO lphc
, WND
* wnd
, LPARAM lParam
)
267 static char clbName
[] = "ComboLBox";
268 static char editName
[] = "Edit";
270 LPCREATESTRUCT32A lpcs
= (CREATESTRUCT32A
*)lParam
;
272 if( !CB_GETTYPE(lphc
) ) lphc
->dwStyle
|= CBS_SIMPLE
;
273 else if( CB_GETTYPE(lphc
) != CBS_DROPDOWNLIST
) lphc
->wState
|= CBF_EDIT
;
276 lphc
->owner
= lpcs
->hwndParent
;
278 /* M$ IE 3.01 actually creates (and rapidly destroys) an ownerless combobox */
280 if( lphc
->owner
|| !(lpcs
->style
& WS_VISIBLE
) )
283 RECT32 editRect
, btnRect
, lbRect
;
285 GetWindowRect32( wnd
->hwndSelf
, &lphc
->RectCombo
);
287 lphc
->wState
|= CBF_MEASUREITEM
;
288 CBCalcPlacement( lphc
, &editRect
, &btnRect
, &lbRect
);
289 lphc
->RectButton
= btnRect
;
290 lphc
->droppedWidth
= lphc
->editHeight
= 0;
292 /* create listbox popup */
294 lbeStyle
= (LBS_NOTIFY
| WS_BORDER
| WS_CLIPSIBLINGS
) |
295 (lpcs
->style
& (WS_VSCROLL
| CBS_OWNERDRAWFIXED
| CBS_OWNERDRAWVARIABLE
));
297 if( lphc
->dwStyle
& CBS_SORT
)
298 lbeStyle
|= LBS_SORT
;
299 if( lphc
->dwStyle
& CBS_HASSTRINGS
)
300 lbeStyle
|= LBS_HASSTRINGS
;
301 if( lphc
->dwStyle
& CBS_NOINTEGRALHEIGHT
)
302 lbeStyle
|= LBS_NOINTEGRALHEIGHT
;
303 if( lphc
->dwStyle
& CBS_DISABLENOSCROLL
)
304 lbeStyle
|= LBS_DISABLENOSCROLL
;
306 if( CB_GETTYPE(lphc
) == CBS_SIMPLE
) /* child listbox */
307 lbeStyle
|= WS_CHILD
| WS_VISIBLE
;
308 else /* popup listbox */
310 lbeStyle
|= WS_POPUP
;
311 OffsetRect32( &lbRect
, lphc
->RectCombo
.left
, lphc
->RectCombo
.top
);
314 /* Dropdown ComboLBox is not a child window and we cannot pass
315 * ID_CB_LISTBOX directly because it will be treated as a menu handle.
318 lphc
->hWndLBox
= CreateWindowEx32A( 0, clbName
, NULL
, lbeStyle
,
319 lbRect
.left
+ SYSMETRICS_CXBORDER
,
320 lbRect
.top
+ SYSMETRICS_CYBORDER
,
321 lbRect
.right
- lbRect
.left
- 2 * SYSMETRICS_CXBORDER
,
322 lbRect
.bottom
- lbRect
.top
- 2 * SYSMETRICS_CYBORDER
,
323 lphc
->self
->hwndSelf
,
324 (lphc
->dwStyle
& CBS_DROPDOWN
)? (HMENU32
)0 : (HMENU32
)ID_CB_LISTBOX
,
325 lphc
->self
->hInstance
, (LPVOID
)lphc
);
329 lbeStyle
= WS_CHILD
| WS_VISIBLE
| WS_BORDER
| ES_NOHIDESEL
| ES_LEFT
;
330 if( lphc
->wState
& CBF_EDIT
)
332 if( lphc
->dwStyle
& CBS_OEMCONVERT
)
333 lbeStyle
|= ES_OEMCONVERT
;
334 if( lphc
->dwStyle
& CBS_AUTOHSCROLL
)
335 lbeStyle
|= ES_AUTOHSCROLL
;
336 if( lphc
->dwStyle
& CBS_LOWERCASE
)
337 lbeStyle
|= ES_LOWERCASE
;
338 else if( lphc
->dwStyle
& CBS_UPPERCASE
)
339 lbeStyle
|= ES_UPPERCASE
;
340 lphc
->hWndEdit
= CreateWindowEx32A( 0, editName
, NULL
, lbeStyle
,
341 editRect
.left
, editRect
.top
, editRect
.right
- editRect
.left
,
342 editRect
.bottom
- editRect
.top
, lphc
->self
->hwndSelf
,
343 (HMENU32
)ID_CB_EDIT
, lphc
->self
->hInstance
, NULL
);
344 if( !lphc
->hWndEdit
) bEdit
= FALSE
;
349 lphc
->RectEdit
= editRect
;
350 if( CB_GETTYPE(lphc
) != CBS_SIMPLE
)
352 lphc
->wState
|= CBF_NORESIZE
;
353 SetWindowPos32( wnd
->hwndSelf
, 0, 0, 0,
354 lphc
->RectCombo
.right
- lphc
->RectCombo
.left
,
355 lphc
->RectEdit
.bottom
- lphc
->RectEdit
.top
,
356 SWP_NOMOVE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
357 lphc
->wState
&= ~CBF_NORESIZE
;
359 TRACE(combo
,"init done\n");
360 return wnd
->hwndSelf
;
362 ERR(combo
, "edit control failure.\n");
363 } else ERR(combo
, "listbox failure.\n");
364 } else ERR(combo
, "no owner for visible combo.\n");
366 /* CreateWindow() will send WM_NCDESTROY to cleanup */
371 /***********************************************************************
374 * Paint combo button (normal, pressed, and disabled states).
376 static void CBPaintButton(LPHEADCOMBO lphc
, HDC32 hdc
)
383 COLORREF oldTextColor
, oldBkColor
;
385 if( lphc
->wState
& CBF_NOREDRAW
) return;
387 hPrevBrush
= SelectObject32(hdc
, GetSysColorBrush32(COLOR_BTNFACE
));
388 CONV_RECT16TO32( &lphc
->RectButton
, &r
);
390 Rectangle32(hdc
, r
.left
, r
.top
, r
.right
, r
.bottom
);
391 if( (bBool
= lphc
->wState
& CBF_BUTTONDOWN
) )
393 DrawEdge32( hdc
, &r
, EDGE_SUNKEN
, BF_RECT
);
394 OffsetRect32( &r
, 1, 1 );
397 DrawEdge32( hdc
, &r
, EDGE_RAISED
, BF_RECT
);
401 InflateRect32( &r
, -1, -1 );
403 x
= (r
.left
+ r
.right
- CBitWidth
) >> 1;
404 y
= (r
.top
+ r
.bottom
- CBitHeight
) >> 1;
406 InflateRect32( &r
, -3, -3 );
408 hMemDC
= CreateCompatibleDC32( hdc
);
409 SelectObject32( hMemDC
, hComboBmp
);
410 oldTextColor
= SetTextColor32( hdc
, GetSysColor32(COLOR_BTNFACE
) );
411 oldBkColor
= SetBkColor32( hdc
, CB_DISABLED(lphc
) ? RGB(128,128,128) :
413 BitBlt32( hdc
, x
, y
, 8, 8, hMemDC
, 0, 0, SRCCOPY
);
414 SetBkColor32( hdc
, oldBkColor
);
415 SetTextColor32( hdc
, oldTextColor
);
416 DeleteDC32( hMemDC
);
417 SelectObject32( hdc
, hPrevBrush
);
420 /***********************************************************************
423 * Paint CBS_DROPDOWNLIST text field / update edit control contents.
425 static void CBPaintText(LPHEADCOMBO lphc
, HDC32 hdc
)
430 if( lphc
->wState
& CBF_NOREDRAW
) return;
432 /* follow Windows combobox that sends a bunch of text
433 * inquiries to its listbox while processing WM_PAINT. */
435 if( (id
= SendMessage32A(lphc
->hWndLBox
, LB_GETCURSEL32
, 0, 0) ) != LB_ERR
)
437 size
= SendMessage32A( lphc
->hWndLBox
, LB_GETTEXTLEN32
, id
, 0);
438 if( (pText
= HeapAlloc( GetProcessHeap(), 0, size
+ 1)) )
440 SendMessage32A( lphc
->hWndLBox
, LB_GETTEXT32
, (WPARAM32
)id
, (LPARAM
)pText
);
441 pText
[size
] = '\0'; /* just in case */
445 if( lphc
->wState
& CBF_EDIT
)
447 if( CB_HASSTRINGS(lphc
) ) SetWindowText32A( lphc
->hWndEdit
, pText
? pText
: "" );
448 if( lphc
->wState
& CBF_FOCUSED
)
449 SendMessage32A( lphc
->hWndEdit
, EM_SETSEL32
, 0, (LPARAM
)(-1));
451 else /* paint text field ourselves */
453 HBRUSH32 hPrevBrush
= 0;
458 if ((hDC
= GetDC32(lphc
->self
->hwndSelf
)))
460 HBRUSH32 hBrush
= SendMessage32A( lphc
->owner
,
462 hDC
, lphc
->self
->hwndSelf
);
463 hPrevBrush
= SelectObject32( hDC
,
464 (hBrush
) ? hBrush
: GetStockObject32(WHITE_BRUSH
) );
471 HFONT32 hPrevFont
= (lphc
->hFont
) ? SelectObject32(hDC
, lphc
->hFont
) : 0;
473 PatBlt32( hDC
, (rect
.left
= lphc
->RectEdit
.left
+ SYSMETRICS_CXBORDER
),
474 (rect
.top
= lphc
->RectEdit
.top
+ SYSMETRICS_CYBORDER
),
475 (rect
.right
= lphc
->RectEdit
.right
- SYSMETRICS_CXBORDER
),
476 (rect
.bottom
= lphc
->RectEdit
.bottom
- SYSMETRICS_CYBORDER
) - 1, PATCOPY
);
477 InflateRect32( &rect
, -1, -1 );
479 if( lphc
->wState
& CBF_FOCUSED
&&
480 !(lphc
->wState
& CBF_DROPPED
) )
484 FillRect32( hDC
, &rect
, GetSysColorBrush32(COLOR_HIGHLIGHT
) );
485 SetBkColor32( hDC
, GetSysColor32( COLOR_HIGHLIGHT
) );
486 SetTextColor32( hDC
, GetSysColor32( COLOR_HIGHLIGHTTEXT
) );
487 itemState
= ODS_SELECTED
| ODS_FOCUS
;
488 } else itemState
= 0;
490 if( CB_OWNERDRAWN(lphc
) )
492 DRAWITEMSTRUCT32 dis
;
494 if( lphc
->self
->dwStyle
& WS_DISABLED
) itemState
|= ODS_DISABLED
;
496 dis
.CtlType
= ODT_COMBOBOX
;
497 dis
.CtlID
= lphc
->self
->wIDmenu
;
498 dis
.hwndItem
= lphc
->self
->hwndSelf
;
499 dis
.itemAction
= ODA_DRAWENTIRE
;
501 dis
.itemState
= itemState
;
504 dis
.itemData
= SendMessage32A( lphc
->hWndLBox
, LB_GETITEMDATA32
,
506 SendMessage32A( lphc
->owner
, WM_DRAWITEM
,
507 lphc
->self
->wIDmenu
, (LPARAM
)&dis
);
511 ExtTextOut32A( hDC
, rect
.left
+ 1, rect
.top
+ 1,
512 ETO_OPAQUE
| ETO_CLIPPED
, &rect
,
513 pText
? pText
: "" , size
, NULL
);
514 if(lphc
->wState
& CBF_FOCUSED
&& !(lphc
->wState
& CBF_DROPPED
))
515 DrawFocusRect32( hDC
, &rect
);
518 if( hPrevFont
) SelectObject32(hDC
, hPrevFont
);
521 if( hPrevBrush
) SelectObject32( hDC
, hPrevBrush
);
522 ReleaseDC32( lphc
->self
->hwndSelf
, hDC
);
527 HeapFree( GetProcessHeap(), 0, pText
);
530 /***********************************************************************
533 static LRESULT
COMBO_Paint(LPHEADCOMBO lphc
, HDC32 hParamDC
)
538 hDC
= (hParamDC
) ? hParamDC
539 : BeginPaint32( lphc
->self
->hwndSelf
, &ps
);
540 if( hDC
&& !(lphc
->wState
& CBF_NOREDRAW
) )
542 HBRUSH32 hPrevBrush
, hBkgBrush
;
544 hBkgBrush
= SendMessage32A( lphc
->owner
, WM_CTLCOLORLISTBOX
,
545 hDC
, lphc
->self
->hwndSelf
);
546 if( !hBkgBrush
) hBkgBrush
= GetStockObject32(WHITE_BRUSH
);
548 hPrevBrush
= SelectObject32( hDC
, hBkgBrush
);
549 if( !IsRectEmpty32(&lphc
->RectButton
) )
551 /* paint everything to the right of the text field */
553 PatBlt32( hDC
, lphc
->RectEdit
.right
, lphc
->RectEdit
.top
,
554 lphc
->RectButton
.right
- lphc
->RectEdit
.right
,
555 lphc
->RectEdit
.bottom
- lphc
->RectEdit
.top
, PATCOPY
);
556 CBPaintButton( lphc
, hDC
);
559 if( !(lphc
->wState
& CBF_EDIT
) )
561 /* paint text field */
563 HPEN32 hPrevPen
= SelectObject32( hDC
, GetSysColorPen32(
564 COLOR_WINDOWFRAME
) );
566 Rectangle32( hDC
, lphc
->RectEdit
.left
, lphc
->RectEdit
.top
,
567 lphc
->RectEdit
.right
, lphc
->RectButton
.bottom
);
568 SelectObject32( hDC
, hPrevPen
);
569 CBPaintText( lphc
, hDC
);
571 if( hPrevBrush
) SelectObject32( hDC
, hPrevBrush
);
573 if( !hParamDC
) EndPaint32(lphc
->self
->hwndSelf
, &ps
);
577 /***********************************************************************
580 * Select listbox entry according to the contents of the edit control.
582 static INT32
CBUpdateLBox( LPHEADCOMBO lphc
)
584 INT32 length
, idx
, ret
;
588 length
= CB_GETEDITTEXTLENGTH( lphc
);
591 pText
= (LPSTR
) HeapAlloc( GetProcessHeap(), 0, length
+ 1);
593 TRACE(combo
,"\t edit text length %i\n", length
);
597 if( length
) GetWindowText32A( lphc
->hWndEdit
, pText
, length
+ 1);
598 else pText
[0] = '\0';
599 idx
= SendMessage32A( lphc
->hWndLBox
, LB_FINDSTRING32
,
600 (WPARAM32
)(-1), (LPARAM
)pText
);
601 if( idx
== LB_ERR
) idx
= 0; /* select first item */
603 HeapFree( GetProcessHeap(), 0, pText
);
608 SendMessage32A( lphc
->hWndLBox
, LB_SETCURSEL32
, (WPARAM32
)idx
, 0 );
612 SendMessage32A( lphc
->hWndLBox
, LB_SETTOPINDEX32
, (WPARAM32
)idx
, 0 );
613 /* probably superfluous but Windows sends this too */
614 SendMessage32A( lphc
->hWndLBox
, LB_SETCARETINDEX32
, (WPARAM32
)idx
, 0 );
619 /***********************************************************************
622 * Copy a listbox entry to the edit control.
624 static void CBUpdateEdit( LPHEADCOMBO lphc
, INT32 index
)
629 TRACE(combo
,"\t %i\n", index
);
633 length
= CB_GETEDITTEXTLENGTH( lphc
);
636 if( (pText
= (LPSTR
) HeapAlloc( GetProcessHeap(), 0, length
+ 1)) )
638 GetWindowText32A( lphc
->hWndEdit
, pText
, length
+ 1 );
639 index
= SendMessage32A( lphc
->hWndLBox
, LB_FINDSTRING32
,
640 (WPARAM32
)(-1), (LPARAM
)pText
);
641 HeapFree( GetProcessHeap(), 0, pText
);
646 if( index
>= 0 ) /* got an entry */
648 length
= SendMessage32A( lphc
->hWndLBox
, LB_GETTEXTLEN32
, (WPARAM32
)index
, 0);
651 if( (pText
= (LPSTR
) HeapAlloc( GetProcessHeap(), 0, length
+ 1)) )
653 SendMessage32A( lphc
->hWndLBox
, LB_GETTEXT32
,
654 (WPARAM32
)index
, (LPARAM
)pText
);
655 SendMessage32A( lphc
->hWndEdit
, WM_SETTEXT
, 0, (LPARAM
)pText
);
656 SendMessage32A( lphc
->hWndEdit
, EM_SETSEL32
, 0, (LPARAM
)(-1) );
657 HeapFree( GetProcessHeap(), 0, pText
);
663 /***********************************************************************
666 * Show listbox popup.
668 static void CBDropDown( LPHEADCOMBO lphc
)
672 LPRECT32 pRect
= NULL
;
674 TRACE(combo
,"[%04x]: drop down\n", CB_HWND(lphc
));
676 CB_NOTIFY( lphc
, CBN_DROPDOWN
);
680 lphc
->wState
|= CBF_DROPPED
;
681 if( CB_GETTYPE(lphc
) == CBS_DROPDOWN
)
683 index
= CBUpdateLBox( lphc
);
684 if( !(lphc
->wState
& CBF_CAPTURE
) ) CBUpdateEdit( lphc
, index
);
688 index
= SendMessage32A( lphc
->hWndLBox
, LB_GETCURSEL32
, 0, 0 );
689 if( index
== LB_ERR
) index
= 0;
690 SendMessage32A( lphc
->hWndLBox
, LB_SETTOPINDEX32
, (WPARAM32
)index
, 0 );
691 SendMessage32A( lphc
->hWndLBox
, LB_CARETON32
, 0, 0 );
692 pRect
= &lphc
->RectEdit
;
695 /* now set popup position */
697 GetWindowRect32( lphc
->self
->hwndSelf
, &rect
);
699 rect
.top
+= lphc
->RectEdit
.bottom
- lphc
->RectEdit
.top
- SYSMETRICS_CYBORDER
;
700 rect
.bottom
= rect
.top
+ lphc
->RectCombo
.bottom
-
701 lphc
->RectCombo
.top
- SYSMETRICS_CYBORDER
;
702 rect
.right
= rect
.left
+ lphc
->RectCombo
.right
- lphc
->RectCombo
.left
;
703 rect
.left
+= ( CB_GETTYPE(lphc
) == CBS_DROPDOWNLIST
) ? 0 : CBitOffset
;
705 SetWindowPos32( lphc
->hWndLBox
, HWND_TOP
, rect
.left
, rect
.top
,
706 rect
.right
- rect
.left
, rect
.bottom
- rect
.top
,
707 SWP_NOACTIVATE
| SWP_NOSIZE
| SWP_NOREDRAW
);
709 if( !(lphc
->wState
& CBF_NOREDRAW
) )
711 RedrawWindow32( lphc
->self
->hwndSelf
, pRect
, 0, RDW_INVALIDATE
|
712 RDW_ERASE
| RDW_UPDATENOW
| RDW_NOCHILDREN
);
713 ShowWindow32( lphc
->hWndLBox
, SW_SHOWNA
);
716 /***********************************************************************
719 * Hide listbox popup.
721 static void CBRollUp( LPHEADCOMBO lphc
, BOOL32 ok
, BOOL32 bButton
)
723 HWND32 hWnd
= lphc
->self
->hwndSelf
;
725 CB_NOTIFY( lphc
, (ok
) ? CBN_SELENDOK
: CBN_SELENDCANCEL
);
727 if( IsWindow32( hWnd
) && CB_GETTYPE(lphc
) != CBS_SIMPLE
)
730 TRACE(combo
,"[%04x]: roll up [%i]\n", CB_HWND(lphc
), (INT32
)ok
);
732 /* always send WM_LBUTTONUP? */
733 SendMessage32A( lphc
->hWndLBox
, WM_LBUTTONUP
, 0, (LPARAM
)(-1) );
735 if( lphc
->wState
& CBF_DROPPED
)
739 lphc
->wState
&= ~CBF_DROPPED
;
740 ShowWindow32( lphc
->hWndLBox
, SW_HIDE
);
742 if( CB_GETTYPE(lphc
) == CBS_DROPDOWN
)
744 INT32 index
= SendMessage32A( lphc
->hWndLBox
, LB_GETCURSEL32
, 0, 0 );
745 CBUpdateEdit( lphc
, index
);
746 rect
= lphc
->RectButton
;
751 UnionRect32( &rect
, &lphc
->RectButton
,
754 rect
= lphc
->RectEdit
;
758 if( bButton
&& !(lphc
->wState
& CBF_NOREDRAW
) )
759 RedrawWindow32( hWnd
, &rect
, 0, RDW_INVALIDATE
|
760 RDW_ERASE
| RDW_UPDATENOW
| RDW_NOCHILDREN
);
761 CB_NOTIFY( lphc
, CBN_CLOSEUP
);
766 /***********************************************************************
769 * Used by the ComboLBox to show/hide itself in response to VK_F4, etc...
771 BOOL32
COMBO_FlipListbox( LPHEADCOMBO lphc
, BOOL32 bRedrawButton
)
773 if( lphc
->wState
& CBF_DROPPED
)
775 CBRollUp( lphc
, TRUE
, bRedrawButton
);
783 /***********************************************************************
786 * Edit control helper.
788 HWND32
COMBO_GetLBWindow( WND
* pWnd
)
790 LPHEADCOMBO lphc
= CB_GETPTR(pWnd
);
791 if( lphc
) return lphc
->hWndLBox
;
796 /***********************************************************************
799 static void CBRepaintButton( LPHEADCOMBO lphc
)
801 HDC32 hDC
= GetDC32( lphc
->self
->hwndSelf
);
805 CBPaintButton( lphc
, hDC
);
806 ReleaseDC32( lphc
->self
->hwndSelf
, hDC
);
810 /***********************************************************************
813 static void COMBO_SetFocus( LPHEADCOMBO lphc
)
815 if( !(lphc
->wState
& CBF_FOCUSED
) )
817 if( CB_GETTYPE(lphc
) == CBS_DROPDOWNLIST
)
818 SendMessage32A( lphc
->hWndLBox
, LB_CARETON32
, 0, 0 );
820 if( lphc
->wState
& CBF_EDIT
)
821 SendMessage32A( lphc
->hWndEdit
, EM_SETSEL32
, 0, (LPARAM
)(-1) );
822 lphc
->wState
|= CBF_FOCUSED
;
823 if( !(lphc
->wState
& CBF_EDIT
) ) CBPaintText( lphc
, 0 );
825 CB_NOTIFY( lphc
, CBN_SETFOCUS
);
829 /***********************************************************************
832 static void COMBO_KillFocus( LPHEADCOMBO lphc
)
834 HWND32 hWnd
= lphc
->self
->hwndSelf
;
836 if( lphc
->wState
& CBF_FOCUSED
)
838 SendMessage32A( hWnd
, WM_LBUTTONUP
, 0, (LPARAM
)(-1) );
840 CBRollUp( lphc
, FALSE
, TRUE
);
841 if( IsWindow32( hWnd
) )
843 if( CB_GETTYPE(lphc
) == CBS_DROPDOWNLIST
)
844 SendMessage32A( lphc
->hWndLBox
, LB_CARETOFF32
, 0, 0 );
846 lphc
->wState
&= ~CBF_FOCUSED
;
849 if( lphc
->wState
& CBF_EDIT
)
850 SendMessage32A( lphc
->hWndEdit
, EM_SETSEL32
, (WPARAM32
)(-1), 0 );
851 else CBPaintText( lphc
, 0 );
853 CB_NOTIFY( lphc
, CBN_KILLFOCUS
);
858 /***********************************************************************
861 static LRESULT
COMBO_Command( LPHEADCOMBO lphc
, WPARAM32 wParam
, HWND32 hWnd
)
863 if( lphc
->wState
& CBF_EDIT
&& lphc
->hWndEdit
== hWnd
)
865 /* ">> 8" makes gcc generate jump-table instead of cmp ladder */
867 switch( HIWORD(wParam
) >> 8 )
869 case (EN_SETFOCUS
>> 8):
871 TRACE(combo
,"[%04x]: edit [%04x] got focus\n",
872 CB_HWND(lphc
), lphc
->hWndEdit
);
874 if( !(lphc
->wState
& CBF_FOCUSED
) ) COMBO_SetFocus( lphc
);
877 case (EN_KILLFOCUS
>> 8):
879 TRACE(combo
,"[%04x]: edit [%04x] lost focus\n",
880 CB_HWND(lphc
), lphc
->hWndEdit
);
882 /* NOTE: it seems that Windows' edit control sends an
883 * undocumented message WM_USER + 0x1B instead of this
884 * notification (only when it happens to be a part of
885 * the combo). ?? - AK.
888 COMBO_KillFocus( lphc
);
892 case (EN_CHANGE
>> 8):
893 CB_NOTIFY( lphc
, CBN_EDITCHANGE
);
894 CBUpdateLBox( lphc
);
897 case (EN_UPDATE
>> 8):
898 CB_NOTIFY( lphc
, CBN_EDITUPDATE
);
901 case (EN_ERRSPACE
>> 8):
902 CB_NOTIFY( lphc
, CBN_ERRSPACE
);
905 else if( lphc
->hWndLBox
== hWnd
)
907 switch( HIWORD(wParam
) )
910 CB_NOTIFY( lphc
, CBN_ERRSPACE
);
914 CB_NOTIFY( lphc
, CBN_DBLCLK
);
920 TRACE(combo
,"[%04x]: lbox selection change [%04x]\n",
921 CB_HWND(lphc
), lphc
->wState
);
923 /* do not roll up if selection is being tracked
924 * by arrowkeys in the dropdown listbox */
926 if( (lphc
->wState
& CBF_DROPPED
) && !(lphc
->wState
& CBF_NOROLLUP
) )
927 CBRollUp( lphc
, (HIWORD(wParam
) == LBN_SELCHANGE
), TRUE
);
928 else lphc
->wState
&= ~CBF_NOROLLUP
;
930 CB_NOTIFY( lphc
, CBN_SELCHANGE
);
931 CBPaintText( lphc
, 0 );
936 /* nothing to do here since ComboLBox always resets the focus to its
937 * combo/edit counterpart */
944 /***********************************************************************
947 * Fixup an ownerdrawn item operation and pass it up to the combobox owner.
949 static LRESULT
COMBO_ItemOp32( LPHEADCOMBO lphc
, UINT32 msg
,
950 WPARAM32 wParam
, LPARAM lParam
)
952 HWND32 hWnd
= lphc
->self
->hwndSelf
;
954 TRACE(combo
,"[%04x]: ownerdraw op %04x\n", CB_HWND(lphc
), msg
);
956 #define lpIS ((LPDELETEITEMSTRUCT32)lParam)
958 /* two first items are the same in all 4 structs */
959 lpIS
->CtlType
= ODT_COMBOBOX
;
960 lpIS
->CtlID
= lphc
->self
->wIDmenu
;
962 switch( msg
) /* patch window handle */
965 lpIS
->hwndItem
= hWnd
;
969 #define lpIS ((LPDRAWITEMSTRUCT32)lParam)
970 lpIS
->hwndItem
= hWnd
;
974 #define lpIS ((LPCOMPAREITEMSTRUCT32)lParam)
975 lpIS
->hwndItem
= hWnd
;
980 return SendMessage32A( lphc
->owner
, msg
, lphc
->self
->wIDmenu
, lParam
);
983 /***********************************************************************
986 static LRESULT
COMBO_GetText( LPHEADCOMBO lphc
, UINT32 N
, LPSTR lpText
)
988 if( lphc
->wState
& CBF_EDIT
)
989 return SendMessage32A( lphc
->hWndEdit
, WM_GETTEXT
,
990 (WPARAM32
)N
, (LPARAM
)lpText
);
992 /* get it from the listbox */
996 INT32 idx
= SendMessage32A( lphc
->hWndLBox
, LB_GETCURSEL32
, 0, 0 );
1000 INT32 length
= SendMessage32A( lphc
->hWndLBox
, LB_GETTEXTLEN32
,
1003 /* 'length' is without the terminating character */
1005 lpBuffer
= (LPSTR
) HeapAlloc( GetProcessHeap(), 0, length
+ 1 );
1011 INT32 n
= SendMessage32A( lphc
->hWndLBox
, LB_GETTEXT32
,
1012 (WPARAM32
)idx
, (LPARAM
)lpBuffer
);
1014 /* truncate if buffer is too short */
1019 if( n
!= LB_ERR
) memcpy( lpText
, lpBuffer
, (N
>n
) ? n
+1 : N
-1 );
1020 lpText
[N
- 1] = '\0';
1022 HeapFree( GetProcessHeap(), 0, lpBuffer
);
1032 /***********************************************************************
1035 * This function sets window positions according to the updated
1036 * component placement struct.
1038 static void CBResetPos( LPHEADCOMBO lphc
, LPRECT32 lbRect
, BOOL32 bRedraw
)
1040 BOOL32 bDrop
= (CB_GETTYPE(lphc
) != CBS_SIMPLE
);
1042 /* NOTE: logs sometimes have WM_LBUTTONUP before a cascade of
1043 * sizing messages */
1045 if( lphc
->wState
& CBF_EDIT
)
1046 SetWindowPos32( lphc
->hWndEdit
, 0, lphc
->RectEdit
.left
, lphc
->RectEdit
.top
,
1047 lphc
->RectEdit
.right
- lphc
->RectEdit
.left
,
1048 lphc
->RectEdit
.bottom
- lphc
->RectEdit
.top
,
1049 SWP_NOZORDER
| SWP_NOACTIVATE
| ((bDrop
) ? SWP_NOREDRAW
: 0) );
1052 OffsetRect32( lbRect
, lphc
->RectCombo
.left
, lphc
->RectCombo
.top
);
1054 lbRect
->right
-= lbRect
->left
; /* convert to width */
1055 lbRect
->bottom
-= lbRect
->top
;
1056 SetWindowPos32( lphc
->hWndLBox
, 0, lbRect
->left
, lbRect
->top
,
1057 lbRect
->right
, lbRect
->bottom
,
1058 SWP_NOACTIVATE
| SWP_NOZORDER
| ((bDrop
) ? SWP_NOREDRAW
: 0) );
1062 if( lphc
->wState
& CBF_DROPPED
)
1064 lphc
->wState
&= ~CBF_DROPPED
;
1065 ShowWindow32( lphc
->hWndLBox
, SW_HIDE
);
1068 lphc
->wState
|= CBF_NORESIZE
;
1069 SetWindowPos32( lphc
->self
->hwndSelf
, 0, 0, 0,
1070 lphc
->RectCombo
.right
- lphc
->RectCombo
.left
,
1071 lphc
->RectEdit
.bottom
- lphc
->RectEdit
.top
,
1072 SWP_NOMOVE
| SWP_NOZORDER
| SWP_NOACTIVATE
| SWP_NOREDRAW
);
1073 lphc
->wState
&= ~CBF_NORESIZE
;
1075 if( bRedraw
&& !(lphc
->wState
& CBF_NOREDRAW
) )
1076 RedrawWindow32( lphc
->self
->hwndSelf
, NULL
, 0,
1077 RDW_INVALIDATE
| RDW_ERASE
| RDW_UPDATENOW
);
1082 /***********************************************************************
1085 static void COMBO_Size( LPHEADCOMBO lphc
)
1090 GetWindowRect32( lphc
->self
->hwndSelf
, &rect
);
1091 w
= rect
.right
- rect
.left
; h
= rect
.bottom
- rect
.top
;
1093 TRACE(combo
,"w = %i, h = %i\n", w
, h
);
1095 /* CreateWindow() may send a bogus WM_SIZE, ignore it */
1097 if( w
== (lphc
->RectCombo
.right
- lphc
->RectCombo
.left
) )
1099 if( (CB_GETTYPE(lphc
) == CBS_SIMPLE
) &&
1100 (h
== (lphc
->RectCombo
.bottom
- lphc
->RectCombo
.top
)) )
1102 else if( (lphc
->dwStyle
& CBS_DROPDOWN
) &&
1103 (h
== (lphc
->RectEdit
.bottom
- lphc
->RectEdit
.top
)) )
1106 lphc
->RectCombo
= rect
;
1107 CBCalcPlacement( lphc
, &lphc
->RectEdit
, &lphc
->RectButton
, &rect
);
1108 CBResetPos( lphc
, &rect
, TRUE
);
1112 /***********************************************************************
1115 static void COMBO_Font( LPHEADCOMBO lphc
, HFONT32 hFont
, BOOL32 bRedraw
)
1119 lphc
->hFont
= hFont
;
1121 if( lphc
->wState
& CBF_EDIT
)
1122 SendMessage32A( lphc
->hWndEdit
, WM_SETFONT
, (WPARAM32
)hFont
, bRedraw
);
1123 SendMessage32A( lphc
->hWndLBox
, WM_SETFONT
, (WPARAM32
)hFont
, bRedraw
);
1125 GetWindowRect32( lphc
->self
->hwndSelf
, &rect
);
1126 OffsetRect32( &lphc
->RectCombo
, rect
.left
- lphc
->RectCombo
.left
,
1127 rect
.top
- lphc
->RectCombo
.top
);
1128 CBCalcPlacement( lphc
, &lphc
->RectEdit
,
1129 &lphc
->RectButton
, &rect
);
1130 CBResetPos( lphc
, &rect
, bRedraw
);
1134 /***********************************************************************
1135 * COMBO_SetItemHeight
1137 static LRESULT
COMBO_SetItemHeight( LPHEADCOMBO lphc
, INT32 index
, INT32 height
)
1139 LRESULT lRet
= CB_ERR
;
1141 if( index
== -1 ) /* set text field height */
1143 if( height
< 32768 )
1147 lphc
->editHeight
= height
;
1148 GetWindowRect32( lphc
->self
->hwndSelf
, &rect
);
1149 OffsetRect32( &lphc
->RectCombo
, rect
.left
- lphc
->RectCombo
.left
,
1150 rect
.top
- lphc
->RectCombo
.top
);
1151 CBCalcPlacement( lphc
, &lphc
->RectEdit
,
1152 &lphc
->RectButton
, &rect
);
1153 CBResetPos( lphc
, &rect
, TRUE
);
1157 else if ( CB_OWNERDRAWN(lphc
) ) /* set listbox item height */
1158 lRet
= SendMessage32A( lphc
->hWndLBox
, LB_SETITEMHEIGHT32
,
1159 (WPARAM32
)index
, (LPARAM
)height
);
1163 /***********************************************************************
1164 * COMBO_SelectString
1166 static LRESULT
COMBO_SelectString( LPHEADCOMBO lphc
, INT32 start
, LPCSTR pText
)
1168 INT32 index
= SendMessage32A( lphc
->hWndLBox
, LB_SELECTSTRING32
,
1169 (WPARAM32
)start
, (LPARAM
)pText
);
1172 if( lphc
->wState
& CBF_EDIT
)
1173 CBUpdateEdit( lphc
, index
);
1175 CBPaintText( lphc
, 0 );
1177 return (LRESULT
)index
;
1180 /***********************************************************************
1183 static void COMBO_LButtonDown( LPHEADCOMBO lphc
, LPARAM lParam
)
1185 POINT32 pt
= { LOWORD(lParam
), HIWORD(lParam
) };
1186 BOOL32 bButton
= PtInRect32(&lphc
->RectButton
, pt
);
1187 HWND32 hWnd
= lphc
->self
->hwndSelf
;
1189 if( (CB_GETTYPE(lphc
) == CBS_DROPDOWNLIST
) ||
1190 (bButton
&& (CB_GETTYPE(lphc
) == CBS_DROPDOWN
)) )
1192 lphc
->wState
|= CBF_BUTTONDOWN
;
1193 if( lphc
->wState
& CBF_DROPPED
)
1195 /* got a click to cancel selection */
1197 CBRollUp( lphc
, TRUE
, FALSE
);
1198 if( !IsWindow32( hWnd
) ) return;
1200 if( lphc
->wState
& CBF_CAPTURE
)
1202 lphc
->wState
&= ~CBF_CAPTURE
;
1205 lphc
->wState
&= ~CBF_BUTTONDOWN
;
1209 /* drop down the listbox and start tracking */
1211 lphc
->wState
|= CBF_CAPTURE
;
1213 SetCapture32( hWnd
);
1215 if( bButton
) CBRepaintButton( lphc
);
1219 /***********************************************************************
1222 * Release capture and stop tracking if needed.
1224 static void COMBO_LButtonUp( LPHEADCOMBO lphc
, LPARAM lParam
)
1226 if( lphc
->wState
& CBF_CAPTURE
)
1228 lphc
->wState
&= ~CBF_CAPTURE
;
1229 if( CB_GETTYPE(lphc
) == CBS_DROPDOWN
)
1231 INT32 index
= CBUpdateLBox( lphc
);
1232 CBUpdateEdit( lphc
, index
);
1237 if( lphc
->wState
& CBF_BUTTONDOWN
)
1239 lphc
->wState
&= ~CBF_BUTTONDOWN
;
1240 CBRepaintButton( lphc
);
1244 /***********************************************************************
1247 * Two things to do - track combo button and release capture when
1248 * pointer goes into the listbox.
1250 static void COMBO_MouseMove( LPHEADCOMBO lphc
, WPARAM32 wParam
, LPARAM lParam
)
1252 POINT32 pt
= { LOWORD(lParam
), HIWORD(lParam
) };
1255 if( lphc
->wState
& CBF_BUTTONDOWN
)
1257 BOOL32 bButton
= PtInRect32(&lphc
->RectButton
, pt
);
1261 lphc
->wState
&= ~CBF_BUTTONDOWN
;
1262 CBRepaintButton( lphc
);
1266 GetClientRect32( lphc
->hWndLBox
, &lbRect
);
1267 MapWindowPoints32( lphc
->self
->hwndSelf
, lphc
->hWndLBox
, &pt
, 1 );
1268 if( PtInRect32(&lbRect
, pt
) )
1270 lphc
->wState
&= ~CBF_CAPTURE
;
1272 if( CB_GETTYPE(lphc
) == CBS_DROPDOWN
) CBUpdateLBox( lphc
);
1274 /* hand over pointer tracking */
1275 SendMessage32A( lphc
->hWndLBox
, WM_LBUTTONDOWN
, wParam
, lParam
);
1280 /***********************************************************************
1283 * http://www.microsoft.com/msdn/sdk/platforms/doc/sdk/win32/ctrl/src/combobox_15.htm
1285 LRESULT WINAPI
ComboWndProc( HWND32 hwnd
, UINT32 message
,
1286 WPARAM32 wParam
, LPARAM lParam
)
1288 WND
* pWnd
= WIN_FindWndPtr(hwnd
);
1292 LPHEADCOMBO lphc
= CB_GETPTR(pWnd
);
1294 TRACE(combo
, "[%04x]: msg %s wp %08x lp %08lx\n",
1295 pWnd
->hwndSelf
, SPY_GetMsgName(message
), wParam
, lParam
);
1297 if( lphc
|| message
== WM_NCCREATE
)
1301 /* System messages */
1304 return COMBO_NCCreate(pWnd
, lParam
);
1307 COMBO_NCDestroy(lphc
);
1311 return COMBO_Create(lphc
, pWnd
, lParam
);
1314 /* wParam may contain a valid HDC! */
1315 return COMBO_Paint(lphc
, wParam
);
1321 return (LRESULT
)(DLGC_WANTARROWS
| DLGC_WANTCHARS
);
1324 if( lphc
->hWndLBox
&&
1325 !(lphc
->wState
& CBF_NORESIZE
) ) COMBO_Size( lphc
);
1329 COMBO_Font( lphc
, (HFONT16
)wParam
, (BOOL32
)lParam
);
1333 return (LRESULT
)lphc
->hFont
;
1336 if( lphc
->wState
& CBF_EDIT
)
1337 SetFocus32( lphc
->hWndEdit
);
1339 COMBO_SetFocus( lphc
);
1343 #define hwndFocus ((HWND16)wParam)
1345 (hwndFocus
!= lphc
->hWndEdit
&& hwndFocus
!= lphc
->hWndLBox
))
1346 COMBO_KillFocus( lphc
);
1351 return COMBO_Command( lphc
, wParam
, (HWND32
)lParam
);
1354 return COMBO_GetText( lphc
, (UINT32
)wParam
, (LPSTR
)lParam
);
1357 case WM_GETTEXTLENGTH
:
1362 if( lphc
->wState
& CBF_EDIT
)
1363 return SendMessage32A( lphc
->hWndEdit
, message
, wParam
, lParam
);
1368 case WM_COMPAREITEM
:
1369 case WM_MEASUREITEM
:
1370 return COMBO_ItemOp32( lphc
, message
, wParam
, lParam
);
1373 if( lphc
->wState
& CBF_EDIT
)
1374 EnableWindow32( lphc
->hWndEdit
, (BOOL32
)wParam
);
1375 EnableWindow32( lphc
->hWndLBox
, (BOOL32
)wParam
);
1380 lphc
->wState
&= ~CBF_NOREDRAW
;
1382 lphc
->wState
|= CBF_NOREDRAW
;
1384 if( lphc
->wState
& CBF_EDIT
)
1385 SendMessage32A( lphc
->hWndEdit
, message
, wParam
, lParam
);
1386 SendMessage32A( lphc
->hWndLBox
, message
, wParam
, lParam
);
1390 if( KEYDATA_ALT
& HIWORD(lParam
) )
1391 if( wParam
== VK_UP
|| wParam
== VK_DOWN
)
1392 COMBO_FlipListbox( lphc
, TRUE
);
1397 if( lphc
->wState
& CBF_EDIT
)
1398 return SendMessage32A( lphc
->hWndEdit
, message
, wParam
, lParam
);
1400 return SendMessage32A( lphc
->hWndLBox
, message
, wParam
, lParam
);
1402 case WM_LBUTTONDOWN
:
1403 if( !(lphc
->wState
& CBF_FOCUSED
) ) SetFocus32( lphc
->self
->hwndSelf
);
1404 if( lphc
->wState
& CBF_FOCUSED
) COMBO_LButtonDown( lphc
, lParam
);
1408 COMBO_LButtonUp( lphc
, lParam
);
1412 if( lphc
->wState
& CBF_CAPTURE
)
1413 COMBO_MouseMove( lphc
, wParam
, lParam
);
1416 /* Combo messages */
1418 case CB_ADDSTRING16
:
1419 if( CB_HASSTRINGS(lphc
) ) lParam
= (LPARAM
)PTR_SEG_TO_LIN(lParam
);
1420 case CB_ADDSTRING32
:
1421 return SendMessage32A( lphc
->hWndLBox
, LB_ADDSTRING32
, 0, lParam
);
1423 case CB_INSERTSTRING16
:
1424 wParam
= (INT32
)(INT16
)wParam
;
1425 if( CB_HASSTRINGS(lphc
) ) lParam
= (LPARAM
)PTR_SEG_TO_LIN(lParam
);
1426 case CB_INSERTSTRING32
:
1427 return SendMessage32A( lphc
->hWndLBox
, LB_INSERTSTRING32
, wParam
, lParam
);
1429 case CB_DELETESTRING16
:
1430 case CB_DELETESTRING32
:
1431 return SendMessage32A( lphc
->hWndLBox
, LB_DELETESTRING32
, wParam
, 0);
1433 case CB_SELECTSTRING16
:
1434 wParam
= (INT32
)(INT16
)wParam
;
1435 if( CB_HASSTRINGS(lphc
) ) lParam
= (LPARAM
)PTR_SEG_TO_LIN(lParam
);
1436 case CB_SELECTSTRING32
:
1437 return COMBO_SelectString( lphc
, (INT32
)wParam
, (LPSTR
)lParam
);
1439 case CB_FINDSTRING16
:
1440 wParam
= (INT32
)(INT16
)wParam
;
1441 if( CB_HASSTRINGS(lphc
) ) lParam
= (LPARAM
)PTR_SEG_TO_LIN(lParam
);
1442 case CB_FINDSTRING32
:
1443 return SendMessage32A( lphc
->hWndLBox
, LB_FINDSTRING32
, wParam
, lParam
);
1445 case CB_FINDSTRINGEXACT16
:
1446 wParam
= (INT32
)(INT16
)wParam
;
1447 if( CB_HASSTRINGS(lphc
) ) lParam
= (LPARAM
)PTR_SEG_TO_LIN(lParam
);
1448 case CB_FINDSTRINGEXACT32
:
1449 return SendMessage32A( lphc
->hWndLBox
, LB_FINDSTRINGEXACT32
,
1451 case CB_SETITEMHEIGHT16
:
1452 wParam
= (INT32
)(INT16
)wParam
; /* signed integer */
1453 case CB_SETITEMHEIGHT32
:
1454 return COMBO_SetItemHeight( lphc
, (INT32
)wParam
, (INT32
)lParam
);
1456 case CB_GETITEMHEIGHT16
:
1457 wParam
= (INT32
)(INT16
)wParam
;
1458 case CB_GETITEMHEIGHT32
:
1459 if( (INT32
)wParam
>= 0 ) /* listbox item */
1460 return SendMessage32A( lphc
->hWndLBox
, LB_GETITEMHEIGHT32
, wParam
, 0);
1461 return (lphc
->RectEdit
.bottom
- lphc
->RectEdit
.top
);
1463 case CB_RESETCONTENT16
:
1464 case CB_RESETCONTENT32
:
1465 SendMessage32A( lphc
->hWndLBox
, LB_RESETCONTENT32
, 0, 0 );
1466 CBPaintText( lphc
, 0 );
1469 case CB_INITSTORAGE32
:
1470 return SendMessage32A( lphc
->hWndLBox
, LB_INITSTORAGE32
, wParam
, lParam
);
1472 case CB_GETHORIZONTALEXTENT32
:
1473 return SendMessage32A( lphc
->hWndLBox
, LB_GETHORIZONTALEXTENT32
, 0, 0);
1475 case CB_SETHORIZONTALEXTENT32
:
1476 return SendMessage32A( lphc
->hWndLBox
, LB_SETHORIZONTALEXTENT32
, wParam
, 0);
1478 case CB_GETTOPINDEX32
:
1479 return SendMessage32A( lphc
->hWndLBox
, LB_GETTOPINDEX32
, 0, 0);
1481 case CB_GETLOCALE32
:
1482 return SendMessage32A( lphc
->hWndLBox
, LB_GETLOCALE32
, 0, 0);
1484 case CB_SETLOCALE32
:
1485 return SendMessage32A( lphc
->hWndLBox
, LB_SETLOCALE32
, wParam
, 0);
1487 case CB_GETDROPPEDWIDTH32
:
1488 if( lphc
->droppedWidth
)
1489 return lphc
->droppedWidth
;
1490 return lphc
->RectCombo
.right
- lphc
->RectCombo
.left
-
1491 (lphc
->wState
& CBF_EDIT
) ? CBitOffset
: 0;
1493 case CB_SETDROPPEDWIDTH32
:
1494 if( (CB_GETTYPE(lphc
) != CBS_SIMPLE
) &&
1495 (INT32
)wParam
< 32768 ) lphc
->droppedWidth
= (INT32
)wParam
;
1498 case CB_GETDROPPEDCONTROLRECT16
:
1499 lParam
= (LPARAM
)PTR_SEG_TO_LIN(lParam
);
1503 CBGetDroppedControlRect32( lphc
, &r
);
1504 CONV_RECT32TO16( &r
, (LPRECT16
)lParam
);
1508 case CB_GETDROPPEDCONTROLRECT32
:
1509 if( lParam
) CBGetDroppedControlRect32(lphc
, (LPRECT32
)lParam
);
1512 case CB_GETDROPPEDSTATE16
:
1513 case CB_GETDROPPEDSTATE32
:
1514 return (lphc
->wState
& CBF_DROPPED
) ? TRUE
: FALSE
;
1517 lParam
= (LPARAM
)PTR_SEG_TO_LIN(lParam
);
1520 return COMBO_Directory( lphc
, (UINT32
)wParam
,
1521 (LPSTR
)lParam
, (message
== CB_DIR32
));
1522 case CB_SHOWDROPDOWN16
:
1523 case CB_SHOWDROPDOWN32
:
1524 if( CB_GETTYPE(lphc
) != CBS_SIMPLE
)
1528 if( !(lphc
->wState
& CBF_DROPPED
) )
1532 if( lphc
->wState
& CBF_DROPPED
)
1533 CBRollUp( lphc
, FALSE
, TRUE
);
1539 return SendMessage32A( lphc
->hWndLBox
, LB_GETCOUNT32
, 0, 0);
1541 case CB_GETCURSEL16
:
1542 case CB_GETCURSEL32
:
1543 return SendMessage32A( lphc
->hWndLBox
, LB_GETCURSEL32
, 0, 0);
1545 case CB_SETCURSEL16
:
1546 wParam
= (INT32
)(INT16
)wParam
;
1547 case CB_SETCURSEL32
:
1548 return SendMessage32A( lphc
->hWndLBox
, LB_SETCURSEL32
, wParam
, 0);
1550 case CB_GETLBTEXT16
:
1551 wParam
= (INT32
)(INT16
)wParam
;
1552 lParam
= (LPARAM
)PTR_SEG_TO_LIN(lParam
);
1553 case CB_GETLBTEXT32
:
1554 return SendMessage32A( lphc
->hWndLBox
, LB_GETTEXT32
, wParam
, lParam
);
1556 case CB_GETLBTEXTLEN16
:
1557 wParam
= (INT32
)(INT16
)wParam
;
1558 case CB_GETLBTEXTLEN32
:
1559 return SendMessage32A( lphc
->hWndLBox
, LB_GETTEXTLEN32
, wParam
, 0);
1561 case CB_GETITEMDATA16
:
1562 wParam
= (INT32
)(INT16
)wParam
;
1563 case CB_GETITEMDATA32
:
1564 return SendMessage32A( lphc
->hWndLBox
, LB_GETITEMDATA32
, wParam
, 0);
1566 case CB_SETITEMDATA16
:
1567 wParam
= (INT32
)(INT16
)wParam
;
1568 case CB_SETITEMDATA32
:
1569 return SendMessage32A( lphc
->hWndLBox
, LB_SETITEMDATA32
, wParam
, lParam
);
1571 case CB_GETEDITSEL16
:
1572 wParam
= lParam
= 0; /* just in case */
1573 case CB_GETEDITSEL32
:
1574 if( lphc
->wState
& CBF_EDIT
)
1578 return SendMessage32A( lphc
->hWndEdit
, EM_GETSEL32
,
1579 (wParam
) ? wParam
: (WPARAM32
)&a
,
1580 (lParam
) ? lParam
: (LPARAM
)&b
);
1584 case CB_SETEDITSEL16
:
1585 case CB_SETEDITSEL32
:
1586 if( lphc
->wState
& CBF_EDIT
)
1587 return SendMessage32A( lphc
->hWndEdit
, EM_SETSEL32
,
1588 (INT32
)(INT16
)LOWORD(lParam
), (INT32
)(INT16
)HIWORD(lParam
) );
1591 case CB_SETEXTENDEDUI16
:
1592 case CB_SETEXTENDEDUI32
:
1593 if( CB_GETTYPE(lphc
) == CBS_SIMPLE
) return CB_ERR
;
1596 lphc
->wState
|= CBF_EUI
;
1597 else lphc
->wState
&= ~CBF_EUI
;
1600 case CB_GETEXTENDEDUI16
:
1601 case CB_GETEXTENDEDUI32
:
1602 return (lphc
->wState
& CBF_EUI
) ? TRUE
: FALSE
;
1604 case (WM_USER
+ 0x1B):
1605 WARN(combo
, "[%04x]: undocumented msg!\n", hwnd
);
1607 return DefWindowProc32A(hwnd
, message
, wParam
, lParam
);